A direct-to-consumer (B2C) pet e-commerce platform β built mobile-first, USA-first, multi-country by design.
PetGo is a full-stack direct-to-consumer (B2C) pet e-commerce app β food, toys, accessories and health products, sold straight to pet owners. The codebase is a portfolio + learning project, but the architecture is wired for real-world expansion: electronic tax docs, payment gateways and additional countries are all stubbed out behind feature flags rather than hard-coded out.
The storefront targets the USA as the launch country, with the data model and pricing rules already shaped to onboard Colombia and PerΓΊ without refactoring (currency, tax rate, locale and shipping zone are all per-country fields on the schema).
Note β The source code lives in a private repository. This repo exists as the public showcase.
π petgo-store.click
| Layer | Choices |
|---|---|
| Storefront | Next.js 15 App Router Β· React 19 Β· Turbopack Β· Apollo Client v4 Β· Serwist (PWA) Β· Tailwind v4 Β· next-themes Β· next-intl |
| API | Bun runtime Β· Hono Β· GraphQL Yoga Β· better-auth (email + OTP) Β· Drizzle ORM Β· DataLoader |
| Database | PostgreSQL (Neon free-tier in prod) |
| Resend (transactional auth OTPs) | |
| Tooling | Bun workspaces Β· Turborepo Β· Biome Β· GraphQL Code Generator (client-preset) |
- π Bilingual EN / ES via
next-intl, locale-prefixed routes (/en/.../es/...) - π Dark mode with tuned brand palette per theme β not a default Tailwind invert
- π± Mobile-first with dedicated desktop layouts (not just responsive β different chrome on every breakpoint)
- π² PWA-ready via Serwist (installable, offline fallback page)
- πΎ Active-pet awareness β products with proteins the user's pet is allergic to are filtered out automatically across home, search, category, shop and brand surfaces
- π Guest cart via cryptographically-random session tokens, auto-claims into the user's account on sign-in
- β‘ Apollo Client v4 + RSC with
PreloadQueryfor SSR-streamed product data β no skeleton flash on the first paint of the home page
- π§± Strongly-typed GraphQL schema generated end-to-end with
graphql-codegen(client preset + fragment masking) - βοΈ Hexagonal-ish architecture β every feature has its own
service(business logic),repository(Drizzle queries) andresolvers(GraphQL plumbing) with thin handoffs in each direction - π Auth via
better-authβ email + password, password-reset OTP, bearer tokens (cookie-less by design, CORS-friendly) - π¨ Resend integration β graceful fallback to stdout-log when
RESEND_API_KEYisn't set so local dev and CI never need a live mail provider - π Hand-rolled DataLoader registry β per-request loaders for catalog joins (variants, images, reviews aggregate) keep N+1 queries off the wire
- 113+ unit tests across 13 service-layer suites (
bun:test) - Money-touching code (cart totals, coupons, tax documents, order placement) is exercised end-to-end with happy + error paths
- IDOR-style ownership checks tested explicitly β a foreign user-id surfaces as
NotFoundError, never silently writes
- Storefront auto-deploys from
mainto Vercel on every push - API runs from a tracked Dockerfile (multi-stage Bun + Alpine, ~150MB), pushed to GCP Artifact Registry and deployed to a Compute Engine e2-micro VM
- DNS managed in AWS Route 53 β apex domain on Vercel,
api.*subdomain on the VM - Vercel Analytics + Speed Insights wired for Core Web Vitals
Built by Miriam AcuΓ±a β software engineer shipping side projects to explore the parts of the stack day-job tickets don't always touch.