1.0.0
CurrentFirst public release. The seven-file static HTML theme is now an Astro storefront with a Markdown catalog, a real cart, and Stripe Checkout — and it still runs with no credentials at all.
Added
Markdown product catalog with Zod-validated frontmatter — 19 products, variants, options and per-variant pricing.
Stripe Embedded Checkout mounted inside the theme’s own payment step, with STRIPE_CHECKOUT_MODE=hosted as the escape hatch for strict CSP.
Server-side pricing in src/lib/commerce/pricing.ts. The browser sends slugs and quantities; amounts are recomputed from the catalog before a session exists.
Webhook fulfilment with two-layer idempotency, including the async payment events EU methods depend on.
Passwordless accounts: magic-link sign-in, stateless signed cookies, order history and the Stripe Customer Portal.
Cart, wishlist and compare stores backed by localStorage, synced across tabs, holding no prices.
Faceted shop with URL-as-state filtering, plus prerendered category and collection routes for search engines.
/search, /wishlist, /compare, /journal, six policy pages and this changelog — every footer link in the source pointed at a page that did not exist.
Six repo-specific checkers behind npm run check:all, each written after a bug it would have caught.
Changed
Three contradictory price universes — the drawer’s items array, the cart page’s PRICES map and checkout’s base = 4650 — reconciled into one catalog.
Seven duplicated copies of the header, footer, promo bar and design tokens collapsed into one set of components. Divergences were resolved by counting usage, not by reading one file.
All money is integer minor units; major units appear only in product Markdown and JSON-LD.
Fonts and photography are self-hosted and run through astro:assets. No external font or CDN request survives, and builds work offline.
Removed
Card number, expiry and CVC inputs, along with the masking script and the CSS that dressed them. Stripe renders those on its own domain — that is what keeps a shop PCI SAQ-A eligible.
The cosmetic promo-code handler and every client-side total. The client displays what the server computed.
Security
The magic-link sign-in URL is returned to the browser only under import.meta.env.DEV. Without that gate, a build with Stripe keys and no mail provider let anyone sign in as any address they could type.
Order lookup checks ownership inside the lookup function rather than at each call site, so a new caller cannot forget it.
Signed tokens must carry a numeric exp. Treating a missing one as “never expires” had made an immortal credential possible.