# A plan-of-plans for a production-grade end-to-end e-commerce website.

> Source: <https://gist.github.com/Vikaskumargd/e463a7bcc4e2102c3eac5ca00efe9346>
> Published: 2026-07-07 09:02:22+00:00

**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/sitemap`

integration for`sitemap.xml`

index (MP-12).- Static
`public/robots.txt`

. - OG-image route per product (MP-12).
`hreflang`

stub 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`

(the`astro/zod`

module) 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.vars`

for 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`/rum`

beacon 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/clear`

`checkout/createOrder`

,`checkout/capture`

`admin/login`

,`admin/updateOrderStatus`

,`admin/assignTracking`

`orders/getStatus`

(for the guest order-status page)- End-to-end type safety from UI → service via
`astro:schema`

for 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 via`loader`

+ 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 inside`src/features/*/pages/`

. Pages are thin: they call services and render. - Components live in
`src/components/`

(Astro convention) organized by feature subfolder — NOT inside`src/features/*/components/`

. - Actions live in
`src/actions/`

(native Astro location). - Middleware lives in
`src/middleware.ts`

(native Astro middleware) — replaces the custom`withMiddleware()`

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 import`src/features/*/service`

+`src/lib/core/*`

only`src/features/*/service.ts`

→ may import`src/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/A`

may import`src/features/B`

internals `src/lib/app/prod.ts`

+`src/lib/app/test.ts`

are the ONLY files allowed to import concrete adapters`src/pages/*`

→ may import`src/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 test`

native 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 in`src/components/seo/MetaHead.astro`

(title, description, canonical, OG, Twitter cards) - Base responsive image component scaffold (Astro
`<Image>`

+`astro:assets`

) - ESLint with
`no-restricted-imports`

rules from §3.5; Prettier - Vitest via
`astro test`

`src/layouts/Layout.astro`

with head + token-driven styles + font optimization`.dev.vars`

skeleton for local secrets**Tests**: repo boots, layout renders, lint passes, base components render.** Pages touched**:`src/layouts/Layout.astro`

only.

- D1 binding in
`wrangler.jsonc`

+ Drizzle migration infra in`src/lib/db/`

(no tables yet) - R2 binding +
`ImageRepository`

interface in`src/lib/bindings/images/`

- KV binding +
`CartRepository`

+`SessionRepository`

interfaces in`src/lib/bindings/cart/`

- Analytics Engine binding +
`AnalyticsSink`

interface in`src/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 on`locals`

- 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`

`/health`

route`/rum`

beacon endpoint (~50 lines) → Analytics Engine`src/lib/db/`

folder layout with empty migration scaffolding;`src/features/*/`

folders with empty`service.ts`

+`repository.ts`

interface stubs**Tests**: logger/env/error unit tests;`/health`

and`/rum`

integration tests; middleware security-headers assertion test.**Pages touched**:`/health`

,`/rum`

(endpoints only).

- Drizzle schema for
`products`

,`variants`

,`product_images`

in`src/lib/db/schema/catalog.ts`

- First migration
`ProductRepository`

interface in`src/features/catalog/repository.ts`

+ Drizzle impl- Seed 5 products (with variants + images) via a seed script
- Astro
`<Image>`

+`astro:assets`

for 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 at`src/pages/products/index.astro`

, product detail at`src/pages/products/[slug].astro`

(all prerendered at build) `catalog`

service (`getProduct`

,`listProducts`

) in`src/features/catalog/service.ts`

- SEO meta + JSON-LD (
`Product`

,`Offer`

,`BreadcrumbList`

) on product pages via`src/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]`

.

`CartRepository`

KV default impl in`src/lib/bindings/cart/`

- Cart service (
`addToCart`

,`updateLine`

,`removeLine`

,`clear`

,`totals`

) in`src/features/cart/service.ts`

- Cart Actions (
`cart/add`

,`cart/update`

,`cart/remove`

,`cart/clear`

) in`src/actions/cart.ts`

with`astro:schema`

input 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`

.

`CheckoutDraft`

typed shape (items, address, shipping method, totals) in`src/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:schema`

validation on all form inputs in`src/actions/checkout.ts`

**Tests**: draft lifecycle (create/read/update/expire), signed-link validation.** Pages touched**:`/checkout`

(address + shipping step).

`PaymentProvider`

interface in`src/lib/bindings/payment/types.ts`

`RazorpayAdapter`

in`src/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.vars`

for local **Tests**: adapter against Razorpay test mode; webhook signature verification test; idempotency test.** Pages touched**:`/api/webhooks/razorpay`

(one API route).

`orders`

+`order_items`

Drizzle schema in`src/lib/db/schema/orders.ts`

+ migration`OrderRepository`

interface + Drizzle impl in`src/features/orders/`

`checkout`

service`createOrder`

(creates order in`placed`

state) +`capture`

(transitions to`paid`

on 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:
`EmailSender`

interface +`SmtpAdapter`

in`src/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/orders`

list page (filterable by status) at`src/pages/admin/orders/index.astro`

`/admin/orders/[id]`

detail page at`src/pages/admin/orders/[id].astro`

- Status change Actions in
`src/actions/admin.ts`

(`admin/updateOrderStatus`

,`admin/assignTracking`

) with`astro: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 at`src/pages/orders/[token].astro`

where 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.astro`

and`src/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:content`

collection 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_redemptions`

Drizzle schema in`src/lib/db/schema/coupons.ts`

+ migration- Coupon types: % off, flat off, free shipping; constraints: min-order, expires, single-use, per-customer-cap
`DiscountService`

in`src/features/checkout/service.ts`

(or a dedicated`src/features/discounts/`

) applies at checkout (line or order total)- Admin Actions in
`src/actions/admin.ts`

to 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
`/rum`

beacon → Analytics Engine (wired in MP-0d) via`src/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/sitemap`

integration for`sitemap.xml`

index- Static
`public/robots.txt`

- OG-image route per product at
`src/pages/og/[slug].png.ts`

(generated via`satori`

+`sharp`

; helpers in`src/features/seo/og-image.ts`

) `hreflang`

stub (IN only for v1) — extends cleanly for multi-language later- Full JSON-LD:
`Organization`

,`WebSite`

in`src/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
`/rum`

beacon) **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.ts`

based on actual third-party scripts used - Rate-limit threshold tuning in
`src/lib/core/rate-limit.ts`

with 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:

— catches interface drift in`pnpm typecheck`

at end of every MP`src/lib/bindings/*/types.ts`

that 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 changes`PaymentProvider`

, 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.)*
