Skip to content

Commit 917f1d5

Browse files
committed
feat: updated read me / metadata and some template logic
1 parent 8d6e6b9 commit 917f1d5

13 files changed

Lines changed: 189 additions & 97 deletions

File tree

CLI-spec.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111
**Does:**
1212

13-
- `npx claws-supply auth` — device authorization with browser approval and local token storage
14-
- `npx claws-supply build` — build and sign a local template artifact (`manifest.json` + hashes)
15-
- `npx claws-supply publish` — create a draft template for the authenticated user via `/api/cli/v1`
13+
- `npx claws-supply@latest auth` — device authorization with browser approval and local token storage
14+
- `npx claws-supply@latest build` — build and sign a local template artifact (`manifest.json` + hashes)
15+
- `npx claws-supply@latest publish` — create a draft template for the authenticated user via `/api/cli/v1`
1616

1717
**Doesn't (not in MVP):**
1818

@@ -156,8 +156,8 @@ claws-supply/
156156
│ ├── index.ts # Entry: shebang + bootstrap
157157
│ ├── cli.ts # Commander program definition
158158
│ ├── commands/
159-
│ │ ├── install.ts # npx claws-supply <slug> (or interactive)
160-
│ │ └── info.ts # npx claws-supply info <slug>
159+
│ │ ├── install.ts # npx claws-supply@latest <slug> (or interactive)
160+
│ │ └── info.ts # npx claws-supply@latest info <slug>
161161
│ ├── lib/
162162
│ │ ├── api.ts # Fetch from claws.supply API
163163
│ │ ├── download.ts # Download zip + verify archive hash
@@ -188,7 +188,7 @@ That's it. No config patching, no permission engine, no security scanner. Those
188188
### 5.1 Auth
189189

190190
```bash
191-
npx claws-supply auth
191+
npx claws-supply@latest auth
192192
```
193193

194194
- Starts device authorization via `/api/cli/v1/auth/device/code`
@@ -199,7 +199,7 @@ npx claws-supply auth
199199
### 5.2 Build
200200

201201
```bash
202-
npx claws-supply build
202+
npx claws-supply@latest build
203203
```
204204

205205
- Prompts for title + slug
@@ -210,7 +210,7 @@ npx claws-supply build
210210
### 5.3 Publish
211211

212212
```bash
213-
npx claws-supply publish
213+
npx claws-supply@latest publish
214214
```
215215

216216
- Requests zip upload token from `/api/cli/v1/templates/uploads/zip-token`
@@ -718,7 +718,7 @@ Always:
718718
The download may be corrupted. Try again, or download from claws.supply directly.
719719
720720
✗ Template "nonexistent-slug" not found
721-
Check the slug at https://claws.supply or run `npx claws-supply` to browse.
721+
Check the slug at https://claws.supply or run `npx claws-supply@latest` to browse.
722722
723723
✗ This is a paid template ($12.00)
724724
Purchase it at: https://claws.supply/openclaw/template/reddit-marketing-starter

MVP.md

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,21 @@
5353
- Browsing sales: 30% platform commission
5454
- Direct-link sales: 20% platform commission
5555
- Direct referral window: 90 days
56+
- [x] DONE — Template purchase flow shipped (code path):
57+
- `POST /api/purchases/checkout` creates authenticated checkout sessions for paid templates
58+
- Commission split is persisted on `purchase` (`commission_rate`, `platform_fee_amount_cents`, `seller_payout_amount_cents`)
59+
- Stripe Checkout for paid templates is created in seller connected-account context with `application_fee_amount`
60+
- Connect webhook shipped at `POST /api/stripe/webhooks/connect` to transition purchases to `completed` / `failed`
61+
- Template detail quick-command gate shipped on `/openclaw/template/[templateSlug]`:
62+
- free template: copy command
63+
- paid + signed out: sign-in CTA
64+
- paid + signed in without purchase: purchase CTA
65+
- paid + owner/admin/purchased: copy command
5666
- [x] DONE — Advertising subscriptions v1 shipped:
5767
- Public sales + authenticated campaign management page at `/advertise`
5868
- Ad campaign schema + migration (`ad_campaign`, `stripe_webhook_event`, enums/indexes/constraints)
5969
- Ads APIs shipped: `GET /api/ads/availability`, `GET/POST /api/ads/campaign`, `POST /api/ads/campaign/cancel`, `POST /api/ads/logo-handle`
60-
- Stripe ads webhook lifecycle sync shipped at `POST /api/stripe/webhooks`
70+
- Stripe ads webhook lifecycle sync shipped at `POST /api/stripe/webhooks/platform`
6171
- Sponsored rendering shipped for sidebar and in-grid results cards
6272
- Legal updates shipped for advertising subscriptions/moderation in terms + policy pages
6373
- [x] DONE — Members community surfaces shipped:
@@ -101,7 +111,7 @@
101111
- Member privacy decision: public member read paths only select safe fields (`id`, `username`, `name`, `bio`, `image`, verification flags, timestamps); email is never exposed.
102112
- Migration prerequisite: local/dev must run latest Drizzle migrations before app runtime (`bun run migrate`) so lifecycle columns like `template.status` exist.
103113
- Current gap snapshot:
104-
- Checkout/purchase routes + Stripe webhook purchase creation are still pending.
114+
- Purchase checkout + connect-webhook completion are shipped; `GET /api/purchases` and `GET /api/purchases/[templateSlug]` are still pending.
105115
- Review routes are still pending.
106116
- Dedicated `/api/members` and `/api/members/[username]` endpoints are still pending (public pages currently read server-side directly).
107117
- Automated tests for lifecycle/read/blob/payment flows are still pending.
@@ -388,19 +398,27 @@ No shareable pre-signed blob download URL is returned to client.
388398
### 6.2 Purchase Flow
389399

390400
```
391-
1. Buyer clicks "Buy" on template page
392-
2. Determine sale_type:
393-
- If URL has ?ref={sellerUsername} → sale_type = "direct"
401+
1. Buyer clicks purchase CTA on template detail page.
402+
2. Client calls POST /api/purchases/checkout with body { templateSlug, ref? }.
403+
3. Route enforces authenticated session + Zod input validation.
404+
4. Service validates template availability + prevents self-purchase + checks existing ownership.
405+
5. Determine sale_type:
406+
- If request body has ref matching seller username → sale_type = "direct"
394407
- Otherwise → sale_type = "browsing"
395-
3. Look up commission rate:
408+
6. Look up commission rate:
396409
a. Check commission_overrides for this seller
397410
b. If no override → use defaults (direct: 20%, browsing: 30%)
398-
4. Create Stripe Checkout Session:
399-
- application_fee_amount = price * (commission_rate / 100)
400-
- transfer_data.destination = seller's stripe_account_id
401-
5. On successful payment (webhook: checkout.session.completed):
402-
a. Create purchase record
403-
6. Buyer can now download the template
411+
7. Upsert pending purchase row with:
412+
- price, commission_rate, platform_fee_amount_cents, seller_payout_amount_cents
413+
8. Create Stripe Checkout Session for the seller connected account:
414+
- request option: stripeAccount = seller.stripe_account_id
415+
- payment_intent_data.application_fee_amount = platform fee
416+
9. Persist stripe_checkout_session_id + checkout_started purchase event.
417+
10. On successful payment webhook (`checkout.session.completed` / `checkout.session.async_payment_succeeded`):
418+
a. Update purchase status to completed
419+
b. Set completed_at + stripe_payment_intent_id
420+
c. Persist checkout_completed purchase event
421+
11. Buyer can now download/use the paid template.
404422
```
405423

406424
`download_count` is incremented on successful download stream start (`GET /api/templates/[slug]/download`), not on checkout completion.
@@ -502,11 +520,11 @@ Deprecated/removed routes:
502520

503521
### 7.3 Purchase Routes
504522

505-
| Method | Route | Auth | Description |
506-
| ------ | ------------------------------- | ---- | ---------------------------------------------------------------------- |
507-
| `POST` | `/api/purchases/checkout` || Create Stripe Checkout session. Body: `{ templateSlug, ref? }` |
508-
| `GET` | `/api/purchases` || List current user's purchases. Includes template info for re-download. |
509-
| `GET` | `/api/purchases/[templateSlug]` || Check if current user owns a specific template |
523+
| Method | Route | Auth | Status | Description |
524+
| ------ | ------------------------------- | ---- | ----------- | ---------------------------------------------------------------------- |
525+
| `POST` | `/api/purchases/checkout` || ✅ Shipped | Create Stripe Checkout session. Body: `{ templateSlug, ref? }` |
526+
| `GET` | `/api/purchases` || ⚠️ Pending | List current user's purchases. Includes template info for re-download. |
527+
| `GET` | `/api/purchases/[templateSlug]` || ⚠️ Pending | Check if current user owns a specific template |
510528

511529
### 7.4 Review Routes
512530

@@ -527,11 +545,14 @@ Deprecated/removed routes:
527545

528546
### 7.6 Stripe Routes
529547

530-
| Method | Route | Auth | Description |
531-
| ------ | ---------------------------- | ---- | ----------------------------------------------------------------- |
532-
| `POST` | `/api/stripe/connect` || Create Stripe Connect account + return onboarding URL |
533-
| `GET` | `/api/stripe/connect/status` || Check Stripe account status (onboarding complete, verified, etc.) |
534-
| `POST` | `/api/stripe/webhooks` |\* | Stripe webhook handler. \*Verified via Stripe signature. |
548+
| Method | Route | Auth | Status | Description |
549+
| ------ | ------------------------------- | ---- | ----------- | -------------------------------------------------------------------------------------------- |
550+
| `POST` | `/api/profile/stripe/connect` || ✅ Shipped | Create Stripe Connect account link and return onboarding URL. |
551+
| `GET` | `/api/profile/stripe/status` || ✅ Shipped | Check Stripe account status (onboarding complete, verified, etc.). |
552+
| `POST` | `/api/stripe/webhooks/connect` |\* | ✅ Shipped | Stripe Connect webhook for template purchases + connected account updates. |
553+
| `POST` | `/api/stripe/webhooks/platform` |\* | ✅ Shipped | Stripe platform webhook for advertising subscriptions. |
554+
555+
\* Verified via Stripe signature.
535556

536557
### 7.7 Admin Routes
537558

@@ -621,7 +642,12 @@ app/
621642
- **SEO title:** "{Template Title} — OpenClaw Template on Claws.supply"
622643
- **Content:**
623644
- Template title, description (rendered markdown), cover image
624-
- Price (or "Free"), Buy/Download button
645+
- Price + quick command row: `npx claws-supply use {templateSlug}`
646+
- Quick command access states:
647+
- Free template: copy command visible for all visitors
648+
- Paid + signed out: locked command row + sign-in CTA
649+
- Paid + signed in without completed purchase: purchase CTA (`Purchase for $X`)
650+
- Paid + owner/admin/paid buyer: copy command visible
625651
- Seller info card (avatar, name, verified badge, link to profile)
626652
- Stats: downloads, average rating, review count
627653
- Reviews section (paginated)
@@ -668,9 +694,9 @@ app/
668694
#### CLI Publishing Guide (`/openclaw/templates/publish-via-cli`)
669695

670696
- Public guide page for sellers with exact CLI commands:
671-
- `npx claws-supply auth`
672-
- `npx claws-supply build`
673-
- `npx claws-supply publish`
697+
- `npx claws-supply@latest auth`
698+
- `npx claws-supply@latest build`
699+
- `npx claws-supply@latest publish`
674700
- This replaces the previous web create-template form flow.
675701

676702
#### Dashboard — Settings (`/dashboard/settings`)
@@ -739,7 +765,20 @@ For MVP, admin features are **API-only** (no admin UI). Admins use API calls or
739765

740766
## 11. Webhook Handlers
741767

742-
### Stripe Webhooks (`POST /api/stripe/webhooks`)
768+
### Stripe Connect Webhooks (`POST /api/stripe/webhooks/connect`)
769+
770+
| Event | Action |
771+
| ---------------------------------------- | ----------------------------------------------------------------------------------------------- |
772+
| `checkout.session.completed` | Complete template purchase when payment status is `paid`. |
773+
| `checkout.session.async_payment_succeeded` | Complete template purchase for delayed-success payment methods. |
774+
| `checkout.session.expired` | Mark pending template purchase as failed/expired. |
775+
| `checkout.session.async_payment_failed` | Mark pending template purchase as failed. |
776+
| `account.updated` | Sync seller `stripeVerified` status from Connect account capability flags. |
777+
778+
Webhook signatures are verified via `stripe.webhooks.constructEvent()` with `STRIPE_CONNECT_WEBHOOK_SECRET`.
779+
Connect webhook event IDs are persisted in `stripe_connect_webhook_event` for idempotency.
780+
781+
### Stripe Platform Webhooks (`POST /api/stripe/webhooks/platform`)
743782

744783
| Event | Action |
745784
| ------------------------------- | -------------------------------------------------------------------------------------------- |
@@ -749,8 +788,8 @@ For MVP, admin features are **API-only** (no admin UI). Admins use API calls or
749788
| `customer.subscription.deleted` | End campaign and stop visibility. |
750789
| `invoice.payment_failed` | Record failure state for observability; do not hide ad immediately. |
751790

752-
All webhooks are verified via `stripe.webhooks.constructEvent()` with signing secret.
753-
Webhook event IDs are persisted for idempotency in `stripe_webhook_event`.
791+
Webhook signatures are verified via `stripe.webhooks.constructEvent()` with `STRIPE_PLATFORM_WEBHOOK_SECRET`.
792+
Platform webhook event IDs are persisted for idempotency in `stripe_webhook_event`.
754793

755794
---
756795

@@ -771,6 +810,7 @@ Webhook event IDs are persisted for idempotency in `stripe_webhook_event`.
771810
13. **Versioning:** each version is immutable and unique per template; new version must increment by exactly `+1` (integer versioning).
772811
14. **Download tracking:** `download_count` increments only after private blob fetch begins successfully.
773812
15. **Soft delete:** deletion sets lifecycle status to `deleted`; data is retained.
813+
16. **Paid command gate:** on template detail pages, paid-template command copy is allowed only for owner/admin/completed-purchase users; ineligible users see sign-in or purchase CTA.
774814

775815
### Known Hardening Gaps (Non-Blocking Follow-up)
776816

README.md

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,93 @@
1-
# claws.supply
1+
# Claws.supply
22

3-
Bun + Turborepo monorepo.
3+
Claws.supply is a marketplace for OpenClaw templates. Builders can discover production-ready agent setups faster, sellers can publish and monetize their templates, and buyers can purchase and deploy proven configurations. Template creation is CLI-first through the `claws-supply` package.
44

5-
Landing page: [claws.supply](https://claws.supply)
5+
## What's In This Repo
66

7-
## Workspace Layout
7+
- `apps/web` - Next.js App Router marketplace app and API (`@claws-supply/web`)
8+
- `packages/cli` - `claws-supply` creator CLI for auth, build, and draft publish
89

9-
- `apps/web`: Next.js App Router application (`@claws-supply/web`)
10-
- `packages/cli`: claws.supply creator CLI (`claws-supply`)
10+
## Tech Stack
1111

12-
## CLI Usage
12+
- Monorepo/runtime: Bun (`>=1.3.1`) + Turborepo
13+
- Web: Next.js App Router, React, Tailwind CSS
14+
- Data/auth/payments/storage: Drizzle ORM + PostgreSQL, Better Auth, Stripe, Vercel Blob
15+
- CLI: Node (`>=20`), Commander, Zod, fflate, Vercel Blob client
1316

14-
Run without installing globally:
17+
## Quickstart (Local Development)
18+
19+
Prerequisites:
20+
21+
- Bun `>=1.3.1`
22+
- Node `>=20`
23+
- Docker (for local Postgres)
24+
25+
1. Install dependencies.
1526

1627
```bash
17-
npx claws-supply auth
18-
npx claws-supply build
19-
npx claws-supply publish
28+
bun install
2029
```
2130

22-
`build` uses your current folder by default. Use `--source <path>` only when the target project is in a different folder.
31+
2. Start local Postgres.
2332

24-
## Requirements
33+
```bash
34+
docker compose up -d
35+
```
2536

26-
- Bun `1.3.1` or newer
37+
3. Create local env file and fill values.
2738

28-
## Install
39+
```bash
40+
cp apps/web/env.template apps/web/.env.local
41+
```
42+
43+
4. Run database migrations.
2944

3045
```bash
31-
bun install
46+
bun run migrate
3247
```
3348

34-
## Root Commands
49+
5. Start the app.
3550

3651
```bash
3752
bun run dev
38-
bun run build
39-
bun run start
40-
bun run lint
41-
bun run check:no-runtime-sql
42-
bun run db:generate
43-
bun run migrate
4453
```
4554

46-
## Environment Files
55+
Web runs at `http://localhost:3039`.
56+
57+
## Common Monorepo Commands
58+
59+
| Command | Purpose |
60+
| --- | --- |
61+
| `bun run dev` | Run web app in development mode (`@claws-supply/web`) |
62+
| `bun run build` | Build web app |
63+
| `bun run start` | Start production server for web app |
64+
| `bun run lint` | Run lint checks for web app |
65+
| `bun run db:generate` | Generate Drizzle migrations |
66+
| `bun run migrate` | Apply database migrations |
67+
| `bun run check:no-runtime-sql` | Guardrail check for runtime SQL usage |
68+
69+
## CLI Quickstart (Creator Flow)
70+
71+
Run from your template project folder:
72+
73+
```bash
74+
npx claws-supply@latest auth
75+
npx claws-supply@latest build
76+
npx claws-supply@latest publish
77+
```
78+
79+
CLI defaults:
80+
81+
- Production API target is `https://claws.supply`
82+
- Use `-D` to target local API: `http://localhost:3039`
83+
- `build` uses the current directory by default (`--source` is optional)
84+
85+
For full CLI flags, local artifact/auth state paths, local smoke flows, and troubleshooting, see [`packages/cli/README.md`](packages/cli/README.md).
4786

48-
- Web app env file: `apps/web/.env.local`
49-
- Template env values: `apps/web/env.template`
87+
## Docs And Links
5088

51-
If you previously had `.env.local` at repo root, move it to `apps/web/.env.local`.
89+
- Site: [https://claws.supply](https://claws.supply)
90+
- Product docs: [https://claws.supply/docs](https://claws.supply/docs)
91+
- CLI docs: [`packages/cli/README.md`](packages/cli/README.md)
92+
- Internal product spec: [`MVP.md`](MVP.md)
93+
- Internal CLI spec: [`CLI-spec.md`](CLI-spec.md)

apps/web/app/layout.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import { Navbar } from "@/components/navbar";
66
import { SiteFooter } from "@/components/site-footer";
77
import { Toaster } from "@/components/ui/sonner";
88
import { getSessionFromNextHeaders } from "@/lib/auth/session";
9-
import { absoluteUrl, getDefaultOgImagePath, getSiteUrl } from "@/lib/seo";
9+
import {
10+
absoluteUrl,
11+
DEFAULT_SITE_TAGLINE,
12+
getDefaultOgImagePath,
13+
getSiteUrl,
14+
} from "@/lib/seo";
1015
import "./globals.css";
1116
import { MainProviders } from "./providers";
1217
import Script from "next/script";
@@ -17,7 +22,7 @@ const DEFAULT_OG_IMAGE_URL = absoluteUrl(getDefaultOgImagePath());
1722
export const metadata: Metadata = {
1823
metadataBase: new URL(SITE_URL),
1924
title: {
20-
default: "Claws.supply — OpenClaw AI Agent Templates Marketplace",
25+
default: DEFAULT_SITE_TAGLINE,
2126
template: "%s",
2227
},
2328
description:
@@ -26,7 +31,7 @@ export const metadata: Metadata = {
2631
canonical: "/",
2732
},
2833
openGraph: {
29-
title: "Claws.supply — OpenClaw AI Agent Templates Marketplace",
34+
title: DEFAULT_SITE_TAGLINE,
3035
description:
3136
"Discover popular and latest OpenClaw agent templates, and launch faster with production-ready setups.",
3237
url: "/",
@@ -43,7 +48,7 @@ export const metadata: Metadata = {
4348
},
4449
twitter: {
4550
card: "summary_large_image",
46-
title: "Claws.supply — OpenClaw AI Agent Templates Marketplace",
51+
title: DEFAULT_SITE_TAGLINE,
4752
description:
4853
"Discover popular and latest OpenClaw agent templates, and launch faster with production-ready setups.",
4954
images: [DEFAULT_OG_IMAGE_URL],

0 commit comments

Comments
 (0)