A web encyclopedia of cat breeds. Search more than 100 breeds, read about their temperament, origin and history, browse photos and keep a personal list of favourites.
Live demo · Getting started · API reference
Cat Wiki is a full-stack JavaScript application built for the devChallenges.io Cat Wiki challenge. It has two parts:
- Client: a React single-page application that renders the user interface.
- Server: a small Express API that proxies TheCatAPI. It keeps the API key on the server, caches responses and returns consistent error messages.
- Breed search: an autocomplete search box on the home page. It matches breed names and alternative names, and works with the keyboard (arrow keys, Enter, Escape).
- Breed catalogue: the full list of breeds, with a name filter that is stored in the URL so a filtered list can be shared or bookmarked.
- Breed details: description, temperament, origin, life span, weight, height, breed group, history and a gallery of photos.
- Favourites: save breeds from any page. Favourites are kept in
localStorageand stay in sync across open tabs. - Light and dark themes: the app follows the system preference by default, remembers the user's choice and applies it before the first paint, so the page never flashes the wrong theme.
- Responsive and accessible: the layout is mobile-first and uses semantic markup, ARIA combobox and switch roles, visible focus states and labelled controls.
- Resilient data loading: React Query shares and caches data across pages. The app shows skeleton loaders, an error state with a retry button, a 404 page and a placeholder for breeds that have no photo.
| Search | Breed catalogue |
|---|---|
![]() |
![]() |
| Breed details | Favourites (dark theme) |
|---|---|
![]() |
![]() |
| Layer | Technologies |
|---|---|
| Client | React 18, React Router 6, TanStack Query 5, Tailwind CSS 3, Vite 6, Axios, React Icons |
| Server | Node.js, Express 4, Axios, CORS, dotenv |
| Tooling | ESLint 9 (flat config) with React and React Hooks rules |
| Hosting | Vercel (static client and serverless API) |
CatWiki/
├── client/ React single-page application
│ ├── index.html
│ ├── vite.config.js Dev server and /api proxy
│ ├── tailwind.config.js
│ └── src/
│ ├── api/ Axios client for the Cat Wiki API
│ ├── components/ Shared UI (layout, header, cards, states)
│ ├── context/ Theme and favourites providers
│ ├── hooks/ Data-fetching and utility hooks
│ ├── pages/ Main, Breeds, Details, Favourites, NotFound
│ └── utils/ Search, storage and helper functions
├── server/ Express API proxy for TheCatAPI
│ ├── api/index.js Vercel serverless entry point
│ └── src/
│ ├── app.js Express app (middleware and routes)
│ ├── server.js Local HTTP server
│ ├── config.js Environment configuration
│ ├── controllers/ Request handlers and validation
│ ├── middleware/ 404 and error handling
│ ├── routes/
│ ├── services/ TheCatAPI client with in-memory cache
│ └── utils/
└── previews/ Screenshots used in this README
- Node.js 18 or later and npm
- A free API key from TheCatAPI. The API also works without a key, but it applies stricter rate limits and returns fewer images.
git clone https://github.com/oiibar/CatWiki.git
cd CatWikicd server
npm install
cp .env.example .env # then set CAT_API_KEY in .env
npm run devThe API runs at http://localhost:5000. You can check that it is up at http://localhost:5000/api/health.
Open a second terminal:
cd client
npm install
npm run devOpen http://localhost:5173 in your browser. In development, the Vite dev server forwards every /api request to the local server, so the client needs no extra configuration.
| Variable | Default | Description |
|---|---|---|
CAT_API_KEY |
none | Your TheCatAPI key. |
PORT |
5000 |
Port of the local server. |
CORS_ORIGINS |
empty (all origins) | Comma-separated list of client origins allowed to call the API. |
CACHE_TTL_MS |
3600000 |
How long TheCatAPI responses stay in the in-memory cache, in milliseconds. |
CAT_API_URL |
https://api.thecatapi.com/v1 |
Base URL of TheCatAPI. |
| Variable | Default | Description |
|---|---|---|
VITE_API_URL |
/api |
Base URL of the Cat Wiki API. The production value is set in client/.env.production. |
API_PROXY_TARGET |
http://localhost:5000 |
Development only: where the Vite dev server forwards /api requests. Change it if the server runs on another port. |
| Location | Command | Description |
|---|---|---|
server/ |
npm run dev |
Starts the API and restarts it when files change (node --watch). |
server/ |
npm start |
Starts the API. |
client/ |
npm run dev |
Starts the Vite development server. |
client/ |
npm run build |
Builds the production bundle into client/dist. |
client/ |
npm run preview |
Serves the production build locally. |
client/ |
npm run lint |
Runs ESLint. |
All endpoints accept GET requests and return JSON. Errors use the format { "error": "message" }.
| Endpoint | Description |
|---|---|
/api/health |
Health check. Returns { "status": "ok" }. |
/api/breeds |
Lists all breeds. |
/api/breeds/:id |
Returns one breed by its TheCatAPI id, for example beng. |
/api/breeds/:id/images?limit=8 |
Returns photos of a breed. limit must be between 1 and 25 and defaults to 8. |
| Status | Meaning |
|---|---|
400 |
The breed id is not valid. |
404 |
The breed or route does not exist. |
502 |
TheCatAPI could not be reached. |
503 |
TheCatAPI rate limit was reached. |
The client and the server are deployed to Vercel as two separate projects.
- Server: create a Vercel project with
server/as the root directory.vercel.jsonsends every request to the Express app inapi/index.js. SetCAT_API_KEY, and setCORS_ORIGINSto the client URL. - Client: create a Vercel project with
client/as the root directory. Vercel detects Vite automatically. SetVITE_API_URLto the server URL followed by/api, or editclient/.env.production.vercel.jsonsends every route toindex.html, so links to client-side routes such as/details/bengwork when opened directly.
- Design challenge by devChallenges.io.
- Breed data and photos from TheCatAPI.
Built by Aibar. You can reach me through contact-me-neon.vercel.app.





