Last updated 2026-04-26
Launch checklist
A live tally of what's done, what's pending, and what needs you (the SaaS owner) to act. Designed to be read top-to-bottom; ship when everything's checked.
Status legend
- ✅ done
- ⚠️ partial / needs attention
- ❌ not started / blocker
1. Billing + payments
- ✅ Stripe Python lib installed (
stripe>=10.0) - ✅ Stripe secret key + price ID + webhook secret stored in
app_config(via/ops/integrations) - ✅ Stripe webhook endpoint registered for
checkout.session.completed+customer.subscription.deleted - ✅ Stripe Customer Portal route at
/admin/billing/portal(subscribers can manage card / cancel) - ⚠️ Stripe Customer Portal must be activated in Stripe Dashboard → Settings → Billing → Customer portal → Activate (one-time, before any subscriber tries to use the Manage button)
- ⚠️ Currently in test mode (
sk_test_…). Switch to live mode before charging real money: replace all three Stripe values at/ops/integrationswith their_live_equivalents. - ❌ End-to-end test checkout — trigger one from
/admin/billingwith test card4242 4242 4242 4242to validate the round-trip + webhook signature. Verifycompany.stripe_subscription_idlands in DB after success.
2. Analytics
- ✅ Google Analytics 4 wired (
GA4_MEASUREMENT_IDinapp_config, snippet renders on landing + every authed page) - ✅ First-party pageview tracking (
/ops/analytics) — pageviews, sessions, top pages, referrers, UTM, signup funnel, MRR - ✅ Engagement beacon (time-on-page + scroll depth) — captured per pageview, surfaced on
/ops/analyticstop-pages table - ⚠️ Google Search Console site verified — need to wire the GSC API into
/ops/analyticsfor organic-keyword data (next round; needs you to create a GCP service account JSON) - ❌ AI source detection — track when traffic comes from ChatGPT / Perplexity / Claude / Gemini
3. SEO + GEO
- ✅
/sitemap.xmlauto-generated (10 marketing pages + every help article + every blog post) - ✅
/robots.txtwith explicit AI crawler Allow block (GPTBot, PerplexityBot, ClaudeBot, anthropic-ai, Google-Extended, CCBot) - ✅
/llms.txtfor AI assistants (curated map per llmstxt.org) - ✅ Landing page: canonical, OpenGraph, Twitter Card, JSON-LD (Organization + WebSite + SoftwareApplication)
- ✅ Pricing page: canonical, OG, Twitter, JSON-LD (Product + FAQPage)
- ⚠️
/signuppage: needs OG + JSON-LD treatment - ⚠️ Blog post template: needs BlogPosting JSON-LD per post
- ❌ Per-page SEO audit panel on
/ops/analytics(title length, meta-desc, H1 count, word count flags) - ❌ Real social card image — currently using
/static/icon-192.png(square logo). Should be 1200×630 with branded layout for richer LinkedIn/Twitter previews. Manual creation needed.
4. Public pages
- ✅ Landing (
/) - ✅ Pricing (
/pricing) - ✅ Signup (
/signup) - ✅ Login (
/login) - ✅ Privacy (
/privacy) - ✅ Terms (
/terms) - ✅ Trust & security (
/trust) - ✅ Help (
/help) + per-feature articles - ✅ Blog (
/blog) - ✅ Roadmap (
/roadmap) - ⚠️ Privacy + Terms need a real lawyer review before charging real customers — current versions are launch-grade boilerplate, not bulletproof
5. Authentication + access
- ✅ Email + password signup with UTM attribution capture
- ✅ Forgot password (
/forgot-password) - ✅ Per-employee invite emails (with 7-day token)
- ✅ 3 roles (employee / manager / admin) + 3 module flags (Finance / HR / Legal) — see Roles
- ✅
/ops/*strictly limited to product owner (allowlist viaOPS_ACCESS_EMAILSenv) - ✅ Multi-tenant isolation: every query scopes by
company_id; defense-in-depth on cross-tenant joins
6. Email
- ✅ SMTP configured (IONOS) — invite emails, password reset, manual delivery, weekly digest, flag-change notifications all working
- ⚠️ Reputation warm-up: send volume should ramp gradually for the first ~30 days post-launch to avoid spam folder. Avoid sending 100s on day 1 from a never-used domain.
7. Multi-tenant data
- ✅ Per-tenant SQLite isolation enforced via WHERE clauses
- ✅ M365 OAuth (per-employee, per-tenant)
- ✅ QuickBooks Online (per-entity, per-tenant)
- ✅ Multi-entity rollups (US / India / Switzerland / Ukraine, etc.) with FX rates
- ✅ AR/AP dashboard (live + per-entity + consolidated)
8. Reliability + monitoring
- ✅ systemd-managed gunicorn (
/etc/systemd/system/timeopt.service) - ✅ Audit log (every important action recorded with actor + timestamp)
- ❌ Error tracking — no Sentry / Rollbar / Honeybadger. Production 500s only show in journalctl. Wire one before launch so user-facing errors surface.
- ❌ Backups — instance/timeopt.db is on a single VPS. No off-site backup. At minimum: nightly cron that gzips + uploads to S3 / R2 / IONOS object storage.
- ❌ Uptime monitor — no external pingdom/UptimeRobot. Add one so you find out about downtime before customers.
9. Customer-facing UX
- ✅ Onboarding flow (signup → first project → first time entry)
- ✅ Per-role manual at
/help/manual(auto-extends with module flags — manager-with-Finance-flag sees both manager + Finance docs) - ✅ Help docs comprehensive: every shipped feature has a doc
- ⚠️ Empty state polish: new tenants land in many pages with zero data. The empty states exist but vary in quality.
- ❌ Onboarding checklist for new admin — first-login walkthrough ("invite your team, set hourly rates, install desktop client, …"). Drives activation.
10. Compliance + GDPR
- ✅ IP hashing in pageview log
- ✅ DSR / GDPR module in Legal (track + auto-set 30-day SLA on incoming requests)
- ❌ Self-service GDPR data export —
/api/me/exportfor any logged-in user to dump their own data as JSON - ❌ Cookie banner — minimal cookie use today (session, theme), but EU visitors expect a banner. Required if you want to advertise to EU markets.
11. Content
- ✅ At least one blog post live → check
/blog - ⚠️ Pricing comparison content — landing + pricing make claims; pages contrasting OtiumWork vs Clockify / Toggl / Harvest would draw bottom-funnel SEO
- ⚠️ Case study or screenshot gallery — "show, don't tell". Even one annotated screenshot reduces hesitation
- ⚠️ Demo video — 60-second screen recording of the core loop (capture → review → bill). Closes deals.
12. Domain + infra
- ✅ TLS (otiumwork.com)
- ✅ Reasonable DNS (A record to IONOS VPS)
- ⚠️ MX records pointing to IONOS for
info@otiumwork.com - ❌ DKIM + SPF + DMARC — verify all three for outbound email (invite, reset, digest) so your messages don't land in spam
Quick "ready to launch" sanity test
- Open https://otiumwork.com in incognito → loads in <1s, no console errors
- Click Pricing → understand the price + click Start free trial
- Sign up with a fresh email → end up logged in within 30 seconds
- Add 1 employee → see invite email arrive
- As admin →
/admin/billing→ click Subscribe → complete Stripe Checkout (test card) → return to billing page → seeSubscribedstatus - Click Manage subscription → land in Stripe Customer Portal → cancel → return → see status change
- Check
/ops/analytics10 minutes later → see your visit in pageview count, your signup in funnel
If all 7 work end-to-end without you intervening, you're launch-ready.
Owner-only items (this doc surfaces them; you handle the actual setup)
- Stripe live-mode keys
- Sentry account + DSN
- Backup destination (S3/R2 bucket + access key)
- Uptime monitor account
- DKIM/SPF/DMARC DNS records (via IONOS DNS panel)
- Real lawyer review of Privacy + Terms
- Demo video creation
See something wrong or outdated in this article? Report it →