A modern, serverless e-commerce store built with Astro, Cloudflare Workers, and Stripe. Features real-time cart management, secure payment processing, and asynchronous order fulfillment.
- Static Site Generation with Astro for blazing-fast page loads
- Serverless API powered by Cloudflare Workers
- Real-time Cart using Durable Objects (auto-expires after 30 minutes)
- Secure Payments via Stripe Checkout
- Async Order Processing with Cloudflare Queues
- Order Management stored in Cloudflare D1 (SQLite)
- Webhook Handling for payment eventse
- Automatic Retries with dead letter queue for failed orders
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Astro │────▶│ Workers │────▶│ Stripe │
│ (SSG) │ │ (API) │ │ (Payments) │
└─────────────┘ └──────────────┘ └─────────────┘
│
┌───────┼───────┐
▼ ▼ ▼
┌────────┐ ┌────┐ ┌────────┐
│Durable │ │ D1 │ │ Queues │
│Objects │ │ │ │ │
└────────┘ └────┘ └────────┘
- Node.js 16.17.0 or later
- Cloudflare account
- Stripe account
- Wrangler CLI
- Stripe CLI (for webhook testing)
-
Clone the repository
git clone https://github.com/yourusername/workreform-store.git cd workreform-store -
Install dependencies
npm install
-
Set up environment variables
cp .env.example .env
Edit
.envand add your Stripe keys:STRIPE_SECRET_KEY: Your Stripe secret keySTRIPE_PUBLISHABLE_KEY: Your Stripe publishable keySTRIPE_WEBHOOK_SECRET: Your webhook endpoint secret
-
Start the development server
npm run dev
Your site will be available at http://localhost:4321
-
Test Stripe webhooks locally (in a separate terminal)
stripe listen --forward-to localhost:4321/api/webhook/stripe
Copy the webhook signing secret and add it to your
.env -
Test payments with Stripe test cards
- Success:
4242 4242 4242 4242 - Decline:
4000 0000 0000 0002 - More test cards
- Success:
-
Run the setup script
chmod +x setup.sh ./setup.sh
This will:
- Create D1 database
- Run migrations
- Create Queues (order-processing, order-dlq)
- Prompt for Stripe secrets
-
Update wrangler.toml
Replace the placeholder IDs with the actual IDs from step 1:
[[d1_databases]] binding = "DB" database_name = "workreform-store" database_id = "YOUR_ACTUAL_D1_ID"
-
Deploy to Cloudflare
npm run build wrangler deploy
-
Configure Stripe webhook endpoint
In the Stripe Dashboard:
- Add endpoint:
https://your-worker.workers.dev/api/webhook/stripe - Select events:
checkout.session.completedcheckout.session.async_payment_succeededpayment_intent.payment_failed
- Copy the signing secret to
wrangler secret put STRIPE_WEBHOOK_SECRET
- Add endpoint:
npm run build
wrangler deployworkreform-store/
├── src/
│ ├── pages/ # Astro pages
│ │ ├── index.astro # Homepage with product listing
│ │ ├── cart.astro # Shopping cart
│ │ ├── success.astro # Order success page
│ │ └── api/ # API endpoints
│ │ ├── cart/ # Cart management
│ │ │ ├── add.ts
│ │ │ ├── get.ts
│ │ │ ├── update.ts
│ │ │ └── remove.ts
│ │ ├── checkout/
│ │ │ └── session.ts # Stripe checkout
│ │ └── webhook/
│ │ └── stripe.ts # Stripe webhooks
│ ├── content/
│ │ └── products/ # Product markdown files
│ ├── components/
│ │ ├── AddToCart.astro # Add to cart button
│ │ └── Cart.astro # Cart component
│ ├── cart-do.ts # Durable Object for cart
│ ├── queue-consumer.ts # Queue consumer for orders
│ └── worker.ts # Worker entry point
├── migrations/ # D1 database migrations
│ └── 0001_create_orders.sql
├── public/ # Static assets
├── astro.config.mjs # Astro configuration
├── wrangler.toml # Cloudflare Workers config
└── package.json
Products are managed as markdown files in src/content/products/:
---
title: "Product Name"
description: "Product description"
price: 29.99
image: "/images/product.jpg"
category: "Category"
stock: 100
featured: true
sku: "PROD-001"
stripeProductId: "prod_xxx"
stripePriceId: "price_xxx"
---
Product details and specifications...# Using Stripe CLI
stripe products create \
--name="Product Name" \
--description="Description"
stripe prices create \
--product="prod_xxx" \
--unit-amount=2999 \
--currency=usdOr use the included products:
- WorkReform T-Shirt ($25) -
prod_SphJjGkdfmlDJW - WorkReform Coffee Mug ($15) -
prod_SphJ3ji8BpDtiK
- Browse products at http://localhost:4321
- Click "Add to Cart" on products
- View cart at http://localhost:4321/cart
- Proceed to checkout
- Complete a test purchase
- Check logs:
wrangler tail --format pretty - Verify order in D1:
wrangler d1 execute workreform-store --command="SELECT * FROM orders"
# Monitor queue
wrangler tail --format pretty
# Check queue metrics
wrangler queues stats order-processingwrangler tail --format pretty# List orders
wrangler d1 execute workreform-store \
--command="SELECT * FROM orders ORDER BY created_at DESC LIMIT 10"
# Check order items
wrangler d1 execute workreform-store \
--command="SELECT * FROM order_items WHERE order_id = ?"# Queue statistics
wrangler queues stats order-processing
# Dead letter queue
wrangler queues stats order-dlq- PCI Compliance: Payments handled by Stripe's hosted checkout
- Webhook Verification: All webhooks verified with Stripe signatures
- Cart Expiration: Auto-delete after 30 minutes to prevent abuse
- HTTPS Only: Enforced by Cloudflare Workers
- Secrets Management: API keys stored as encrypted secrets
- No User Accounts: Anonymous checkout only (privacy-first)
- Check cookies are enabled
- Verify Durable Objects are deployed
- Check cart expiration (30 minutes)
- Verify Stripe keys are correct
- Check webhook endpoint is configured
- Ensure webhook secret matches
- Check D1 database is created
- Verify migrations have run
- Check queue consumer logs
- Check queue is created:
wrangler queues list - Monitor dead letter queue for failures
- Check worker logs for errors
-
POST /api/cart/add- Add item to cart{ "id": "PROD-001", "name": "Product Name", "price": 29.99, "quantity": 1 } -
GET /api/cart/get- Get cart contents -
POST /api/cart/update- Update item quantity -
POST /api/cart/remove- Remove item from cart
POST /api/checkout/session- Create Stripe checkout session- Returns:
{ sessionId, url }
- Returns:
POST /api/webhook/stripe- Handle Stripe webhooks- Requires:
stripe-signatureheader
- Requires:
- No Pages Dependency: Pure Workers implementation (Pages is being deprecated)
- Cost Efficient: Aggressive cart expiration prevents resource abuse
- Scalable: Durable Objects provide consistent state without databases
- Secure: All payments handled by Stripe's PCI-compliant infrastructure
- Fast: Static generation + edge computing = sub-second load times
- Resilient: Queue-based order processing with automatic retries
- Page Load: < 500ms (static assets from edge)
- API Response: < 100ms (Workers at edge)
- Cart Operations: < 50ms (Durable Objects)
- Global Availability: 200+ Cloudflare data centers
- Customer accounts and authentication
- Order history and tracking
- Email notifications (SendGrid/Mailgun)
- Inventory management
- Admin dashboard
- Product reviews and ratings
- Discount codes and promotions
- Multi-currency support
- Shipping calculations
- Tax calculations with Stripe Tax
- Abandoned cart recovery
- Analytics dashboard
- A/B testing framework
This project is licensed under the MIT License.
- Astro - Static site generator
- Cloudflare Workers - Serverless platform
- Stripe - Payment processing
Built with ❤️ using Cloudflare Workers and Stripe