The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Chasa listing page.
Paste your unpaid invoices. Get the follow-up email already written, in the right tone for how late it is.
docstoc never emails your clients for you — it drafts follow-ups you copy into Gmail, Outlook, or Apple Mail. Tone escalates with days overdue (friendly → firm → direct).
| URL | |
|---|---|
| Marketing | https://docstoc.io/ |
| App (Tool) | https://docstoc.io/app/ |
| Login | https://docstoc.io/app/login |
| Connector | https://docstoc.io/app/connector |
| Admin | https://docstoc.io/app/admin |
| API | https://api.docstoc.io |
| MCP | https://api.docstoc.io/mcp — read-only tools public; draft_chase_email requires session or API key |
Worker PUBLIC_APP_URL is https://docstoc.io (magic links, OAuth callbacks, Stripe return URLs, digest links).
Legacy chasa.io / api.chasa.io 301 to docstoc (Pages _middleware.ts + worker redirect). See scripts/oauth-redirect-uris.md for provider console URIs.
Go-live checklist
docstoc.io on Cloudflare Pages project chasa and wait for Active.www.docstoc.io → apex: handled by apps/web/functions/_middleware.ts (redeploy web).chasa.io / www.chasa.io → docstoc.io: same middleware.api.chasa.io → api.docstoc.io: worker middleware in apps/worker/src/lib/legacyHostRedirect.ts.api.docstoc.io — see scripts/oauth-redirect-uris.md../scripts/dmarc-remove-rua.sh (removes rua= from _dmarc.docstoc.io)../scripts/go-live-verify.sh.The order does not matter: browser-facing links are built from the origin the request came in on (see “App origin resolution” below), so pages.dev and chasa.io both keep working whichever is deployed first.
Magic links, post-login redirects, Stripe return URLs and team invites use the origin the user is actually on, not PUBLIC_APP_URL. The Pages /api proxy forwards it as X-Docstoc-App-Origin, and the worker honours it only if it matches lib/appUrl.ts's allowlist (PUBLIC_APP_URL, docstoc.io, www.docstoc.io, legacy chasa.io hosts, *.pages.dev project/preview hosts, localhost). This keeps preview deploys self-contained and makes the domain cutover zero-downtime.
Requests that arrive without a trusted origin — provider OAuth callbacks hitting api.docstoc.io directly, and the digest cron — still fall back to PUBLIC_APP_URL.
| Plan | Price | AI drafts | Team seats | Notes |
|---|---|---|---|---|
| Free | $0 | 5 / month (server-enforced) | 1 (owner only) | No signup required for drafts; sign in to upgrade |
| Pro | $14.99 / mo | Unlimited | 5 (owner + invites) | Flat workspace fee — not per-seat; most popular |
| Business | $39.99 / mo | Unlimited | 20 | Smart reply, risk score, demand letters, cert branding, SSL automation |
Stripe price IDs live in apps/worker/wrangler.toml as STRIPE_PRICE_SOLO (maps to Pro), STRIPE_PRICE_PRO / STRIPE_PRICE_ENTERPRISE (map to Business; non-secret). Billing portal and webhooks update accounts.plan and is_paid.
| Feature | Free | Pro+ |
|---|---|---|
| AI chase email drafts (tone by days overdue) | 5/mo | Unlimited |
15+ copy-paste email templates (/free-templates/) | ✓ | ✓ |
| CSV invoice upload (Tool) | ✓ | ✓ |
| Manual invoice list + aging board (Tool) | ✓ | ✓ |
| Rewrite softer / firmer / shorter | — | ✓ |
| Thank-you, reply-to-client, 3-step sequence, SMS/WhatsApp drafts | — | ✓ |
| Clients CRM + contact notes | — | ✓ |
| Aging sync (Tool → server) | — | ✓ |
| Reminder calendar (planned chase dates) | — | ✓ |
| Chase timeline + mark sent/paid | — | ✓ |
| Daily chase digest email (9 AM Eastern, approve-to-send) | — | ✓ |
| Reminder snooze + stop when marked paid | — | ✓ |
| Email open/click tracking on tracked HTML | — | ✓ |
| Default payment link (Stripe, PayPal, Venmo, Zelle…) | — | ✓ |
| Zapier templates (FreshBooks, Wave, Zoho Books) | — | ✓ |
| Smart reply classifier + promised pay date detection | — | Business |
| Client payment risk score | — | Business |
| Formal demand letter + collections evidence pack | — | Business |
| Custom certificate branding + SSL automation | — | Business |
| Custom branding (logo, late-fee hint) | — | ✓ (admin role) |
Outbound webhooks (chase.drafted, chase.sent, …) + HMAC signatures | — | ✓ (admin) |
| Click tracking (tracked copy HTML) | — | ✓ |
| Team invites (admin / member roles) | — | ✓ |
| Cloud storage PDF import (Dropbox, OneDrive, Box) | — | ✓ |
| QuickBooks Online + Xero overdue import | — | ✓ |
HTTP API + API keys (/api/v1/chase/draft) | — | ✓ |
| Zapier / Make via API key | — | ✓ |
Workspace roles: owner is always admin. Invited members can use Pro+ features; admin-only actions: branding, webhooks, connector OAuth connect/import, API key CRUD, team invites.
/app/*)| Route | Purpose |
|---|---|
/ | Tool — invoice list, AI drafts, CSV/PDF import, multi-select batch |
/login | Magic-link login + Cloudflare Turnstile |
/account | Plan, billing portal, payment link |
/team | Invite members, roles (Pro+) |
/clients | Client CRM (Pro+) |
/branding | Logo + late-fee hint (workspace admin) |
/webhooks | Outbound webhook URLs (workspace admin) |
/connector | Cloud storage + QBO/Xero OAuth + API keys |
/admin | Internal admin dashboard (separate cookie) |
All app routes except /login and /admin require a session. Unauthenticated users redirect to /login. SPA analytics require cookie consent (GDPR).
Same path as Docracy: lightweight catalogs in apps/web/app/src/lib/i18n/ (no i18next). LocaleProvider + EN|ES switcher on login, sidebar, and More sheet. P1 covers login / shell / welcome; expand catalogs for the rest of the app next. Preference stored as chasa_locale. Marketing HTML stays English until a later pass.
apps/web/public/)/invoice-follow-up, /payment-reminder, /overdue-invoice, /chase-invoices, /freelancer-invoice-follow-up/features/ (index, AI tone, templates), /docs/, /ai, /about/blog/ (3 articles + dynamic post.html)/free-templates/ — 15 generated template pages + index/privacy, /terms, /imprintsitemap.xml, robots.txt, 404.html, cookie consent, scroll-depth analytics_headersRegenerate free templates after editing apps/web/scripts/generate-free-templates.mjs:
Monorepo (npm workspaces):
| Package | Stack | Deploy target |
|---|---|---|
apps/web | React 18 + Vite + React Router | Cloudflare Pages (chasa) |
apps/worker | Hono + Cloudflare Workers + D1 + Workers AI | api.chasa.io |
Data: Cloudflare D1 (chasa-db). OAuth tokens encrypted at rest (AES-GCM, TOKEN_SECRET). Sessions in sessions table; magic links single-use (atomic consume).
AI: Cloudflare Workers AI (@cf/meta/llama-3.1-8b-instruct-fp8). Prompts wrap user content in delimiters to reduce injection.
| Prefix | Purpose |
|---|---|
/api/auth | Magic link request/verify, logout, Turnstile config |
/api/account | Profile, branding |
/api (emails) | generate-email, rewrite-email, generate-thank-you, generate-reply, generate-sequence, generate-sms |
/api/billing | Stripe checkout, portal, webhook |
/api/aging | Aging board CRUD + atomic batch sync |
/api/clients | Client CRM |
/api/reminders | Chase reminder calendar |
/api/team | Workspace members + invites |
/api/webhooks | Outbound webhook CRUD |
/api/connector | Legacy API key CRUD |
/api/account/connectors | Cloud + accounting OAuth |
/api/tracking | Tracked copy + click stats |
/api/analytics | Event track + pageview aggregates |
/api/v1/chase/draft | Public HTTP API (Bearer chasa_… key) |
/api/admin | Admin dashboard API |
/api/blog | Public blog posts from D1 |
/api/csp-report | CSP violation reports |
/mcp | MCP JSON-RPC (draft tools, template list) |
/api/t/:id | Click redirect (allowlisted URLs only) |
ai_usage), not client-sidestripe_events)X-Chasa-Signature: sha256=… HMACreport-uri → /api/csp-reportwrangler secret put …Without RESEND_API_KEY, magic links log to the worker console — copy the URL into your browser.
CI (.github/workflows/ci.yml) runs lint → test → static HTML validation → typecheck on every PR; auto-deploys worker + web on push to main when CLOUDFLARE_API_TOKEN is set.
After schema changes:
Migrations 0001–0011 include plans, admin/analytics, branding, webhooks, API keys, cloud connectors, clients/aging, parity features, and security hardening (rate limits, AI usage, Stripe idempotency, tracking link allowlist).
Protects /api/auth/request and admin login.
chasa-71s.pages.dev, chasa.io, localhostTURNSTILE_SITE_KEY in wrangler.toml [vars]wrangler secret put TURNSTILE_SECRET_KEYGET /api/auth/config.Local / without keys: verification bypassed with console warning. Test keys:
| Value | |
|---|---|
| Site key | 1x00000000000000000000AA |
| Secret key | 1x0000000000000000000000000000000AA |
cd apps/worker && wrangler d1 create chasa-db — paste database_id into wrangler.toml
wrangler d1 migrations apply chasa-db --remote
Stripe (test mode first): create two recurring Prices (Pro $14.99, Business $39.99). Copy price_… IDs into wrangler.toml:
STRIPE_PRICE_SOLO, STRIPE_PRICE_PRO, STRIPE_PRICE_ENTERPRISEwrangler secret put TOKEN_SECRET — openssl rand -hex 32
wrangler secret put STRIPE_SECRET_KEY (test key first)
Stripe webhook → https://api.chasa.io/api/billing/webhook — events: checkout.session.completed, customer.subscription.deleted → wrangler secret put STRIPE_WEBHOOK_SECRET
wrangler secret put RESEND_API_KEY — verify sending domain in Resend
Turnstile — see above
wrangler secret put ADMIN_PASSWORD — for /app/admin
Cloud storage OAuth (optional, Pro+):
| Provider | Redirect URI |
|---|---|
| Dropbox | https://api.docstoc.io/api/account/connectors/dropbox/callback |
| OneDrive | https://api.docstoc.io/api/account/connectors/onedrive/callback |
| Box | https://api.docstoc.io/api/account/connectors/box/callback |
https://api.docstoc.io/api/account/connectors/google/callback |
Google Sign-In redirect: https://api.docstoc.io/api/auth/google/callback
Step-by-step for each provider: scripts/connectors-docstoc-setup.md
QuickBooks Online + Xero (optional, Pro+):
| Provider | Redirect URI |
|---|---|
| QBO | https://api.docstoc.io/api/account/connectors/quickbooks/callback |
| Xero | https://api.docstoc.io/api/account/connectors/xero/callback |
See scripts/connectors-docstoc-setup.md for console steps.
Cloudflare Pages project chasa + custom domain chasa.io; Worker custom domain api.chasa.io
Switch to Stripe live keys/prices/webhook only after end-to-end test-mode smoke test
apps/worker/.dev.vars, gitignored)Stripe CLI for local webhooks:
Uses separate D1 (chasa-db-staging) — create and paste ID in wrangler.toml [env.staging].
generate-seo.mjs runs on every npm run build and writes:
sitemap.xml — all public pages (marketing, templates, blog)robots.txt — crawl rules + sitemap URLblog/feed.xml — RSS for blog posts{indexnow-key}.txt — IndexNow key file for Bing/Yandexindex.html / ai.html when env vars are set (see below)Press kit at /press — logos, boilerplate, suggested anchor text for backlinks.
Add property https://chasa.io at Search Console
Choose HTML tag verification → copy the content="…" value
Rebuild with the token:
Or use DNS TXT in Cloudflare (no rebuild needed).
Submit sitemap: https://chasa.io/sitemap.xml
URL Inspection on /, /app/, /payment-reminder, /free-templates/
Optional Bing: BING_SITE_VERIFICATION=… same as Google.
After deploy, ping IndexNow (Bing):
Site-side done: social links + sameAs schema on all pages, internal links from blog → landing pages, RSS + llms.txt.
Still manual (copy from press kit):
/app/ or a blog articlechasa.io/blog/ articles or /free-templates/, not just homepagechasa.iodocstoc is a product of RELACON GmbH, Vienna, Austria. See /imprint and /privacy.
Contact: founder@chasa.io