I Built a Paid Article Platform in One Day with Claude Code
Publishing platforms take too much. 15-20% fees on every sale. Sell a $10 article and you get $8.
So I built my own. With Claude Code, it took one day.
https://draft-publish.com
Why I Built It
The options for selling paid articles are limited.
| Platform | Fee | Problem |
|---|---|---|
| Medium | 0% (reader pays $5/mo) | Writers don't get paid per article |
| Substack | 10% | No CLI, browser-only editing |
| Gumroad | 10% | Not designed for articles |
| Self-hosted WordPress | 0% | Payment integration is painful |
I'm an engineer. I want to write articles in my terminal and publish with a single command. Clicking around in a browser editor isn't my style.
So I decided to build a platform where you write Markdown and run draft push to publish.
Tech Stack
- Backend: FastAPI + uvicorn (Python 3.12)
- Frontend: Jinja2 templates + contenteditable editor (no React)
- DB: SQLite (WAL mode)
- Payments: Stripe Checkout + Stripe Connect
- Auth: Google OAuth + X OAuth + password + SSH public key (for CLI)
- Hosting: Mini PC at home + Cloudflare Tunnel
- CLI: typer + rich
Why no React? Simple — compatibility with Claude Code. "Build this page with Jinja2 templates" moves dramatically faster than "design React components." No need for an SPA anyway.
How the Day Went
Started in the morning. By evening, the platform was live and ready to sell articles.
Sprint 1 (Morning): Foundation
Told Claude Code "I want to build a paid article platform with FastAPI + SQLite + Stripe" and built basic CRUD with Stripe Checkout integration.
- Article CRUD (create, list, detail, delete)
- Markdown rendering (markdown-it)
- Stripe Checkout (purchase → Webhook → DB update)
- Paywall (`` marker splits free/paid content)
- User auth (Google OAuth)
The paywall mechanism is simple. Write `` in your Markdown. Everything above it is free to read. Everything below requires purchase. The server splits the HTML and only returns the free portion to non-buyers.
Sprint 2 (Early Afternoon): Editor
Built a hybrid contenteditable + Markdown editor. Split view with Markdown on the left, live preview on the right.
Features:
- Toolbar (headings, bold, italic, links, images, tables, code blocks)
- Keyboard shortcuts (Ctrl+B, Ctrl+I, Ctrl+K, Ctrl+E)
- Slash commands (type / for a menu)
- Image drag & drop
- Auto-save (every 5 seconds)
The slash commands are Notion-style. /image to insert an image, /table for a table, /code for a code block. Told Claude Code "implement Notion-like slash commands" and it just worked.
Sprint 3 (Late Afternoon): CLI
This is the part I'm most proud of. Built a CLI with GitHub-style SSH authentication.
# Install
pipx install git+https://github.com/s-saga011/draft-publish.git
# Set server
draft remote https://draft-publish.com
# Create an article
draft new "Article Title" --price 5
# Put article.md and images in the folder
draft push
draft push auto-detects Markdown files and images in the folder, uploads them to the server, and rewrites image paths in the Markdown automatically.
Authentication uses SSH public keys. Register your public key on the web Settings page, and the CLI signs requests with your private key. GitHub-style, so no passwords to store.
Sprint 4 (Evening): Deploy
Deployed to a mini PC at home (i9-9880H, 32GB RAM).
# Auto-start with systemd
sudo systemctl enable draft
# Expose via Cloudflare Tunnel
sudo systemctl enable cloudflared
Cloudflare Tunnel eliminates the need for port forwarding and SSL certificates. The tunnel connects to localhost, and Cloudflare handles HTTPS. Infrastructure cost is zero beyond the domain ($10.46/year).
Payments: Stripe Connect
Since this is a creator platform, purchase payments need to be automatically split with creators. Used Stripe Connect.
How it works:
- Creator connects their Stripe account in Settings
- Reader purchases an article → Stripe Checkout handles payment
- Stripe automatically sends funds to the creator (minus 3% platform fee)
Total fee: Stripe payment fee 3.6% + platform 3% = 6.6%. Less than half of what other platforms charge.
Added a 30-minute refund guarantee too. One-click refund within 30 minutes of purchase. This is designed to weed out empty content. Articles with high refund rates naturally stop selling.
Multilingual Support
Both the articles and UI support English and Japanese.
- Templates: All text output through a translation dictionary (
i18n.py) - Auto-detection from browser language + manual toggle
- Currency: Japanese → JPY, English → USD (Stripe payments switch currency too)
- CLI:
draft lang ento switch to English
I wanted the platform ready to sell internationally. Technical articles and data analysis articles have demand regardless of language.
Actually Selling Articles
Building the platform means nothing if nobody uses it. So I became my own first customer.
I ran AI-powered investment backtests and turned the results into articles. Backtested all S&P 500 stocks — 730,000 data points.
Workflow:
- Write backtest code with Claude Code
- Generate charts with matplotlib
- Ask Claude Code to "turn these analysis results into an article"
- Polish the output Markdown and
draft push
From article creation to publishing, no browser needed. Everything happens in the terminal.
Current State
- Live in production: https://draft-publish.com
- Articles: 10 (Japanese/English)
- CLI: One-line install via pipx
Still Todo
- Exchange rate API integration (currently hardcoded)
- More users (marketing)
Technically Interesting Points
SQLite Is Enough
"SQLite for a paid service?" you might think. But SQLite with WAL mode enabled is surprisingly capable. It handles up to ~100K monthly page views with no issues. No need to migrate to PostgreSQL until concurrent writes exceed 10 per second.
Server resource usage: 5.4GB/31GB memory, 0.04 CPU load, 10% disk. Nothing is happening.
Cloudflare Tunnel
Cloudflare Tunnel was the best choice for exposing a home server.
- No port forwarding (don't touch router settings)
- No SSL certificate management (Cloudflare handles it)
- Free DDoS protection included
- No static IP required
Write 4 lines in config.yml and register with systemd. Done.
tunnel: xxxxx
credentials-file: /home/user/.cloudflared/xxxxx.json
ingress:
- hostname: draft-publish.com
service: http://localhost:8001
- service: http_status:404
SSH Key Authentication (CLI)
Implemented GitHub-style SSH authentication from scratch.
- Server generates a random nonce (challenge) and returns it
- Client signs the nonce with their private key and sends it back
- Server verifies the signature against registered public keys
No passwords to store. If ~/.ssh/id_ed25519 exists, authentication is automatic.
Building with Claude Code
Getting a working product in one day was thanks to Claude Code. What worked well:
- Stripe Webhooks, OAuth, SSH auth — anything requiring "read the spec and implement it precisely" was fast
- Jinja2 template mass-production was absurdly fast (full EN/JP support for all pages in half a day)
- Bug identification and fixes were fast (paste the error log and get the cause + fix)
What was tricky:
- Stripe Connect test vs production environment switching caused confusion
- Cloudflare Tunnel DNS setup had a small hiccup
Both were external service configuration issues, not Claude Code problems. The code itself worked almost first try.
Takeaway
A paid article platform is buildable in one day with today's tech stack.
- FastAPI + SQLite + Stripe is enough
- Cloudflare Tunnel to expose a home server for free
- Claude Code to 10x development speed
6.6% fee, 30-minute refund guarantee, CLI publishing. If you're tired of platform fees, give it a try.
https://draft-publish.com
CLI repo: https://github.com/s-saga011/draft-publish