Status: Approved in brainstorming session 2026-07-07
Owner: vikas (human) — executes by dispatching AI per mini-plan using superpowers
Repo: pink-pulsar — Astro 7 + @astrojs/cloudflare adapter on Cloudflare Workers
Purpose: A plan-of-plans for a production-grade end-to-end e-commerce website. Each mini-plan is one PR-sized, AI-implementable, fully-tested increment. The plan-of-plans itself is for human use only — the AI does not execute it; it executes one mini-plan at a time on demand.
| Dimension | Decision |
|---|---|
| Products | Physical goods, small catalog (~5 products) |
| Market | India (INR, English only for v1) |
| Goal | Full ownership, no platform fees |
| Payments | Razorpay (UPI, cards, netbanking, COD) |
| Customer auth | Guest checkout only — no accounts in v1 |
| Fulfillment | Manual packing + flat-rate shipping |
| Notifications | Email now; WhatsApp deferred to future/ |
| Order states | Minimal: placed → paid → shipped → delivered (+ cancelled); extensible for provider statuses later |
| Admin | Basic admin in this repo now; full admin panel deferred to future/ |
| Compliance | Legal pages now (Privacy, Terms, Returns, Shipping, Contact/About). GST tax handling, GST invoices, DPDP consent deferred to future/. |
| Marketing | Discounts/coupons now. Abandoned cart deferred to future/. Analytics events & funnel now. |
- Storefront pages (home, catalog, product detail, legal) prerendered at build (SSG) via Astro. Pure HTML + minimal islands.
- Only dynamic server-rendered routes:
/cart,/checkout,/checkout/success,/admin/orders/*,/orders/[token]. - Lighthouse CI in GH Actions gates every PR: block merge if any category < 90, warn if < 100.
- Zero render-blocking JS/CSS. Astro's minimal island runtime shipped only where interactivity is genuinely needed.
- Long-cache headers for static assets; short cache for HTML.
- MP-13 closes the loop: image variants, cache headers, critical-CSS inlining, font subsetting, RUM budget assertions.
- Full
<head>meta (title, description, canonical, robots, OpenGraph, Twitter cards) via a base component in MP-0a. - JSON-LD:
Product,Offer,BreadcrumbList,Organization,WebSite. @astrojs/sitemapintegration forsitemap.xmlindex (MP-12).- Static
public/robots.txt. - OG-image route per product (MP-12).
hreflangstub set up now (IN only for v1) — extends cleanly when multi-language is added later.- Custom 404/500 pages (MP-9).
- Cloudflare automatic DDoS + managed WAF rules cover volumetric threats (zero setup).
- Workers Rate Limiting binding wired in MP-0d; used per-feature.
- Security headers (CSP, HSTS, X-Frame-Options, Referrer-Policy, Permissions-Policy) in MP-0d middleware.
- Cloudflare Turnstile on admin login (MP-7).
- Astro Actions built-in CSRF protection — verified in MP-0a, used by every Action MP.
astro:schema(theastro/zodmodule) for input validation on every Action — native, no standalone Zod.- Razorpay signature verification on every webhook (MP-5).
- Hashed shared secret in KV + httpOnly secure cookie for admin auth (MP-7).
- HMAC-signed tokens via Web Crypto for guest order-status links (MP-8).
- Wrangler secret store for all secrets;
.dev.varsfor local (MP-0c). - MP-14 (security audit) tunes thresholds, tightens CSP, reviews WAF rules, audits dependencies, walks through threats with real traffic data.
- Workers Observability (already enabled in
wrangler.jsonc) for server-side error tracking. - Workers Analytics Engine for product analytics events via a first-party
/rumbeacon endpoint (~50 lines, MP-0d). - Zero client-side analytics SDK — preserves Lighthouse 100.
- Sentry / PostHog / session replay deferred to
future/as lazy-load mini-plans.
Three-tier server delivery, all native Astro, zero extra routers:
- Astro prerendered (SSG) — storefront: home, catalog list, product detail, legal pages, 404/500, sitemap, robots. Pure HTML + minimal islands. This is the Lighthouse 100 path.
- Astro Actions (
src/actions/) — type-safe RPC for every app-internal mutation:cart/add,cart/update,cart/remove,cart/clearcheckout/createOrder,checkout/captureadmin/login,admin/updateOrderStatus,admin/assignTrackingorders/getStatus(for the guest order-status page)- End-to-end type safety from UI → service via
astro:schemafor input/output schemas.
- Astro API routes — exactly one:
/api/webhooks/razorpay.ts(raw external webhook needing signature verification + custom body parsing). That's the API-route exception; everything else is an Action. - Dynamic server-rendered routes (opted out of prerender via
export const prerender = false):/cart,/checkout,/checkout/success,/admin/orders/*,/orders/[token]. Render vialoader+ call Actions from client islands.
Hybrid output: output: 'static' (Astro 7 default) with prerender = false only on the dynamic routes above. Storefront build is SSG; dynamic routes are on-demand SSR via the Cloudflare Worker; Actions run on the Worker.
Astro uses file-based routing in src/pages/, native Actions in src/actions/, native middleware in src/middleware.ts, and has existing src/components/, src/layouts/, src/assets/. We extend these — not replace them. Cross-cutting code lives in src/lib/; feature business logic (non-routing) lives in src/features/.
src/
pages/ # Astro file-based routing — ALL pages live here (existing)
index.astro # home (prerendered)
products/ # catalog (prerendered)
index.astro # product list
[slug].astro # product detail
cart.astro # cart page (dynamic)
checkout/ # checkout flow (dynamic)
index.astro # address + shipping step
review.astro # review + pay step
success.astro # order confirmed
orders/ # guest order status (dynamic)
[token].astro
admin/ # basic admin (dynamic, auth-gated)
login.astro
orders/
index.astro
[id].astro
coupons/ # MP-10 discounts admin
index.astro
api/ # the ONE api route folder
webhooks/
razorpay.ts
privacy.astro # legal pages (prerendered)
terms.astro
returns.astro
shipping.astro
contact.astro
about.astro
health.astro # health check
rum.ts # analytics beacon endpoint
404.astro
500.astro
actions/ # Astro Actions — native location (RPC entry points)
cart.ts # thin: parse → service → return
checkout.ts
admin.ts
orders.ts
components/ # Astro components — existing, extended
ui/ # Astro-native shadcn base components (Button, Input, Card, ...)
cart/ # cart-specific components (CartSlideover, CartBadge)
checkout/ # checkout-specific components
admin/ # admin-specific components
seo/ # SEO components (MetaHead, JsonLd)
layouts/ # Astro layouts — existing
Layout.astro # base layout with <head>, tokens, font optimization
assets/ # Astro assets — existing (astro:assets)
styles/ # Global styles, Tailwind v4 entry, design tokens (CSS variables)
content/ # Astro content collections (if legal pages migrate to markdown later)
middleware.ts # Native Astro middleware — security headers, request-id, logger, admin auth guard
env.d.ts # Astro env type definitions
lib/ # Cross-cutting code — NOT Astro routing
core/ # framework-agnostic, pure-TS, fully unit-tested
env.ts # typed binding accessor (D1, R2, KV, Analytics Engine, secrets)
logger.ts # structured logging + request id (Workers Logs adapter)
errors.ts # error taxonomy (UserError, ServerError, PaymentError, ...)
auth.ts # HMAC token sign/verify, admin session helpers
rate-limit.ts # Workers Rate Limiting binding helpers
db/ # Drizzle ORM
schema/ # schema definitions (split by feature: catalog.ts, orders.ts, coupons.ts)
migrations/ # Drizzle migrations
client.ts # Drizzle client factory
bindings/ # provider adapters (concrete impls) + interface types
payment/ # types.ts (PaymentProvider) + razorpay.ts (RazorpayAdapter)
email/ # types.ts (EmailSender) + smtp.ts
images/ # types.ts (ImageRepository) + r2.ts
cart/ # types.ts (CartRepository) + kv.ts
analytics/ # types.ts (AnalyticsSink) + analytics-engine.ts
logger/ # types.ts (Logger) + workers-logs.ts
app/ # composition root — the ONLY place concrete adapters are imported
prod.ts # wires real adapters → services
test.ts # wires fakes → services
features/ # Feature slices — business logic only (NO routing, NO .astro pages)
catalog/ # MP-1, MP-2
service.ts repository.ts types.ts tests/
cart/ # MP-3, MP-4
service.ts repository.ts types.ts tests/
checkout/ # MP-5, MP-6a, MP-6b
service.ts repository.ts types.ts tests/
orders/ # MP-7, MP-8
service.ts repository.ts types.ts tests/
admin/ # MP-7 admin business logic
service.ts types.ts tests/
seo/ # MP-12 (JSON-LD helpers, OG-image gen helpers)
jsonld.ts og-image.ts tests/
legal/ # MP-9 (legal page content/metadata)
content.ts tests/
public/
robots.txt # static file (MP-12)
Key differences from a non-Astro project:
- Pages live in
src/pages/(file-based routing) — NOT insidesrc/features/*/pages/. Pages are thin: they call services and render. - Components live in
src/components/(Astro convention) organized by feature subfolder — NOT insidesrc/features/*/components/. - Actions live in
src/actions/(native Astro location). - Middleware lives in
src/middleware.ts(native Astro middleware) — replaces the customwithMiddleware()helper. - Feature slices in
src/features/contain ONLY non-routing business logic:service.ts,repository.ts,types.ts,tests/.
| Concern | Interface | Default impl | Swap target |
|---|---|---|---|
| Database | *Repository per feature |
Drizzle + D1 | Postgres, Turso, Mongo — replace that slice's repository only |
| Payments | PaymentProvider |
RazorpayAdapter |
Stripe, PayPal — new file in bindings/, wire in app/prod.ts |
EmailSender |
SmtpAdapter (Cloudflare Email Service) |
SES, Postmark, Resend — swap adapter only | |
| Object storage | ImageRepository |
R2Adapter |
S3, Cloudinary — swap adapter only |
| Cart store | CartRepository |
KVAdapter |
D1, Redis (Upstash) — swap adapter only |
| Analytics | AnalyticsSink |
AnalyticsEngineAdapter |
PostHog, Rudderstack — swap adapter only |
| Logger | Logger |
WorkersLogsAdapter |
Sentry, Datadog — swap adapter only |
Composition root: src/lib/app/prod.ts wires real adapters; src/lib/app/test.ts wires fakes. Services take interfaces as constructor args — never import an adapter directly. Tests pass fakes, prod passes the real adapter. To swap payments: write StripeAdapter.ts in src/lib/bindings/payment/, change one line in src/lib/app/prod.ts, done. Zero churn in any feature slice.
Services take adapters as constructor args:
// src/lib/bindings/payment/types.ts
export interface PaymentProvider {
createOrder(opts: CreateOrderOpts): Promise<{ orderId: string }>;
verifySignature(opts: VerifyOpts): Promise<boolean>;
refund(orderId: string, amount: number): Promise<RefundResult>;
}
// src/features/checkout/service.ts
export class CheckoutService {
constructor(private deps: { payment: PaymentProvider; orders: OrderRepository; email: EmailSender }) {}
async createOrder(input: CreateOrderInput) { /* uses this.deps.payment */ }
}
// src/lib/app/prod.ts — the only place that knows about real adapters
export const checkout = new CheckoutService({
payment: new RazorpayAdapter(env.RAZORPAY_KEY, env.RAZORPAY_SECRET),
orders: new DrizzleOrderRepository(env.DB),
email: new SmtpAdapter(env.SMTP_URL),
});
// src/actions/checkout.ts — thin
import { checkout } from '~/lib/app/prod';
export const createOrder = defineAction({ handler: async (input) => checkout.createOrder(input) });Why no DI framework: ~6 services and ~8 adapters — a single app/prod.ts file of ~30 lines wires the whole graph. A framework would add magic + bundle weight for zero benefit at this scale.
src/actions/*→ may importsrc/features/*/service+src/lib/core/*onlysrc/features/*/service.ts→ may importsrc/features/*/repository(interfaces) +src/lib/bindings/*/types(interfaces only, never concrete adapters) +src/lib/db/schemas +src/lib/core/*src/lib/bindings/*+src/lib/db/*→ only place that touches Cloudflare bindings / vendor SDKs / Drizzle- No
src/features/Amay importsrc/features/Binternals src/lib/app/prod.ts+src/lib/app/test.tsare the ONLY files allowed to import concrete adapterssrc/pages/*→ may importsrc/features/*/service+src/components/*+src/layouts/*only (pages are thin)
Enabled in MP-0a. strict: true, noUncheckedIndexedAccess: true, exactOptionalPropertyTypes: true. No any without explicit eslint-disable comment explaining why.
Before implementing any mini-plan, the AI must web-search the relevant Astro and Cloudflare docs to confirm whether a native integration exists before reaching for any external dependency.
Decisions locked under this principle:
| Concern | Native choice | Notes |
|---|---|---|
| API/RPC | Astro Actions (src/actions/) |
Native |
| Webhook route | Astro API route (src/pages/api/) |
One exception for Razorpay |
| Middleware | Astro native middleware (src/middleware.ts) |
Native — replaces custom withMiddleware() |
| Input validation | astro:schema (astro/zod module) |
Native, not standalone Zod |
| Fonts | Astro experimental native font optimization | MP-0a |
| Images (build-time) | Astro <Image> + astro:assets |
MP-1, MP-2, MP-14 |
| Images (post-build/admin upload) | R2 + Cloudflare Image Resizing | Adapter pattern |
| Sitemap | @astrojs/sitemap integration |
MP-12 |
| Robots.txt | Static public/robots.txt file |
MP-12 |
| Testing | astro test (uses Vitest under the hood) |
Native |
| Content (if blog ever added) | astro:content collections + @astrojs/mdx |
Future |
| Rate limiting | Workers Rate Limiting binding | Platform-native |
| Analytics | Workers Analytics Engine | Platform-native |
| Error tracking | Workers Observability | Platform-native |
| Cloudflare Email Service | Platform-native |
External deps kept (no native alternative exists):
- Tailwind v4 — CSS tool, zero JS shipped, explicitly requested + needed for shadcn token system
- Drizzle ORM — thinnest D1-compatible ORM, compile-time queries, no runtime weight
- Astro-native shadcn port — UI components built on the shadcn CSS-variable token system
- Tailwind v4 for styling — CSS-native config, zero runtime JS.
- Astro-native shadcn port — port shadcn components as native Astro components using the same CSS-variable token system (the shadcn token system is CSS-only, framework-agnostic). Same look/feel as shadcn proper.
- React islands only where genuinely interactive — cart slide-over (MP-3), Razorpay checkout flow (MP-6b), admin order management (MP-7). Everything else is pure Astro HTML — preserves Lighthouse 100.
- Design tokens defined once in MP-0a (CSS variables: colors, spacing, typography, radii, shadows) and consumed by both Astro components and any React islands.
| Binding | Purpose | Wired in |
|---|---|---|
D1 (DB) |
Products, variants, product images metadata, orders, order items, discounts, coupons | MP-0b (binding), MP-1 (first tables), MP-6a (orders), MP-10 (discounts) |
KV (CART) |
Cart state, admin session, rate-limit counters | MP-0b (binding), MP-3 (cart), MP-7 (admin session) |
R2 (IMAGES) |
Product images (admin-uploaded), generated invoices | MP-0b (binding), MP-1 (read), MP-7 (admin upload if added) |
Analytics Engine (ANALYTICS) |
Product events (page_view → purchase funnel) | MP-0d (binding + beacon), MP-11 (instrumentation) |
Drizzle ORM for D1 — thin, compile-time, D1-compatible. Schema in src/lib/db/schema/ (split by feature). Migrations in src/lib/db/migrations/. Client factory in src/lib/db/client.ts. Repository pattern: each feature defines its *Repository interface in src/features/*/repository.ts and a Drizzle implementation; tests use an in-memory fake.
Each mini-plan is:
- One PR-sized chunk — small enough for thorough human code review
- One capability end-to-end (where reasonable)
- Fully tested (Vitest unit + integration;
astro testnative runner) - Lighthouse CI green (block < 90, warn < 100)
- Preview deploy verified on Cloudflare before merge
- Implemented by AI on demand using superpowers; the plan-of-plans is for human use only
Mini-plans are grouped into folders by sub-system so you navigate one area at a time.
- tsconfig paths, strict mode,
noUncheckedIndexedAccess,exactOptionalPropertyTypes - Tailwind v4 setup (CSS-native config) in
src/styles/ - Astro experimental native font optimization
- Astro-native shadcn base components in
src/components/ui/(Button, Input, Card, etc.) + shared CSS-variable design tokens - Base SEO
<head>component insrc/components/seo/MetaHead.astro(title, description, canonical, OG, Twitter cards) - Base responsive image component scaffold (Astro
<Image>+astro:assets) - ESLint with
no-restricted-importsrules from §3.5; Prettier - Vitest via
astro test src/layouts/Layout.astrowith head + token-driven styles + font optimization.dev.varsskeleton for local secrets- Tests: repo boots, layout renders, lint passes, base components render.
- Pages touched:
src/layouts/Layout.astroonly.
- D1 binding in
wrangler.jsonc+ Drizzle migration infra insrc/lib/db/(no tables yet) - R2 binding +
ImageRepositoryinterface insrc/lib/bindings/images/ - KV binding +
CartRepository+SessionRepositoryinterfaces insrc/lib/bindings/cart/ - Analytics Engine binding +
AnalyticsSinkinterface insrc/lib/bindings/analytics/ src/lib/bindings/folder layout with interface types only (no concrete impls yet beyond stubs)- Tests: binding stubs reachable from a stub route; interfaces typecheck against fakes.
- Pages touched: none.
- GH Actions workflow: lint + typecheck +
astro test+ Lighthouse CI (block < 90, warn < 100) on every PR - Wrangler preview deploy per PR (preview URL posted as PR comment)
- Prod deploy on merge to
main - Wrangler secret store wiring for prod secrets
- PR template (checklist: tests added, Lighthouse green, preview verified, doc-search-for-native-integrations done)
- Dependabot enabled (security updates)
- Tests: pipeline green on a stub route; preview URL reachable.
- Pages touched: none.
- Typed env/binding accessor in
src/lib/core/env.ts - Structured logger + request id in
src/lib/core/logger.ts(Workers Logs adapter) - Error taxonomy in
src/lib/core/errors.ts(UserError, ServerError, PaymentError, etc.) - Native Astro middleware in
src/middleware.ts— security headers (CSP, HSTS, X-Frame-Options, Referrer-Policy, Permissions-Policy), request-id injection, logger setup onlocals - HMAC token sign/verify helpers in
src/lib/core/auth.ts(used by MP-4 checkout links, MP-8 order-status links) - Workers Rate Limiting binding wired; per-feature rate-limit helpers in
src/lib/core/rate-limit.ts /healthroute/rumbeacon endpoint (~50 lines) → Analytics Enginesrc/lib/db/folder layout with empty migration scaffolding;src/features/*/folders with emptyservice.ts+repository.tsinterface stubs- Tests: logger/env/error unit tests;
/healthand/rumintegration tests; middleware security-headers assertion test. - Pages touched:
/health,/rum(endpoints only).
- Drizzle schema for
products,variants,product_imagesinsrc/lib/db/schema/catalog.ts - First migration
ProductRepositoryinterface insrc/features/catalog/repository.ts+ Drizzle impl- Seed 5 products (with variants + images) via a seed script
- Astro
<Image>+astro:assetsfor build-time images - Tests: repository CRUD — unit tests against in-memory fake; integration tests against local D1 (Miniflare).
- Pages touched: none.
- Home page at
src/pages/index.astro, product list atsrc/pages/products/index.astro, product detail atsrc/pages/products/[slug].astro(all prerendered at build) catalogservice (getProduct,listProducts) insrc/features/catalog/service.ts- SEO meta + JSON-LD (
Product,Offer,BreadcrumbList) on product pages viasrc/components/seo/ - Responsive image rendering via Astro
<Image>+ R2 for admin-uploaded images - Astro-native shadcn components from
src/components/ui/for layout - Tests: pages render with seeded data; Lighthouse passes (≥100 perf target).
- Pages touched:
/,/products,/products/[slug].
CartRepositoryKV default impl insrc/lib/bindings/cart/- Cart service (
addToCart,updateLine,removeLine,clear,totals) insrc/features/cart/service.ts - Cart Actions (
cart/add,cart/update,cart/remove,cart/clear) insrc/actions/cart.tswithastro:schemainput validation - Cart slide-over UI in
src/components/cart/(Astro-native shadcn components + React island for interactivity) - Cart badge in header
- Tests: cart service + KV impl; UI smoke test.
- Pages touched: cart slide-over (in
Layout),/cart.
CheckoutDrafttyped shape (items, address, shipping method, totals) insrc/features/checkout/types.ts- Address form + flat-rate shipping method selection page at
src/pages/checkout/index.astro - Draft persisted to KV with short TTL
- HMAC-signed checkout link for guest (so customer can resume if they navigate away) — uses
src/lib/core/auth.ts astro:schemavalidation on all form inputs insrc/actions/checkout.ts- Tests: draft lifecycle (create/read/update/expire), signed-link validation.
- Pages touched:
/checkout(address + shipping step).
PaymentProviderinterface insrc/lib/bindings/payment/types.tsRazorpayAdapterinsrc/lib/bindings/payment/razorpay.ts- Order create + capture flow against Razorpay test mode
src/pages/api/webhooks/razorpay.ts— raw body parse, signature verification, idempotency- Secrets via Wrangler secret store;
.dev.varsfor local - Tests: adapter against Razorpay test mode; webhook signature verification test; idempotency test.
- Pages touched:
/api/webhooks/razorpay(one API route).
orders+order_itemsDrizzle schema insrc/lib/db/schema/orders.ts+ migrationOrderRepositoryinterface + Drizzle impl insrc/features/orders/checkoutservicecreateOrder(creates order inplacedstate) +capture(transitions topaidon verified webhook)- Order state machine:
placed → paid → shipped → delivered(+cancelled) - Tests: order state transitions; repository CRUD; end-to-end capture against fake payment provider.
- Pages touched: none (server-only).
- Checkout review page (
src/pages/checkout/review.astro) — review items + address + shipping + totals - Razorpay Checkout (hosted redirect) for v1; Razorpay Embedded can be a future swap if lower-friction UX is wanted
- Success page (
src/pages/checkout/success.astro) - Email-on-paid:
EmailSenderinterface +SmtpAdapterinsrc/lib/bindings/email/(Cloudflare Email Service); order confirmation email with order details - Tests: end-to-end checkout flow against Razorpay test; order state assertions; email dispatch assertion.
- Pages touched:
/checkout/review,/checkout/success.
- Hashed shared secret in KV + http-only secure cookie session
- Cloudflare Turnstile on login form (bot mitigation)
- Rate-limited login via Workers Rate Limiting binding (helpers from
src/lib/core/rate-limit.ts) /admin/orderslist page (filterable by status) atsrc/pages/admin/orders/index.astro/admin/orders/[id]detail page atsrc/pages/admin/orders/[id].astro- Status change Actions in
src/actions/admin.ts(admin/updateOrderStatus,admin/assignTracking) withastro:schema - Manual "tracking id" text field (free text, surfaces on customer order-status page)
- Email on every status change (via
EmailSender) - Admin business logic in
src/features/admin/service.ts - Tests: admin auth (success, failure, rate-limit); status transitions; email dispatch on each transition.
- Pages touched:
/admin/login,/admin/orders,/admin/orders/[id].
/orders/[token]route atsrc/pages/orders/[token].astrowhere token is HMAC-signed (Web Crypto) containing order id + expiry- Read-only status display + tracking id (if assigned) + items
- Email-on-status-change already sends the signed link (wired in MP-7)
- Tests: signed-link validation (valid token, expired token, tampered token); rendering.
- Pages touched:
/orders/[token].
- Privacy Policy page at
src/pages/privacy.astro - Terms of Service page at
src/pages/terms.astro - Returns policy page at
src/pages/returns.astro - Shipping policy page at
src/pages/shipping.astro - Contact / About page at
src/pages/contact.astroandsrc/pages/about.astro - Custom 404 page at
src/pages/404.astro - Custom 500 page at
src/pages/500.astro - All prerendered; all linked in footer; SEO meta on each
- Content as plain Astro pages for v1 (simplest); can migrate to
astro:contentcollection later if markdown editing is preferred - Page content/metadata helpers in
src/features/legal/content.ts - Tests: pages render; footer links resolve; 404/500 routes return correct status codes.
- Pages touched:
/privacy,/terms,/returns,/shipping,/contact,/about,/404,/500.
coupons+coupon_redemptionsDrizzle schema insrc/lib/db/schema/coupons.ts+ migration- Coupon types: % off, flat off, free shipping; constraints: min-order, expires, single-use, per-customer-cap
DiscountServiceinsrc/features/checkout/service.ts(or a dedicatedsrc/features/discounts/) applies at checkout (line or order total)- Admin Actions in
src/actions/admin.tsto create/list/disable coupons - Coupon input on checkout review page
- Tests: coupon application logic (all types + constraints); redemption tracking; admin Actions.
- Pages touched: checkout review (add coupon input),
/admin/coupons.
- Define GA4-style e-commerce event taxonomy:
page_view,view_item,add_to_cart,begin_checkout,add_shipping_info,add_payment_info,purchase - Instrument storefront pages + cart Actions + checkout flow
- Events sent to
/rumbeacon → Analytics Engine (wired in MP-0d) viasrc/lib/bindings/analytics/ - Maps to GA4/Meta Pixel standard so you can later add ads without re-instrumenting
- Tests: event emission assertions per funnel step; Analytics Engine binding receives expected events.
- Pages touched: instrumentation on existing pages (no new pages).
@astrojs/sitemapintegration forsitemap.xmlindex- Static
public/robots.txt - OG-image route per product at
src/pages/og/[slug].png.ts(generated viasatori+sharp; helpers insrc/features/seo/og-image.ts) hreflangstub (IN only for v1) — extends cleanly for multi-language later- Full JSON-LD:
Organization,WebSiteinsrc/features/seo/jsonld.ts(in addition to per-product JSON-LD from MP-2) - Canonical URL audit
- Meta-tag unit tests (every prerendered page has title + description + canonical + OG)
- Tests: sitemap shape; robots.txt content; JSON-LD validates against schema.org; OG-image route returns image.
- Pages touched:
/sitemap-index.xml,/og/[slug].png(endpoints only).
- Image variants via R2 + Cloudflare Image Resizing for admin-uploaded images (via
src/lib/bindings/images/) - Long-cache headers for static assets (R2 + asset binding)
- Critical-CSS inlining
- Font subsetting (via Astro native font optimization from MP-0a)
- Lighthouse CI thresholds tightened (warn < 100 enforced)
- RUM budget assertions (real-user metrics from
/rumbeacon) - Tests: Lighthouse ≥100 perf on key routes (home, product list, product detail); budget assertions.
- Pages touched: instrumentation on existing pages (no new pages).
- WAF rule review with human (in Cloudflare dashboard)
- CSP tightening in
src/middleware.tsbased on actual third-party scripts used - Rate-limit threshold tuning in
src/lib/core/rate-limit.tswith real traffic data - Dependency audit (Dependabot + manual review)
- Threat-model walkthrough with human
- Pen-test-style review of: admin auth, Razorpay webhook, signed order-status links, all Action input validation
- Tests: security regression test suite (auth bypass attempts, signature forgery, CSRF, XSS attempts).
- Pages touched: none (audit + config).
Listed here so we know they exist. Each will get its own mini-plan when prioritized.
- Full admin panel (own area or repo)
- WhatsApp notifications
- Shiprocket integration / pincode serviceability / auto-shipment creation
- Multi-currency / multi-language (i18n)
- Reviews / ratings
- Returns / RMA / formal refund flow (deferred — for v1, admin can mark an order as cancelled and issue a manual refund/invoice outside the app)
- Wishlist (needs accounts to be useful)
- Search (overkill for 5 products)
- Recommendations / related products
- Out-of-stock email notifications
- Newsletter / marketing capture
- GST tax handling (rate matrix, HSN codes, intra-state/inter-state split)
- GST-compliant tax invoices (serial-numbered, downloadable)
- DPDP Act consent capture at checkout
- Abandoned cart recovery (deferred — needs UX decision on email capture point)
- Session replay (rrweb — incompatible with Lighthouse 100)
- Sentry / PostHog / third-party analytics SDKs (lazy-load post-LCP if added)
- A/B test platform
- Loyalty program
- The plan-of-plans is for human use only. The AI does not execute it.
- The human dispatches the AI to implement one mini-plan at a time using superpowers.
- Each mini-plan becomes one PR (or a small number of small PRs if the AI splits further during implementation).
- After every mini-plan, the human does code review before the next MP is dispatched.
- Every mini-plan ends with: tests green + Lighthouse CI green + preview deploy verified + human review passed.
- Before implementing any MP, the AI web-searches Astro + Cloudflare docs to confirm native integrations exist before reaching for external deps (§4).
1. Human picks the next MP from the plan-of-plans
2. (Optional) brainstorming skill — if the MP has open design decisions not settled in this spec
3. Write mini-plan design doc → docs/superpowers/specs/YYYY-MM-DD-MP-XX-<topic>-design.md
4. Human reviews the mini-plan spec → approve / request changes
5. writing-plans skill → detailed implementation plan with TDD tasks + verification commands
saved to docs/superpowers/plans/YYYY-MM-DD-MP-XX-<topic>-plan.md
6. Human reviews the implementation plan
7. Execute the plan — either executing-plans (separate session, review checkpoints)
or subagent-driven-development (current session, dispatch subagents per task)
8. During execution:
- test-driven-development — write test first, then impl, per task
- systematic-debugging — if a test fails or behavior is unexpected
- verification-before-completion — run verification commands before claiming done
9. requesting-code-review skill — self-review against requirements
10. Human does code review (the gate)
11. receiving-code-review skill — if human gives feedback, AI processes it rigorously
12. finishing-a-development-branch — decide merge / PR / cleanup
13. Next MP — back to step 1
If during any MP's implementation the AI discovers a change that crosses MP boundaries — interface changes, scope changes, ordering changes, or promoting/demoting items between §7 and §8 — the AI MUST:
- Stop and flag — never silently absorb a cross-MP change. Pause implementation.
- Write an Impact Note in the current MP's plan doc covering:
- What was discovered
- Which MPs are affected and how
- Severity:
trivial/contained/cross-MP/spec-level
- Hand the decision to the human, who chooses one of:
- (a) Absorb into current MP — change is small and contained to current MP. Just update the current MP's design doc + implementation plan; no plan-of-plans change.
- (b) Update plan-of-plans spec — change affects future MPs' scope, sequence, or interfaces. Append a dated entry to the Amendments Log (§11); mark affected MP entries inline with
[amended YYYY-MM-DD]; re-plan affected MPs when you reach them. - (c) Add/split/reorder MPs — significant new work or structural shift. Amend spec + create new design doc(s) for affected MPs before continuing.
- The trigger MP continues only after the amendment is recorded (for options b and c).
| Discovery | Action |
|---|---|
| Affects only the current MP's internals | Edit current MP's design doc + plan; no spec change |
| Affects only the current MP's implementation plan | Edit current MP's plan; no spec or design doc change |
Changes an interface in src/lib/bindings/*/types.ts that future MPs consume |
Spec amendment — affects future MPs |
Changes MP scope, ordering, or promotes/demotes from future/ |
Spec amendment |
| Discovers a new sub-system needed | Spec amendment — add new MP |
| Discovers an MP is unnecessary | Spec amendment — demote to future/ |
At the end of each folder's last MP, before moving to the next folder, the human runs a checkpoint:
- Re-read the plan-of-plans spec against the current code state.
- For each remaining MP, ask: "Does the code reality still match this MP's scope and dependencies?"
- If no → write an amendment entry, mark affected MP headings.
- If a future MP's design doc already exists, mark it for revision when you reach it.
- Commit the spec amendment as its own commit:
docs: amend plan-of-plans after <folder> checkpoint.
Checkpoint cadence (5 total):
- After
00-foundations/(end of MP-0d) - After
01-catalog/(end of MP-2) - After
03-checkout/(end of MP-6b — most complex folder) - After
04-orders/+05-compliance/combined (end of MP-9) - After
06-growth/+99-cross-cutting/combined (end of MP-14)
Don't rely only on AI honesty. Three mechanical signals:
pnpm typecheckat end of every MP — catches interface drift insrc/lib/bindings/*/types.tsthat later MPs depend on.- Smoke tests for deferred MPs — keep thin "smoke" tests for
future/items that assert their interfaces still typecheck. If MP-5 changesPaymentProvider, MP-6a's smoke test breaks. - Per-folder review checkpoint (§9.4) — re-reads spec against code state, catches silent drift the AI didn't flag.
All decisions locked during the brainstorming session. No TBDs.
Append-only. New entries added at the bottom. Never rewrite history.
(No amendments yet — spec as committed on 2026-07-07.)