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 forsitemap.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
(theastro/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 inwrangler.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 viaexport const prerender = false
):/cart
,/checkout
,/checkout/success
,/admin/orders/*
,/orders/[token]
. Render via``
- 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/A
may importsrc/features/B
internals src/lib/app/prod.ts
+src/lib/app/test.ts
are 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 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 insrc/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 secretsTests: 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 insrc/lib/bindings/images/
- KV binding +
CartRepository
+SessionRepository
interfaces insrc/lib/bindings/cart/
- Analytics Engine binding +
AnalyticsSink
interface 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 insrc/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
/health
route/rum
beacon endpoint (~50 lines) β Analytics Enginesrc/lib/db/
folder layout with empty migration scaffolding;src/features/*/
folders with emptyservice.ts
+repository.ts
interface stubsTests: 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
insrc/lib/db/schema/catalog.ts
- First migration
ProductRepository
interface insrc/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 atsrc/pages/products/index.astro
, product detail atsrc/pages/products/[slug].astro
(all prerendered at build) catalog
service (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]
.
CartRepository
KV 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.ts
withastro: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 (inLayout
),/cart
.
CheckoutDraft
typed 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:schema
validation on all form inputs insrc/actions/checkout.ts
Tests: draft lifecycle (create/read/update/expire), signed-link validation.** Pages touched**:/checkout
(address + shipping step).
PaymentProvider
interface insrc/lib/bindings/payment/types.ts
RazorpayAdapter
insrc/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 insrc/lib/db/schema/orders.ts
- migration
OrderRepository
interface + Drizzle impl insrc/features/orders/
checkout
servicecreateOrder
(creates order inplaced
state) +capture
(transitions topaid
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
insrc/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) 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].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
andsrc/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 insrc/lib/db/schema/coupons.ts
- migration- Coupon types: % off, flat off, free shipping; constraints: min-order, expires, single-use, per-customer-cap
DiscountService
insrc/features/checkout/service.ts
(or a dedicatedsrc/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) 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/sitemap
integration forsitemap.xml
index- 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
) hreflang
stub (IN only for v1) β extends cleanly for multi-language later- Full JSON-LD:
Organization
,WebSite
insrc/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. 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 inpnpm typecheck
at end of every MPsrc/lib/bindings/*/types.ts
that later MPs depend on.Smoke tests for deferred MPsβ keep thin "smoke" tests forfuture/
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.)