
PetZone — animal-help platform · 2025
A pet-adoption platform that search engines can actually read
A full-stack adoption platform: .NET clean-architecture backend, a React SPA in 6 languages, and a prerender pipeline so a single-page app still ranks in Google.
An SPA that search engines can finally crawl — server-readable adoption pages in 6 languages
The problem
PetZone helps animals find homes — but adoption only happens if people can find the listings. The app was built as a client-rendered React single-page app, which is great for UX and terrible for SEO: search-engine crawlers were served an empty HTML shell, so adoptable-pet pages barely ranked. On top of that the audience is multilingual (the platform ships in 6 languages), which multiplies the SEO surface and the chance of getting it wrong.
My approach
I treated it as two separate problems — a solid backend, and discoverability on top of an SPA — and shipped them in slices:
- A clean-architecture .NET backend split into Domain, Use Cases, Infrastructure, Contracts and API layers, with a dedicated notification microservice. Domain and integration test suites so behaviour is pinned down, not hoped for.
- SEO landing pages — species-level pages (dogs, cats, …) and richer pet DTOs (species/breed names) so each listing has real, indexable content instead of an ID.
- A prerender pipeline — a build step that renders the key routes to static HTML and generates sitemaps, so crawlers get fully-formed pages while users still get the fast SPA.
Stack & why
- Clean architecture in .NET — the domain (animals, listings, volunteers) has real rules; isolating it from infrastructure kept those rules testable and the API thin.
- React + Vite SPA with i18next — fast, app-like UX across 6 locales without a heavyweight framework.
- Prerender + sitemaps instead of a full SSR rewrite — got the SEO benefit without throwing away the working SPA or doubling the hosting complexity. The pragmatic choice beat the "correct" one.
- In-memory caching over Redis — removed an entire piece of infrastructure once profiling showed an external cache wasn't paying for itself at this scale.
The result
- Adoptable-pet and species pages are now server-readable in all supported languages — crawlers see content, not an empty shell.
- The backend has test coverage at the domain and integration level, so changes ship with confidence.
- Infrastructure got simpler over time (Redis removed), not more complex.
What was hard
SEO on a client-rendered SPA is the classic trap: the "real" fix is a full server-side-rendering rewrite, which here would have meant months and a riskier deploy. The hard part was resisting that and instead building a prerender step that gives crawlers static HTML per route per language without forking the codebase into "SSR mode" and "SPA mode." Getting the multilingual sitemaps and canonical URLs right was the fiddly part — get it wrong and Google sees six copies of the same page.
Related work

A portfolio site that books clients for a hair colorist
2026Zvezdochka — hair-coloring studio, Odessa
An image-heavy, multilingual portfolio and booking site for a professional colorist — fast galleries served from object storage, reviews, courses, and direct booking channels.
An owned, multilingual home that turns Instagram traffic into bookings

A product catalog that turns visitors into quote requests
2026SunCold — containers & solar equipment supplier
A multilingual B2B catalog and lead-gen site for a container and solar-energy supplier — fast product pages, a quote-request flow, and SEO content (blog/FAQ) to pull in buyers.
A self-serve catalog and quote funnel that earns its own search traffic
Want something similar built?
I take on a small number of projects at a time. If this looks like your problem, let's talk.