- Frontend
- Next.js 15 + React 19 with the App Router. Tailwind v4 for the styling layer. Server components where data lives server-side; client islands for the canvas, the upload flow, and the wizard. Shared component library across the web app, the wizard, and the extension build.
- API: Hono inside Next.js
- All API endpoints are served by a single Hono application mounted at `app/api/[...route]/route.ts`. Routes organized by domain — auth, payments, credits, users, products, images, style-prompts. CORS, per-route rate limiting (100 req/min/IP), secure headers, and a unified error middleware live in one place. One deploy artifact, one runtime to operate.
- Data layer
- Postgres on Neon with Drizzle ORM. The `credit_ledger` table is immutable — entries are appended, never updated. The user's `current_credits` is a derived cache. Style prompts, product categories, generation history, and image metadata all live in typed Drizzle schemas with Zod validation at the API boundary.
- Auth + identity
- Supabase Auth handles GitHub and Google OAuth. We use three client variants — client-side, server-side (with cookies), and admin — split into separate modules so the wrong client never ends up in the wrong place. JWTs verified server-side on every protected endpoint.
- AI pipeline
- Google Gemini 2.5 Flash Image as the generation model. The prompt-engineering layer runs server-side: category detection, style application, negative-prompt assembly. Generated images are streamed back to the client and persisted in Cloudinary with WebP auto-optimization for delivery.
- Webhooks + billing
- Dodo Payments handles credit purchases. The webhook handler is a Deno Edge Function in Supabase that verifies signatures using `standardwebhooks`, then upserts to the `payments` table and inserts a credit-purchase entry into the ledger. Idempotency comes for free from the unique constraint on the external-reference column.