Appearance
vela-checkout
Hosted checkout application at pay.velapay.io. Public-facing surface for one-time Payment Intents, subscription Checkout Sessions, payment links, and invoices.
Purpose and Role
- Public
/pay/:idcheckout where customers complete one-time payments. - Public
/session/:idcheckout where subscribers complete billing authorization. - Payment links with unique URLs per checkout session (shareable via email, social media, QR code).
- Invoice pages with line items, tax calculation, and PDF generation.
- Email delivery of invoices via Resend integration.
- Turnstile bot protection on public checkout pages.
- Shared checkout-session creation pattern with vela-portal (for plan switching).
- Wallet approval flow — subscribers connect wallet, review terms, sign mandate creation.
Tech Stack
| Technology | Version | Purpose |
|---|---|---|
| React | 19.x | UI library |
| Hono | 4.12.x | API layer (Cloudflare Worker) |
| Cloudflare D1 | GA | Session storage, checkout state |
| Cloudflare Workers | — | Compute runtime |
| @vela/sdk | local alias to sibling SDK | Checkout transaction building |
| Cloudflare Turnstile | — | Bot protection |
| Tailwind CSS | 4.2.x | Styling |
| wrangler | 4.78.x | Cloudflare CLI |
| Resend | — | Email delivery for invoices |
Directory Structure
vela-checkout/
├── src/
│ ├── app/ # React SPA
│ │ ├── components/
│ │ │ ├── checkout/
│ │ │ │ ├── CheckoutShell.tsx # Main checkout layout
│ │ │ │ ├── WalletConnect.tsx # Direct wallet connection
│ │ │ │ ├── PlanReview.tsx # Plan terms display
│ │ │ │ └── Confirmation.tsx # Transaction confirmation
│ │ │ └── invoice/
│ │ │ ├── InvoicePage.tsx # Invoice display
│ │ │ └── InvoicePDF.tsx # PDF generation
│ │ ├── hooks/
│ │ │ ├── useCheckoutFlow.ts # Checkout session management
│ │ │ └── useWalletDetect.ts # Wallet detection
│ │ └── pages/
│ │ ├── checkout.tsx # /checkout/:sessionId
│ │ ├── invoice.tsx # /invoice/:invoiceId
│ │ └── link.tsx # /link/:linkId
│ ├── worker/ # Hono Worker (backend API)
│ │ ├── index.ts # Worker entry
│ │ ├── routes/
│ │ │ ├── checkout.ts # Checkout session CRUD
│ │ │ ├── invoice.ts # Invoice generation
│ │ │ └── payment-link.ts # Payment link management
│ │ └── middleware/
│ │ └── turnstile.ts # Turnstile verification
│ └── lib/
├── wrangler.toml # D1 binding, Turnstile secret
├── vite.config.ts
└── package.jsonDeployment Target
- Cloudflare Workers: Hono Worker for API + React SPA for UI.
- Domain: pay.velapay.io.
Dependencies
What It Depends On
| Dependency | Type | Purpose |
|---|---|---|
@vela/sdk | local alias to sibling SDK | Checkout transaction building, PDAFactory |
vela-dashboard | API proxy | Checkout session creation (shared D1) |
| Cloudflare D1 | Infrastructure | Session and checkout state storage |
| Cloudflare Turnstile | Infrastructure | Bot protection |
| Resend | Infrastructure | Invoice email delivery |
What Depends on It
Nothing. Checkout is a terminal consumer — subscribers use it directly.
Current Status
- v1.5 complete: Hosted checkout with payment links and invoice pages.
- v1.8 complete: Playwright E2E validation, Resend email delivery, multi-token rendering.
- v1.9 accepted on devnet: Payment Intent QR/reference flow, wallet action, status polling, expiry, verified merchant identity, receipt state, allowlisted return action, and route-level bundle budgets.
Notable Design Decisions
Separate from Dashboard
Checkout is a public-facing app with no merchant auth. Extracting it from the dashboard keeps:
- Public traffic isolated from merchant endpoints.
- Deploy cadence independent from merchant features.
- Attack surface minimized (no merchant auth, no org management).
Shared Checkout-Session Pattern
Both vela-checkout and vela-portal (for plan switching) use the same checkout-session creation pattern. Sessions are stored in D1 and consumed by whichever surface initiates the flow.
Payment Intents are intentionally not Checkout Sessions. Checkout reads their canonical state from the dashboard internal API, cannot override cluster or settlement data, and submits only a transaction signature hint for server verification.
Direct Wallet Connection (No iframe)
Unlike the widget, hosted checkout connects the wallet directly on the page. No iframe boundary, no postMessage relay. This simplifies the checkout flow and enables features like QR code wallet pairing.
Turnstile Bot Protection
Public checkout pages are gated with Cloudflare Turnstile to prevent automated abuse (mass subscription attempts, scraping checkout sessions, brute-forcing session IDs).
Payment Links with QR Codes
Each hosted record has its own URL under pay.velapay.io: one-time payments use /pay/:id, while subscription checkout uses /session/:id. Merchants can share supported links by email or QR code.
Invoice Generation
Extended checkout flow supports invoices with line items, tax calculation, PDF generation, and email delivery via Resend. Invoice pages are separate from checkout pages but use the same session management.