
April 21, 2026
Pepanimal
A full-stack, multilingual (ES/EN/FR/PT) platform for responsible dog and cat adoption. It connects shelters with adopters and digitizes the whole process — from publishing an animal to selecting the final adopter — with a public catalog, a shelter management dashboard, integrated chat and notifications.
Built solo, end to end: architecture, frontend, backend, database, component library and infrastructure.
Contents
The problem
Animal adoption is usually handled in a scattered, informal way: one-off posts on social media, conversations over WhatsApp or Instagram, spreadsheets, and no structured tracking of requests. This creates two concrete pain points:
- For shelters: it's hard to give their animals visibility, receive requests in an orderly way, evaluate candidates properly, coordinate the team (several volunteers and staff) and track the status of each adoption. Information lives spread across several tools.
- For adopters: there is no central place to browse animals from different shelters, each animal's information is incomplete, and the request process is opaque — they don't know the status of their request or how to talk to the shelter.
The solution
Pepanimal centralizes and digitizes the entire adoption flow in a single platform:
- A public catalog where anyone can browse dogs and cats up for adoption, with detailed profiles (temperament, compatibility with other pets and children, health status, location and responsible shelter).
- A shelter management dashboard to register animals with photos and video, publish adoptions, manage the team via roles and invitations, and coordinate foster homes.
- A structured request flow: the adopter fills in a pre-adoption questionnaire and submits the request; the shelter reviews it on a board with statuses (Under review → In progress → Validated / Discarded), adds internal comments, chats with the candidate and finally selects the definitive adopter.
- A notification system that keeps the adopter informed on every status change and when they are picked as the final candidate.
The result is a transparent, traceable process with built-in communication, with no reliance on external tools.
![]()
Key features
- Multilingual public catalog of animals by species, with sorting and filters
(breed, size, location) and slug-localized routes (
/animals/perrosin ES,/animals/dogsin EN). - Detailed animal profile: image and video gallery, temperament (energy and independence levels, compatibility with cats/dogs/children/people), health status (vaccinated, dewormed, neutered, special medical condition) and shelter details.
- Authentication with email/password and Google OAuth (Better Auth).
- Shelter dashboard with metrics (available animals, in foster care, adoptions this month, average time in the shelter) and charts.
- Animal management: create, edit, upload images and video, assign caretakers and foster homes.
- Kanban board of adoption requests with statuses, internal team comments and final candidate selection.
- Integrated chat between shelter and adopter, tied to each request.
- Configurable pre-adoption questionnaire with multilingual questions.
- Shelter team management: email invitations with roles (ADMIN / WORKER).
- Foster homes: register and assign animals to temporary homes.
- Content blog about adoption and pet care (52 articles in each of the 4 languages), rendered with MDX.
- Technical SEO: dynamic metadata, JSON-LD structured data, dynamic sitemap and robots, and multilingual hreflang.
- AI image moderation: every uploaded photo is analyzed with OpenAI's moderation API to block disallowed content.
![]()
![]()
![]()
Tech stack
A monorepo using npm workspaces (apps/*, packages/*), Node ≥ 24, deployed on
Vercel with a separate project per app and per-folder conditional builds.
Frontend (apps/web) — Next.js 16 (App Router) · React 19 · TypeScript · Tailwind
CSS 4 · TanStack Query · Zustand · react-hook-form + Zod · next-intl (4 languages) ·
Better Auth · MDX for the blog · FFmpeg (WASM) for in-browser video compression.
Backend (apps/api) — Hono on Node · 4-layer clean architecture
(domain → application → infra → presentation) · InversifyJS (dependency injection) ·
Prisma 7 · Better Auth (email + Google OAuth) · Zod · OpenAI (image moderation) ·
sharp (WebP optimization) · Nodemailer + React Email · AWS SDK S3 · Pino.
Database — PostgreSQL with Prisma (~25 models), Neon (serverless) in production.
A data-level translation system via a Multilang model that stores all four
language variants.
Component library (packages/react-ui) — a local library with Vite + Storybook,
Atomic Design architecture, Recharts for the charts and drag & drop for the kanban board.
Technical challenges
True data-level multilingualism, not just UI. i18n isn't limited to interface text
(handled with next-intl): the domain's dynamic content — breeds, countries, provinces
and questionnaire questions — also exists in all four languages. This was solved with a
Multilang model in the database that translatable entities point to, so switching
languages returns consistent data across the whole app. Routes are even slug-localized.
Client- and server-side media pipeline. Shelters upload heavy photos (often iPhone HEIC) and videos from mobile. A two-stage pipeline was built: on the client, HEIC conversion, image compression and video compression with FFmpeg compiled to WASM before uploading; on the server, re-optimization with sharp (rescaling and WebP re-encoding). Each image also goes through OpenAI AI moderation before being published.
Clean-architecture API with dependency injection. The backend is organized into
domain modules (animal, adoption, shelter, chat…), each with its own layers and a
strict dependency flow. Repositories are defined as abstract contracts injected with
InversifyJS, so business logic never touches Prisma. Layer boundaries are enforced
with file-scoped lint rules.
Monorepo with a shared UI library and independent deployments. Two apps (web,
api) and a locally consumed component library. Each app deploys separately on Vercel
without rebuilding everything on each push, using Ignored Build Steps based on per-folder
git diff and custom vercel.json files.
![]()
![]()
My role
Built solo (full-stack) over ~5 months. End-to-end work: monorepo architecture, frontend (Next.js), backend (Hono with clean architecture + DI), component library with Storybook, data modeling with Prisma and the translation system, integrations (Better Auth with Google OAuth, OpenAI, S3 storage, transactional email), technical SEO, i18n in 4 languages, blog and deployment and quality tooling setup.
Links
- Live site: pepanimal.com
- API: backend.pepanimal.com