Built with Wasp, based on the Open Saas template.
- Make sure you have the
.env.clientand.env.serverfiles with correct dev values in the root of the project. - Run the database with
wasp start dband leave it running. - Run
wasp startand leave it running. - [OPTIONAL]: If this is the first time starting the app, or you've just made changes to your entities/prisma schema, also run
wasp db migrate-dev.
Premium blog posts can be bought per request — by humans or agents — over the x402 payment protocol, in USDC on Base:
GET /api/posts/:slug/full # JSON (agents)
GET /api/posts/:slug/read # rendered HTML (humans — unpaid browser requests
# get the @x402/paywall wallet-connect payment UI)
Unpaid requests for premium posts return 402 Payment Required with the
payment requirements in the PAYMENT-REQUIRED header; clients using
@x402/fetch (or any x402 client) pay and retry automatically. Free posts are
served without payment. This complements the subscription paywall — logged-in
subscribers read via the app as usual.
Config (.env.server): set X402_WALLET_ADDRESS to your receiving EVM
address (unset = endpoint disabled; premium posts return 503, never unpaid
content). X402_NETWORK is base-sepolia (testnet, default) or base
(mainnet — requires a mainnet facilitator such as Coinbase CDP's, via
X402_FACILITATOR_URL). Per-post prices come from the optional price
frontmatter field (USD, e.g. price: "0.10"), defaulting to
DEFAULT_PREMIUM_PRICE_USD in src/blog/content.ts.
Smoke test against a running app: npm run smoke:x402 (add
X402_SMOKE_PRIVATE_KEY=0x... with a funded Base Sepolia wallet to also
exercise the paid path; get testnet USDC at https://faucet.circle.com).
Posts with audio: true in their frontmatter get a TTS narration (OpenAI,
generated at content-sync time, stored privately in S3 at
blog-audio/<slug>.mp3). Two ways to get it:
GET /api/posts/:slug/audio # x402-paid; the response body is the mp3
GET /api/posts/:slug/full # paid JSON also includes a short-lived audioUrl
Pipe it straight into a player: <x402 fetch> /api/posts/<slug>/audio | ffplay -autoexit -nodisp -i -.
Free posts with audio serve it unpaid. Requires OPENAI_API_KEY and the
AWS_S3_* vars at sync time.