Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,12 @@ whisk/
│ ├── core/ # @usewhisk/core — framework-agnostic engine
│ └── react/ # @usewhisk/react — components, hooks, provider
├── examples/
│ └── playground/ # Drop-in showcase + playground
│ ├── playground/ # Drop-in showcase + every-prop playground
│ ├── ecommerce-checkout/ # Atelier Hibiscus — Next.js storefront
│ ├── donate-button/ # OpenForest — Vite donation page
│ ├── themed-saas/ # Steelpath Cloud — Next.js dark dashboard
│ ├── payroll-batch/ # Studio Fortune — Vite batch payouts
│ └── invoice-link/ # Studio Hibiscus — Next.js invoice links
└── apps/
└── docs/ # Documentation site (Fumadocs)
```
Expand All @@ -180,6 +185,24 @@ Deeper design docs — engine boundary, state machine, fee model, resolvers, err

---

## Recipes

Five reference integrations, each a themed mini-app. All run on testnet —
grab test USDC from the [Circle faucet](https://faucet.circle.com).

| Recipe | What it shows | Live demo |
| ----------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------- |
| **E-commerce checkout** | Cart total + merchant address locked; the widget is confirm-and-pay | [demo](https://whisk-ecommerce-checkout.vercel.app/) |
| **Donate button** | Pinned treasury + preset amounts that seed `defaultAmount` | [demo](https://whisk-donate-button.vercel.app/) |
| **Themed SaaS** | `--whisk-*` overrides repaint the widget into a dark dashboard | [demo](https://whisk-themed-saas.vercel.app/) |
| **Payroll batch** | Widget remounts per payee, bridging treasury USDC to each one's chain | [demo](https://whisk-payroll-batch.vercel.app/) |
| **Invoice link** | A shareable URL opens a pre-filled, locked checkout | [demo](https://whisk-invoice-link.vercel.app/) |

Source for each lives under `examples/`. They're starting points to clone and
adapt, not finished apps.

---

## Supported chains

| Network | Chain ID | Send | Bridge | Account types |
Expand Down
10 changes: 5 additions & 5 deletions apps/docs/src/components/marketing/recipes-showcase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const RECIPES: Recipe[] = [
title: "E-commerce checkout",
blurb:
"Recipient + total + both chains are locked from the cart. The widget collapses to a confirm-and-pay surface so the buyer can't fat-finger it.",
href: "https://github.com/Signor1/whisk/tree/main/examples/ecommerce-checkout",
href: "https://whisk-ecommerce-checkout.vercel.app/",
Shell: EcommerceShell,
snippet: [
[b("<"), c("WhiskSend"), txt("")],
Expand All @@ -68,7 +68,7 @@ const RECIPES: Recipe[] = [
title: "Donate button",
blurb:
"Treasury wallet and both chains are pinned. Donors pick from preset amounts the host renders above the widget; the selection seeds defaultAmount.",
href: "https://github.com/Signor1/whisk/tree/main/examples/donate-button",
href: "https://whisk-donate-button.vercel.app/",
Shell: DonateShell,
snippet: [
[
Expand Down Expand Up @@ -98,7 +98,7 @@ const RECIPES: Recipe[] = [
title: "Themed SaaS dashboard",
blurb:
"Override --whisk-* CSS variables once and the widget repaints to the dashboard's palette. The customer can pay from any chain; Whisk bridges to the treasury chain automatically.",
href: "https://github.com/Signor1/whisk/tree/main/examples/themed-saas",
href: "https://whisk-themed-saas.vercel.app/",
Shell: SaasShell,
snippet: [
[cm("// customer pays from their L2, treasury collects on Base")],
Expand All @@ -117,7 +117,7 @@ const RECIPES: Recipe[] = [
title: "Payroll batch",
blurb:
"An admin tool that walks a list of payees. The widget remounts per row with the payee's address + amount locked, and bridges treasury USDC to whatever chain the payee prefers.",
href: "https://github.com/Signor1/whisk/tree/main/examples/payroll-batch",
href: "https://whisk-payroll-batch.vercel.app/",
Shell: PayrollShell,
snippet: [
[cm("// treasury on Base, payees collect on Polygon")],
Expand All @@ -139,7 +139,7 @@ const RECIPES: Recipe[] = [
title: "Invoice payment link",
blurb:
"A shareable URL that opens a pre-filled checkout. Everything comes from the invoice record, including the source chain the client is paying from. Whisk bridges to the studio's home chain in one click.",
href: "https://github.com/Signor1/whisk/tree/main/examples/invoice-link",
href: "https://whisk-invoice-link.vercel.app/",
Shell: InvoiceShell,
snippet: [
[cm("// app/i/[id]/page.tsx")],
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/src/content/docs/recipes/donate-button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ onSuccess={async ({ quote, finalTxHash }) => {
}}
```

## Live demo

[whisk-donate-button.vercel.app](https://whisk-donate-button.vercel.app/) — running on testnet.

## Full source

[`examples/donate-button`](https://github.com/Signor1/whisk/tree/main/examples/donate-button)
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/src/content/docs/recipes/ecommerce-checkout.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ export async function POST(req, { params }) {

This step matters. Skipping it is how stores get drained.

## Live demo

[whisk-ecommerce-checkout.vercel.app](https://whisk-ecommerce-checkout.vercel.app/) — running on testnet.

## Full source

[`examples/ecommerce-checkout`](https://github.com/Signor1/whisk/tree/main/examples/ecommerce-checkout)
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/src/content/docs/recipes/invoice-link.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ export async function POST(req: Request) {
Then the page verifies the signature before mounting the widget. If
the sig doesn't match, show the invalid-link page.

## Live demo

[whisk-invoice-link.vercel.app](https://whisk-invoice-link.vercel.app/) — running on testnet.

## Full source

[`examples/invoice-link`](https://github.com/Signor1/whisk/tree/main/examples/invoice-link)
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/src/content/docs/recipes/payroll-batch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ from one payee to the next, the widget would keep the previous
payee's state around. The `key` forces a fresh mount per row, so
each payment starts from a clean form.

## Live demo

[whisk-payroll-batch.vercel.app](https://whisk-payroll-batch.vercel.app/) — running on testnet.

## Full source

[`examples/payroll-batch`](https://github.com/Signor1/whisk/tree/main/examples/payroll-batch)
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/src/content/docs/recipes/themed-saas.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ export default function PayoutsPage() {
That's it. Every Whisk component (card, input, button, chips, step
rail, banner, badge) picks up the new palette automatically.

## Live demo

[whisk-themed-saas.vercel.app](https://whisk-themed-saas.vercel.app/) — running on testnet.

## Full source

[`examples/themed-saas`](https://github.com/Signor1/whisk/tree/main/examples/themed-saas)
Expand Down
2 changes: 2 additions & 0 deletions examples/donate-button/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# whisk-example-donate-button

> **Live demo:** https://whisk-donate-button.vercel.app/ (testnet)

**OpenForest** — a reforestation NGO landing page with a public donor
wall, annual-goal progress bar, three donation tiers (Seedling, Grove,
Canopy), custom-amount fallback, and an active-projects showcase.
Expand Down
2 changes: 2 additions & 0 deletions examples/ecommerce-checkout/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# whisk-example-ecommerce-checkout

> **Live demo:** https://whisk-ecommerce-checkout.vercel.app/ (testnet)

**Atelier Hibiscus** — an editorial DTC storefront with a 5-product
catalog, multi-item cart, two-step checkout, and order confirmation.
Pay-with-USDC at checkout via Whisk.
Expand Down
2 changes: 2 additions & 0 deletions examples/invoice-link/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# whisk-example-invoice-link

> **Live demo:** https://whisk-invoice-link.vercel.app/ (testnet)

**Studio Hibiscus** — an invoice-link flow with two views:

- `/` (customer view) — reads `?to=…&amount=…&chain=…&memo=…` from the
Expand Down
2 changes: 2 additions & 0 deletions examples/payroll-batch/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# whisk-example-payroll-batch

> **Live demo:** https://whisk-payroll-batch.vercel.app/ (testnet)

**Studio Fortune** — a creative agency payroll tool. Three-step flow
(review → dispatch → confirm), 6 payees on a claret/ivory editorial
palette, progress bar that animates as each transfer settles.
Expand Down
19 changes: 18 additions & 1 deletion examples/playground/src/app/circle-cors-shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,23 @@
* other fetch — wagmi RPC calls, our own routes, analytics — passes
* through untouched.
*/

/**
* True only when the URL's host is Circle's API (`api.circle.com` or any
* `*.circle.com` host). Parses the URL and checks the host rather than
* substring-matching, so the name can't be smuggled into a path or query
* string (e.g. `https://evil.com/?x=api.circle.com`).
*/
function isCircleApiUrl(url: string): boolean {
let host: string;
try {
host = new URL(url, window.location.href).hostname.toLowerCase();
} catch {
return false;
}
return host === "circle.com" || host.endsWith(".circle.com");
}

let installed = false;

export function installCircleCorsShim() {
Expand All @@ -37,7 +54,7 @@ export function installCircleCorsShim() {
? input.href
: input.url;

if (!url.includes("api.circle.com")) {
if (!isCircleApiUrl(url)) {
return originalFetch(input, init);
}

Expand Down
2 changes: 2 additions & 0 deletions examples/themed-saas/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# whisk-example-themed-saas

> **Live demo:** https://whisk-themed-saas.vercel.app/ (testnet)

**Steelpath Cloud** — a B2B treasury dashboard with sidebar nav, KPI
cards, a scheduled-vendors table, recent settlements feed, and an
activity log. Click any vendor row to fund their next payout via Whisk.
Expand Down