Astro 7 ยท Next.js 16
In progress
OilCraft, Subscription Content Platform
A static content tier and a paid subscription app, on the Cloudflare free tier
Astro content site builds clean at 19 routes, 0 vulnerabilities; paid tier wired
Overview
A content and AI platform for essential-oil and carrier-oil blends. Recipes are ratio-based and scale to 100 ml, 250 ml and 500 ml bottles. Three tiers: a free ad- and affiliate-supported content site, a paid custom-blend builder, and a premium AI-personalised tier.
Two properties built in sequence rather than one app with feature flags. The free tier is a static Astro site with typed content collections, JSON-LD and a sitemap, which ships first and captures a waitlist. The app is Next.js, with accounts, an interactive recipe library and bottle calculator, and AI chat behind the premium tier. Both run on Cloudflare with 0 dependency vulnerabilities.
The paid tier is end to end: Razorpay checkout with server-computed amounts, an idempotent webhook as the authoritative fulfilment path, and automatic Zitadel role grants that reach the next minted JWT. Amounts are computed server-side because a client-supplied price is a client-controlled price.
Stack
- Content site
- Astro 7 + Tailwind v4, static, 19 routes
- Application
- Next.js 16 + React 19
- Auth
- Zitadel, roles granted on fulfilment
- Payments
- Razorpay, idempotent webhook fulfilment
- Data
- PostgreSQL, R2, KV
- Hosting
- Cloudflare Pages and Workers
Decisions Worth Explaining
The webhook is the authoritative fulfilment path
A browser redirect after checkout is not a payment confirmation: the tab can close. The webhook is the only thing that grants entitlement, and it is idempotent because payment providers retry.
Amounts computed server-side
A price sent from the client is a price the client controls. The server derives the amount from the plan id.
Two properties, not one
The indexable content and the authenticated app have opposite requirements. Everything behind login is deliberately not indexed.
What Is Not Done
- The brand name is still a planning placeholder; the domain has not been registered.
- The premium AI tier is designed but not implemented.
- No logo or favicon yet.