Blueprint

Project Automated Post Drafter from Solo SaaS Ops Logs

Turn daily ops logs into voice-true AI productivity post drafts in seconds

Primary user

Solo bootstrapped AI productivity SaaS founders with intermediate Next.js/Cloudflare experience who run operations alone

Naming note: The title is provisional and needs domain, trademark, handle, and competitor-conflict checks before launch

Product Spec Brief

This is the plain-English opening brief for the Blueprint: what it is, who it helps, what pain it removes, and what must be true for the MVP to count as working.

Working Title

Project Automated Post Drafter from Solo SaaS Ops Logs

Naming Note

provisional name; run separate availability check before launch

What We Are Building

A deployable full-stack Next.js application on Cloudflare (using Workers/Hono, D1, and AI Gateway) that accepts simple daily ops logs from a solo AI productivity SaaS founder via a web UI, stores them with light tagging in D1, extracts review-ready post drafts using a voice-tuned prompt via AI Gateway, and surfaces the draft in an in-app dashboard (with optional email/Slack delivery) for final human approval before any external use.

Who It Is For

Solo bootstrapped AI productivity SaaS founders who already run daily operations and customer support alone, possess intermediate full-stack experience with Next.js and Cloudflare, and need a repeatable system that turns existing work logs into consistent niche content without adding new manual capture steps.

Problem It Solves

Founders currently lose timely niche observations because every hour is consumed by product work and support, leaving only fragmented attention that produces blank-page guilt instead of stored angles; the app captures the observation at the moment it occurs and converts it into a ready draft on a weekly or on-demand schedule.

Why This Product Exists

Existing tools either require the founder to supply topics manually or generate generic outputs that demand extensive rewriting; this blueprint supplies the missing end-to-end harvesting layer that keeps all logic and data inside the founder's own Cloudflare account.

MVP Proof

When a sample ops log containing one daily support interaction and one feature decision is submitted through the deployed app's UI, the system returns a single complete, editable draft (viewable in the dashboard) that includes traceable source notes and a voice-match indicator, ready for human review within the same app.

Not Building in V1

Multi-platform auto-posting, analytics dashboards, custom model fine-tuning, or any customer-facing output without explicit human approval.

Blueprint Contents

The remaining imported markdown is preserved here so type-specific build details, tables, scripts, setup steps, tests, and citations stay intact.

How to Use This Blueprint

Use this Blueprint to turn each automation into trigger, action, condition, retry, error, logging, and approval blocks. Ask AI to verify connector names, auth scopes, permissions, quotas, and trigger behavior against current docs before activating anything.

Paste the Blueprint into a strong current AI model with reasoning enabled. Enable web search when you need current platform docs, package choices, pricing, UI patterns, APIs, product examples, or licensing checked. Ask the AI to keep the MVP boundary intact, challenge risky assumptions, cite current docs for unstable claims, and produce an implementation plan before building.

First prompt to use:

Using this Blueprint as the exact spec, convert the workflows into trigger/action/error/retry blocks for my environment. Validate current connector names, permissions, quotas, and trigger conditions against official docs. Identify failure modes and ask the smallest set of setup questions before implementation.

Do not skip:

  • Validate assumptions, licensing, permissions, current docs, and any platform limits before production build.
  • Confirm test users, roles, and access boundaries before building screens or workflows.
  • Seed realistic test data before judging formulas, filters, or performance.
  • Run the acceptance tests with real users in each role before launch.
  • Keep human review gates for security, approvals, compliance, and production sharing.
  • Avoid production data until the MVP passes end-to-end tests.

Core User Flows

Flow 1: Submit Log → AI Extract → Review Draft (Primary)

The core loop that converts raw operational notes into review-ready content. This is the only flow that must work flawlessly for MVP.

  1. User navigates to /logs/new — The submit page loads immediately with a free-form textarea. No structured fields required; messy input is expected and handled.
  2. User pastes or types raw ops notes — Any format works: bullet lists, timestamps, shorthand, stream-of-consciousness. A lightweight tagging interface lets the user add 1-3 tags (e.g., "support", "feature-decision") before submission.
  3. User clicks "Submit Log" — The form submits via a Next.js Server Action. The log is validated (minimum 10 characters), stored in the ops_logs table in D1 with the current user's ID and timestamp, and associated tags are written to the log_tags junction table.
  4. AI extraction pipeline triggers — The system calls AI Gateway with the voice-tuned system prompt (see Prompt Templates section), passing the log content and the user's calibrated voice signature. The call uses GPT-4o at temperature 0.4 with strict JSON output mode.
  5. Draft is stored — The AI response is parsed and validated against the output JSON schema. On success, a record is inserted into the drafts table with status pending, the full draft content, source citations, voice-match score, and token usage metadata. The AI call is logged to ai_extracts for audit.
  6. User is redirected to /drafts — After a 1.5-second delay with a success toast ("Log submitted. AI is extracting drafts..."), the browser navigates to the Review Queue.
  7. Draft appears in the review queue — The new draft card shows: title, body preview, voice-match score badge, source notes count, and action buttons (Approve, Edit & Approve, Reject).
  8. Human review gate — The user expands the draft, reads the full content, checks the Source Notes panel for traceability, and evaluates the Voice Match indicator. They can edit inline before making a decision.
  9. Decision is recorded — On Approve: status becomes accepted, a confirmation toast appears, and export/share options unlock. On Reject: a reason is required (dropdown: Inaccurate, Wrong voice, Missing context, Other), status becomes rejected, and the draft is soft-archived after 30 days. On Edit & Approve: the edited content overwrites the draft, status becomes accepted, and the edit is logged.
  10. Audit trail written — Every decision is appended immutably to the ai_extracts table with timestamp, user ID, action, and reason.

Flow 2: Dashboard Check → Quick Actions

The morning ritual page that tells the founder what needs attention.

  1. User logs in and lands on /dashboard — The dashboard is the default authenticated landing page.
  2. Stats row loads — Four cards render: Total Logs (lifetime count), Pending Review (count of drafts with status pending — badge highlighted if >0), Approved This Week (count of accepted drafts in last 7 days), and AI Extractions (total ai_extracts count).
  3. Recent activity list — The last 5 logs or drafts appear with status badges, log date, and a content preview. Clicking any item navigates to its detail view.
  4. Quick actions — The primary CTA "Submit New Log" is always visible. If pending drafts exist, a secondary CTA "Review N Pending Drafts" appears with an amber badge, linking directly to /drafts.
  5. Empty state — For first-time users with zero data, the dashboard shows a welcome message, a "Submit Your First Log" button, and an optional "Load Sample Data" button that creates 1-2 example logs with pre-generated drafts so the user can explore the review workflow.

Flow 3: Browse History → Revisit Past Logs

Full audit trail for accountability and content reuse.

  1. User navigates to /history — A server-side rendered data table loads with the 25 most recent logs, ordered by log_date descending.
  2. Table columns — Date | Log Preview (first 80 chars) | Tags | Draft Status (badge: Pending/Accepted/Rejected/None) | Actions ("View Details" link).
  3. Search and filter — A text input searches across content via a D1 LIKE query. A status filter dropdown filters by draft status. A tag filter shows only logs with selected tags. All filters are server-side.
  4. Row expansion or detail view — Clicking a row opens a detail panel or navigates to /logs/[id], showing the full log content, all associated tags, the generated draft (if any) with its status, and the full source citations list.
  5. Re-extraction — From the detail view, a "Regenerate Draft" button re-runs the AI extraction pipeline on the existing log (useful if voice profile was updated since the first extraction). This creates a new draft record and supersedes the old one.
  6. Pagination — Server-side pagination at 25 rows per page. D1 offset/limit queries with indexed user_id + log_date for performance.

Screen and View Inventory

PageRoutePrimary JobPrimary CTAEmpty StateError StatePermission
Dashboard/dashboardMorning overview: stats, recent activity, quick actions"Submit New Log" (→ /logs/new)Welcome message + "Submit Your First Log" + optional "Load Sample Data"Segment error.tsx: error card with "Something went wrong loading your dashboard" + Retry buttonAuth-only; middleware redirects unauthenticated to /login
Submit Log/logs/newFriction-free input for raw operational notes"Submit Log" (Server Action)N/A — form page always readyForm-level: Zod inline errors. Server-level: Sonner toast "Failed to process log. Please try again."Auth-only
Review Queue/draftsHuman review gate — approve, reject, or edit AI drafts before any external usePer-item: "Approve" / "Edit & Approve" / "Reject". Bulk: "Approve All" / "Reject All""All caught up! No drafts pending review." + "Submit a New Log" outline buttonSegment error.tsx: "Unable to load drafts" + retry. Per-item: toast feedbackAuth-only
History/historySearchable, filterable audit trail of all logs and drafts"View Details" (per row)"No history yet. Your submitted logs and approved drafts will appear here." + "Submit Your First Log"Segment error.tsx: "Unable to load history" + retry. Pagination errors inlineAuth-only
Settings/settingsProfile, voice calibration, preferences, connected accounts"Save Changes" (per section)N/A — settings always have form fieldsPer-section error display. Profile save: inline error. Toast for async confirmationAuth-only

Navigation Structure

A collapsible sidebar (shadcn/ui) on desktop, hamburger-triggered Sheet drawer on mobile.

Sidebar items (top to bottom):

IconLabelRouteBadge
LayoutDashboardDashboard/dashboard
FileTextSubmit Log/logs/new
ClipboardListReview Queue/draftsPending draft count
RotateCcwHistory/history
SettingsSettings/settings

Keyboard shortcut: Ctrl/Cmd+B toggles sidebar collapse to icon-only mode.

Mobile (<768px): Sidebar collapses to hamburger menu. Sheet slides from left at 18rem width. Content padding reduces from p-6 to p-4. Toast notifications move to top-center.


First-Run Experience

The first-run flow prioritizes getting the user to their first successful draft as fast as possible. No forced tutorial; the UI is self-explanatory for intermediate developers.

Step 1: Voice Calibration (One-Time Setup)

On first login with zero data, the dashboard empty state includes a banner: "Before you submit your first log, set up your writing voice so AI drafts sound like you." Three substeps:

  1. Voice Extraction — The user pastes 3-5 existing blog posts or writing samples into a textarea. The system runs a voice extraction prompt via AI Gateway that returns a structured Voice Pattern block (Identity, Audience, Voice Rules, Structural Patterns, Output Calibration). This is stored in the user's profile.
  2. Gap Test — The user reviews a 100-word sample paragraph generated in their extracted voice, identifies discrepancies, and edits the Voice Rules directly in a text editor.
  3. Save Profile — The validated Voice Pattern block is saved to the users table (or KV) as voice_profile. It can be re-calibrated anytime from Settings.

Estimated time: 3-5 minutes. Skippable — user can submit logs with a default voice profile and calibrate later.

Step 2: First Log Submission

After voice setup (or skip), the dashboard empty state shows the primary "Submit Your First Log" CTA. Clicking it navigates to /logs/new. The textarea has a placeholder with a real example:

Paste your operational notes here... e.g.,

SUPPORT: User emailed saying they loved the transcription feature but
wished it worked offline. They'd pay double for offline mode.

PRODUCT: Decided to kill the PDF export feature. Only 0.3% of users
ever used it. Deleted 2,400 lines of code today. Felt surprisingly good.

After submission, the user is redirected to /drafts where their first AI-generated draft appears.

Step 3: First Draft Review

The first draft card in the review queue includes subtle tooltip hints on the Source Notes panel ("These links trace each claim back to your original log") and Voice Match indicator ("Score above 75% means the draft sounds like you"). Tooltips are one-time, tracked via localStorage flag hasSeenTooltips.

An optional "Load Sample Data" button on the dashboard creates 1-2 pre-generated example drafts in pending state, letting the user explore the review workflow with realistic content before committing their own data.


Data Model

Cloudflare D1 (SQLite) with 7 tables. Drizzle ORM for type-safe queries. Attachments table can be deferred post-MVP if file storage is not needed immediately.

SQL CREATE TABLE Statements

SQL
106 lines
-- ============================================================
-- OpsLog Schema for Cloudflare D1 (SQLite)
-- ============================================================

PRAGMA foreign_keys = ON;

Drizzle ORM Schema

TYPESCRIPT
162 lines
// src/db/schema.ts
import {
  sqliteTable, integer, text, real, primaryKey, index, uniqueIndex,
} from "drizzle-orm/sqlite-core";
import { relations, sql } from "drizzle-orm";
import { createId } from "@paralleldrive/cuid2";
TYPESCRIPT
21 lines
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  out: "./drizzle",
  schema: "./src/db/schema.ts",
  dialect: "sqlite",

Database Client Setup

// src/db/client.ts
import { drizzle } from "drizzle-orm/d1";
import * as schema from "./schema";

export function getDb(d1Binding: D1Database) {
  return drizzle(d1Binding, { schema });
}

Sample Records

users:

idemailnamerolecreated_at
usr_abc123def456alice@example.comAlice Chenuser1753987200

ops_logs:

iduser_idlog_datecontentmoodenergy_levelword_countcreated_at
1usr_abc123def4562025-07-28Morning standup ran long due to deployment issues. Fixed the DNS misconfiguration for staging by noon. Paired with Bob on the auth migration.good7421753728000

tags:

idnamecolordescription
1standup#4CAF50Daily standup notes
2blocker#F44336Blocked items
3shipped#2196F3Completed/deployed work

log_tags:

log_idtag_id
11
13

drafts:

idlog_iduser_idstatuscontentmodel_usedtokens_inputtokens_outputconfidencecreated_at
11usr_abc123def456pending## Daily Summary - Jul 28, 2025\n\n- Infra: Resolved DNS misconfiguration...gpt-4o4863120.921753728600

Migration Commands

# Generate migration from schema
npx drizzle-kit generate --name=init

# Apply to local database
npx wrangler d1 migrations apply <db-name> --local

# Apply to production
npx wrangler d1 migrations apply <db-name> --remote

# Verify
npx wrangler d1 migrations list <db-name>

# Optimize indexes after creation
npx wrangler d1 execute <db-name> --command="PRAGMA optimize"

Automation Workflow Inventory

AI Extraction Pipeline

The pipeline that converts a submitted ops log into a review-ready draft.

Prompt
24 lines
[Log Submitted]
    |
    v
[Store log in D1] ----(on success)----> [Queue AI extraction job]
    |                                          |
    v                                          v

Pipeline Steps

  1. Log Storage — The submitted log is inserted into ops_logs via a Server Action. Tag associations are written to log_tags in the same transaction using D1 batch operations.
  2. AI Extraction Trigger — Two options based on load:
    • In-request processing (default for MVP, 30 logs/month): The AI call happens synchronously within the Server Action, returning the draft to the client after 5-25 seconds.
    • Queue-based processing (scalability option): The log ID is sent to a Cloudflare Queue for background processing. The queue consumer calls AI Gateway and stores the result.
  3. AI Gateway Call — The system sends a messages array to AI Gateway with the voice-tuned system prompt and the log content as user message. Model: GPT-4o, temperature 0.4, strict JSON output mode.
  4. Response Handling — The JSON response is validated against the output schema. On success, a drafts record is created with status pending. On failure, the error is logged to ai_extracts and a retry is scheduled (max 3 attempts with exponential backoff: 2s, 5s, 10s).
  5. Draft Surfacing — The new draft appears in the /drafts review queue. If the user is already on that page, a toast notification appears: "New draft ready for review."
  6. Human Review Gate Enforcement — This is an architectural constraint, not a prompt instruction. The status field on the drafts table controls what actions are possible:
    • pending: Only "Approve", "Reject", "Edit & Approve" actions available. No external sharing enabled.
    • accepted: Share/Export/Email/Slack options unlock.
    • rejected: Draft is hidden from queue after 30 days.
    • superseded: Replaced by a newer draft; read-only.

Retry Logic

AttemptDelayAction on Failure
1ImmediateIf AI Gateway returns 5xx or invalid JSON, wait 2s and retry
22 secondsIf still failing, wait 5s and retry
35 secondsIf still failing, mark draft status as error, log full error to ai_extracts, notify user via toast with "Retry" button

Error Handling

  • AI Gateway timeout (>45s): Returns error to client, draft record created with placeholder "Draft generation timed out. Click to retry."
  • Invalid JSON response: Logged to ai_extracts, retry initiated. If all retries exhausted, user sees "Draft generation failed. The AI returned an unexpected format. Retry?"
  • Rate limiting (429): Automatic backoff with jitter. Max wait 30s.
  • Model unavailability: Fallback to Claude Sonnet via AI Gateway fallback routing (configured in dashboard).

Human Review Gate Rules

  1. No external output without approval — Share, Export, Email, Slack buttons are disabled/greyed out until status = 'accepted'.
  2. Edit resets approval — Any edit to an accepted draft changes status back to pending, requiring re-approval.
  3. Rejection requires reason — Rejection must include a reason from dropdown (Inaccurate, Wrong voice, Missing context, Other) + optional text note.
  4. Timeout safety — Drafts in pending state auto-archive after 30 days of inactivity.
  5. Audit trail — Every review decision (who, what, when, reason) is logged immutably to ai_extracts.
  6. Single reviewer — For MVP, only the submitting user can approve their own drafts (no multi-user approval chain).

Prompt Templates

Voice Calibration Prompt

Run once during first-run setup. Paste 3-5 writing samples where indicated.

Prompt
24 lines
You are a voice encoding specialist. Analyze the writing samples below
and extract the author's Voice Patterns into a structured block.

IDENTITY (2 sentences): Who the author is, what they do, credibility markers.
  Specific, not generic.

Main Extraction System Prompt

XML
72 lines
<SYSTEM_PROMPT>

## ROLE & CONTEXT
You are a ghostwriter for a solo bootstrapped AI productivity SaaS founder.
Your output must sound exactly like the founder wrote it themselves -- raw,
honest, with specific operational detail and zero corporate polish. You

User Message Template

Generate a blog post draft from the following operational logs.

Voice profile: [validated voice pattern block or reference to stored profile]
Post type: [standard | deep_dive]
Target audience: [indie_hackers | ai_builders | founders]
Date range: [e.g., Jan 10-16, 2025]
Focus angle (optional): [technical_decision | customer_lesson | growth_moment]

Log entries:
[paste log content here]

Respond ONLY with valid JSON matching the output schema. No markdown fences.

Output JSON Schema

JSON
55 lines
{
  "$schema": "https://json-schema.org/draft-07/schema",
  "title": "FounderBlogDraft",
  "type": "object",
  "required": ["metadata", "draft", "source_citations", "voice_match_note"],
  "properties": {

Model Parameters

ParameterValueReason
Primary Modelgpt-4o-2024-08-06 or laterBest balance of instruction following, voice adherence, structured JSON output via response_format: { type: "json_schema" }
Fallback Modelclaude-sonnet-4-20250514Superior for nuanced voice work when GPT-4o drifts
Temperature0.4Lower than default for voice consistency; higher than 0.2 to preserve natural cadence
Top-P0.85Balanced filtering -- prevents unlikely tokens while allowing vocabulary variety
Top-K50Moderate constraint that works well with Top-P
Max Tokens2,048Sufficient for 1,200-word posts plus JSON wrapper. Increase to 4,096 for deep-dives
Frequency Penalty0.3Prevents repetitive signature phrases
Presence Penalty0.2Light encouragement for topic variety
JSON Modestrict: trueGuarantees schema adherence
System Prompt CachingEnable via cache_controlReduces latency and cost 40-60% on repeated calls

Temperature by Task Stage

StageTemperatureWhen to Use
Voice extraction/calibration0.7Creative exploration during voice discovery
Draft generation (production)0.4Voice consistency
Self-check/evaluation0.2Deterministic compliance checking
Title generation0.6Slightly more creative for hook optimization

Build Order

Week 1-2: Project Setup + D1 Schema + Auth

DayTaskDeliverable
1Create Cloudflare account, install wrangler, run npm create cloudflare@latestProject scaffolded
2Install @opennextjs/cloudflare, Drizzle ORM, Better Auth dependenciesDependencies installed
3Configure wrangler.jsonc, open-next.config.ts, next.config.tsConfig files ready
4Create D1 database, apply initial schema migrationDatabase live with all 7 tables
5Set up Drizzle client, create database connection layersrc/db/client.ts working
6-7Configure Better Auth with D1 + KV, create auth routes/api/auth/[...all]/route.ts handling login
8-9Create login/signup pages, protect dashboard routesAuth flow complete, middleware redirects working
10Test auth end-to-end locally, verify D1 writesLocal auth + DB pipeline verified
11-12Create sidebar navigation, dashboard layout shellDashboard layout with nav rendering
13-14Create dashboard page with stats cards (static data)/dashboard loads with stat placeholders

Key commands:

npm create cloudflare@latest my-app -- --framework=next --experimental
pnpm add @opennextjs/cloudflare drizzle-orm better-auth better-auth-cloudflare
pnpm add -D drizzle-kit wrangler
npx wrangler d1 create my-app-db
npx drizzle-kit generate --name=init
npx wrangler d1 migrations apply my-app-db --local

Week 3-4: Log Submission + Storage

DayTaskDeliverable
15-16Create ops_logs table queries, insert with tagsServer Action for log creation
17-18Build /logs/new page with auto-expanding textareaSubmit page with form validation
19-20Implement tag input (comma-separated, inline pills)Tagging UI functional
21-22Create loading.tsx and error.tsx for submit flowSkeleton + error states
23-24Wire form submission to D1, test with sample dataLogs stored with tags in D1
25-26Add success toast, redirect to /draftsPost-submit UX complete
27-28End-to-end test: submit log → verify in D1 → check historyLog submission pipeline solid

Week 5-6: AI Integration + Prompt Tuning

DayTaskDeliverable
29-30Create AI Gateway connection, test basic completionsrc/services/ai.service.ts calling AI Gateway
31-32Implement voice calibration flow in SettingsVoice extraction prompt working
33-34Build full system prompt with voice signature injectionSystem prompt assembled dynamically
35-36Implement JSON schema validation for AI responsesResponse parsing + validation
37-38Wire AI call into log submission pipeline, store draftDraft generated and stored on log submit
39-40Test with 5+ sample logs, tune prompt for qualityVoice match score >= 70% on test inputs
41-42Add retry logic (3 attempts), error handlingResilient AI pipeline

Week 7-8: Draft Review UI + Human Gate

DayTaskDeliverable
43-44Create /drafts page with draft cardsDraft list rendering with status badges
45-46Build Source Notes panel (collapsible sidebar)Traceable links from draft to log
47-48Build Voice Match indicator (score + breakdown)Visual score with color coding
49-50Implement Approve action with confirmation toastApprove flow + status change
51-52Implement Reject action with reason dropdownReject flow + audit logging
53-54Implement Edit & Approve with inline editorEditable drafts + re-approval
55-56Enforce "no external sharing until approved" gateShare buttons disabled until accepted
57-58Add bulk actions (Approve All / Reject All)Bulk review workflow
59-60End-to-end test: submit → review → approve → verify unlockHuman gate fully functional

Week 9-10: History + Search + Polish

DayTaskDeliverable
61-62Create /history page with data tableSortable table of all logs
63-64Implement server-side text search across log contentSearch via D1 LIKE queries
65-66Add status filter and tag filterMulti-filter working
67-68Implement pagination (25 rows/page)Server-side pagination
69-70Add log detail view with associated draftDrill-down from history to full content
71-72Implement "Regenerate Draft" from historyRe-extraction from existing logs
73-74Polish empty states on all pagesEvery page has meaningful empty state
75-76Add loading skeletons to all async pagesSkeleton screens matching content dimensions

Week 11-12: Testing + Deployment + Voice Fine-Tuning

DayTaskDeliverable
77-78Write Vitest unit tests for utility functionsUnit tests passing
79-80Write Playwright E2E test for critical pathE2E: submit → review → approve
81-82Set up GitHub Actions CI/CD pipeline.github/workflows/ci.yml + deploy.yml
83-84Fine-tune voice prompt with 3-5 real founder samplesVoice match >= 75% on calibrated inputs
85-86Deploy to production Cloudflare WorkersLive at https://your-app.workers.dev
87-88Run smoke tests against productionProduction pipeline verified
89-90Final polish, bug fixes, README documentationProduction-ready v1

Acceptance Tests

MVP Test Scenario

Test ID: MVP-001 Objective: Verify the complete end-to-end pipeline produces a review-ready draft with traceable source notes and voice-match indicator within 30 seconds.

Preconditions:

  • App deployed to Cloudflare Workers with D1 database
  • AI Gateway configured and responding
  • Voice profile trained with at least 3 sample writings
  • User authenticated on the dashboard page
  • Test data does not exist in the database

Minimal Input Log:

Prompt
19 lines
2025-01-15 — Daily Ops

SUPPORT:
- Had a call with Sarah from Acme Corp. She's frustrated that the CSV
  export doesn't include custom fields. She's been asking for this for
  3 weeks. Her exact words: "I'm spending 2 hours every Friday manually

Expected Output:

  • Draft appears within 30 seconds of submission
  • Draft contains complete, coherent write-up based on the input log
  • Source Notes panel shows at least 2 traceable entries linking to original log
  • Voice Match indicator displays a score >= 70%
  • Draft content is fully editable before approval
  • No external sharing options appear until after human approval

Acceptance Criteria Checklist

IDCriteriaPriorityTest Method
AC-01Draft appears in dashboard within 30 seconds of log submissionMUSTPlaywright — measure wall-clock time from click to render
AC-02Draft contains all key information from input log (no dropped items)MUSTManual — compare input sections against draft content
AC-03Source Notes panel shows at least one traceable entry per major log sectionMUSTManual + Playwright — verify DOM contains linked entries
AC-04Each Source Note links back to specific original log textMUSTPlaywright — click source note, verify highlight in original
AC-05Voice Match indicator displays composite score 0-100%MUSTPlaywright — verify score element renders with numeric value
AC-06Voice Match score is >= 70% for well-trained voice profileSHOULDManual — verify on calibrated voice profile
AC-07Draft content is fully editable in dashboard editor before approvalMUSTPlaywright — type in editor, verify content change
AC-08Share/Export/External send buttons disabled until draft approvedMUSTPlaywright — verify button state transitions
AC-09Approving draft unlocks external sharing optionsMUSTPlaywright — click approve, verify buttons enable
AC-10Rejecting draft requires selecting reason from dropdownMUSTManual — attempt rejection without reason, verify blocked
AC-11All review decisions (approve, reject, edit) logged with timestampMUSTManual — check ai_extracts table for decision entries
AC-12Input log preserved immutably and associated with draftMUSTPlaywright — verify API response includes original_log field
AC-13Draft survives page refresh without data lossMUSTPlaywright — refresh page, verify draft state persists
AC-14AI Gateway request/response logged with latency and token countSHOULDManual — verify AI Gateway dashboard shows request
AC-15Drafts can be deleted by owner from drafts listCOULDManual — verify delete button and confirmation flow

Human Review Gate Test

1. Submit the minimal input log via /logs/new
2. Navigate to /drafts, verify draft appears with status "pending"
3. Expand draft card, verify Source Notes panel shows 2+ entries
4. Verify Voice Match score is visible (any numeric value 0-100)
5. Verify Share/Export buttons are disabled/greyed out
6. Click "Approve" → verify confirmation toast → verify status "accepted"
7. Verify Share/Export buttons are now enabled
8. Click "Edit & Approve" → modify draft text → save
9. Verify status returns to "pending" (edit resets approval)
10. Click "Reject" → attempt without reason → verify blocked
11. Select "Wrong voice" as reason → confirm rejection → verify status "rejected"
12. Refresh page → verify all decisions persisted
13. Check ai_extracts table → verify all 4 decisions logged with timestamps

Risks and Validation

RiskImpactLikelihoodMitigationValidation Test
LLM output quality inconsistency — Drafts vary in quality between submissions even with same voice profile; generic or off-voice outputs damage trustHighMedium(1) Lower temperature to 0.4 for consistency; (2) Include self-check step in prompt; (3) Implement voice-match score threshold (< 70% triggers regeneration warning); (4) Fallback to Claude Sonnet if GPT-4o driftsRun 10 identical logs through pipeline, measure voice-match score variance. Target: std dev < 8%. Score >= 70% on 8/10 runs
Voice drift over time — As the founder's writing evolves, the calibrated voice profile becomes stale, producing increasingly mismatched draftsMediumHigh(1) Monthly recalibration prompt (re-extract from 3 most recent published posts); (2) Track confidence_score trend in ai_extracts; (3) Alert user when 2+ consecutive drafts score < 75%; (4) One-click recalibration from SettingsCompare voice-match scores of first 5 drafts vs. drafts generated after 30 days. Flag if average drops > 10 points
Founder stops capturing logs — The core behavioral change (daily logging) may not stick, leading to app abandonmentHighMedium(1) Keep submit page friction-free — one textarea, no required fields; (2) Optional daily reminder email (toggle in Settings); (3) "Load Sample Data" shows value before commitment; (4) Low stakes: logs are private by defaultTrack daily active submitters in first 30 days. Target: 60% of registered users submit at least 3 logs in first week
Cloudflare adapter breaking changes@opennextjs/cloudflare is v1.0-beta; breaking changes could require migration workMediumLow(1) Pin exact version in package.json; (2) Monitor adapter releases weekly; (3) Keep migration notes in README; (4) Abstract Cloudflare-specific code behind service layersVerify build passes with pinned version weekly. Subscribe to adapter release notes
Cost scaling beyond $5/mo — Usage grows beyond 30 logs/month or AI token consumption exceeds free tierLowLow(1) All usage well within Workers Paid included quotas up to 3,000 logs/month; (2) AI Gateway caching reduces redundant calls; (3) Monitor monthly spend via Cloudflare dashboard; (4) Voice prompt caching reduces per-call cost 40-60%Simulate 300 logs/month locally, verify all usage within included quotas. Track actual spend for first month
Auth system complexity — Better Auth with D1 + KV may have edge cases that complicate the solo buildMediumMedium(1) Use better-auth-cloudflare package with documented patterns; (2) Start with email/password only, add OAuth later; (3) Abstract auth behind src/auth/ module; (4) Test auth flow on every deployRun full auth flow (login, session, logout, protected route redirect) in CI on every push
D1 query performance at scale — Unindexed queries on large datasets cause slow page loads and high row-read costsMediumLow(1) All queries use composite index on (user_id, log_date); (2) Run PRAGMA optimize after migrations; (3) Monitor D1 row-read metrics in Cloudflare dashboard; (4) Add query-level caching with Cache API for dashboard statsLoad test with 10,000 log rows, verify dashboard loads in < 1.5s. Monitor D1 row-read count

Non-Functional Requirements

Performance

MetricThresholdMeasurement Method
Draft generation latency (p95)< 30 secondsPlaywright wall-clock + AI Gateway logs
Dashboard page load (p95)< 1.5 secondsLighthouse / Playwright timing
API response time (p95)< 500 msCloudflare Workers analytics
Time to first byte (TTFB)< 200 msWebPageTest / Lighthouse
AI Gateway timeout45 secondsConfigurable via AI Gateway settings
History table filter/sort< 500 msServer-side with indexed queries

Security

RequirementImplementation
Transport encryptionTLS 1.3 (handled by Cloudflare)
AuthenticationBetter Auth with email/password + optional OAuth; sessions stored in KV
API key storageEncrypted via Cloudflare Secrets (wrangler secret put)
Input sanitizationAll user inputs validated with Zod before DB write
SQL injection preventionD1 prepared statements via Drizzle ORM
Draft access controlRow-level: users can only access their own logs and drafts (WHERE user_id = ?)
Audit loggingImmutable ai_extracts table records every AI call and review decision
Session expiry7 days with 1-day refresh window

Reliability

MetricThreshold
Monthly uptime99.0% (~7 hours downtime acceptable)
AI Gateway fallbackClaude Sonnet if GPT-4o fails
Data retentionDrafts retained 1 year; rejected drafts soft-deleted for 30 days
Backup strategyD1 Time Travel for point-in-time recovery
Error handlingGraceful degradation: if AI fails, show error toast with retry
Error boundariesSegment-level error.tsx on every route + root global-error.tsx

Cost (30 logs/month)

ServiceCostNotes
Workers Paid Plan$5.00/moBase subscription; all other usage within included quotas
D1$0<1GB storage, <3M rows written
AI Gateway$0Core features (cache, rate limit, analytics) free
Workers AI tokens$0~30K tokens/month within 10K/day free tier
R2 storage$0<100MB within 10GB free tier
Queues$0<100 operations within 1M/month
Total$5.00/moAll usage well within included quotas

Scalability Headroom

ScaleLogs/MonthEst. CostNotes
Current30$5.00Within all free tiers
Growth (10x)300$5.00Still within all included quotas
Growth (100x)3,000$5.00AI tokens ~$0.05/mo overage
Growth (1000x)30,000$5.50AI tokens ~$0.45/mo; still negligible

Not in MVP

The following features are intentionally excluded from V1 to keep scope tight. They are listed here to prevent scope creep and provide a roadmap for future versions.

FeatureWhy Not V1Future Version
Auto-posting to social platforms (Twitter/X, LinkedIn, etc.)Requires human approval gate to be solid first; external posting is irreversibleV2 — after review gate is battle-tested
Analytics/engagement dashboard (views, likes, click-through)Not the problem this app solves; founder can use native platform analyticsV2 — if content distribution becomes a module
Team/multi-user supportSingle-founder MVP; RBAC adds unnecessary complexityV2 — when team features justified by demand
Custom model fine-tuningVoice calibration via prompt engineering is sufficient; fine-tuning requires training data pipelineV3 — if prompt-based voice match cannot reach 80%+
Mobile native appWeb UI is sufficient for a daily log submission toolV3 — if mobile usage exceeds 40% of sessions
Real-time collaboration on draftsSingle user only; no collaboration neededV2 — with team support
Advanced formatting / rich text editorMarkdown output is sufficient; editing is for polish, not compositionV2 — if non-technical users request WYSIWYG
API rate limiting beyond basic30 logs/month generates minimal load; Cloudflare's built-in rate limiting sufficientV2 — if external API consumers added
Webhook integrations (Zapier, Make, etc.)Email/Slack delivery is manual copy-paste from approved draftsV2 — if automation demand is high
Scheduled/recurring draft generationOn-demand extraction is simpler and more predictableV2 — weekly digest feature
AI-powered improvement on rejected draftsUser edits manually; AI feedback loop adds complexityV2 — if rejection rate > 30%
Billing or payment processingSelf-hosted on user's Cloudflare account; no SaaS billing neededV3 — if offering managed hosting

Open Questions

  1. Which LLM model provides the best voice match for this use case? GPT-4o is the recommended primary with Claude Sonnet as fallback, but the optimal model may vary by founder's writing style. Run A/B tests: generate the same draft with both models and score voice match. Document the winner in the user's profile for future consistency.
  2. How many writing samples are needed for effective voice calibration? The Voice Patterns method recommends 3-5 samples, but the minimum viable number is unknown. Test with 1, 2, 3, and 5 samples and measure the resulting voice-match score. Evidence from research suggests diminishing returns after 3 high-quality samples.
  3. Should rejected drafts be auto-deleted after a period, or retained indefinitely? The current spec soft-archives rejected drafts for 30 days, then hard-deletes. Retaining them indefinitely provides a training corpus for future fine-tuning but consumes D1 storage. Decide based on user preference in Settings (default: retain 30 days).
  4. What is the optimal log length for best AI extraction quality? Too short (under 100 words) may not yield enough substance for a meaningful draft. Too long (over 2,000 words) may dilute the narrative thread or exceed token limits. The current assumption is 200-800 words is the sweet spot, but this should be validated against the first 50 real submissions.
  5. How should voice drift be detected automatically? The current approach tracks confidence_score trend in ai_extracts and alerts when 2+ consecutive drafts score below 75%. A more sophisticated approach would compare n-gram patterns or embedding similarity between recent approved drafts and the original voice profile. Start simple; add NLP comparison only if the threshold-based approach produces false positives.
  6. Should there be a "regenerate" option for drafts that are close but not quite right? Yes — a "Regenerate with different angle" button on the draft card would re-run extraction with a different focus_angle parameter (e.g., shift from "technical_decision" to "customer_lesson"). This is a V1.5 feature, not MVP.
  7. What happens when a log contains sensitive information (customer names, revenue numbers, proprietary details)? The current system stores logs and drafts in the user's own D1 database (data never leaves their Cloudflare account). However, log content is sent to AI Gateway for processing. Document clearly that: (a) logs are processed through Cloudflare AI Gateway, (b) the user should sanitize customer names and sensitive numbers before submission if concerned, (c) a future "redaction" feature could auto-detect and mask sensitive patterns pre-submission.

FAQ

Q: Do I need to know Cloudflare already? Intermediate familiarity is assumed — you should know how to create a Worker, set up a D1 database, and deploy with Wrangler. If you're new to Cloudflare, budget an extra 2-3 days to work through the Cloudflare Workers getting started guide before Week 1.

Q: What if the AI draft doesn't sound like me? The voice calibration step (first-run setup) is designed to prevent this. Paste 3-5 pieces of your actual writing, and the system extracts your voice patterns into a structured profile. If a draft still feels off, the Voice Match indicator shows a score — below 70%, click "Regenerate" or edit the draft directly. You can also re-run voice calibration anytime from Settings with newer writing samples.

Q: How much does it cost to run? At 30 logs per month: $5/month for the Cloudflare Workers Paid plan. All other usage (D1 storage, AI Gateway, Workers AI tokens, R2, Queues) stays within the included free tiers. Even at 3,000 logs/month, the cost stays around $5.00 — only AI token overages would apply, estimated at ~$0.05/month.

Q: Can I use this for Twitter/LinkedIn/Newsletter? The draft output is Markdown-formatted blog posts. For Twitter, you can manually excerpt a paragraph. For LinkedIn, the full post works with minor formatting tweaks. For newsletters, the draft body can be copied directly. Auto-posting to any platform is intentionally not in V1 — every draft requires your approval before it can be shared externally.

Q: What happens to my data? Everything stays in your own Cloudflare account. Logs and drafts live in your D1 database, files in your R2 bucket. No third party (including the app developer) has access to your content. The only external call is to Cloudflare AI Gateway for draft generation, which processes your log content through the LLM. You can export all your data anytime from Settings.

Q: Can I export my logs and drafts? Yes. Settings includes an "Export All Data" button that downloads a JSON file containing all logs, drafts, tags, and review history. This is your data — you own it completely.

Q: Do I need to write logs in a specific format? No. The whole point is to accept messy, unstructured input. Bullet lists, timestamps, stream-of-consciousness, shorthand — the AI extraction pipeline handles all of it. There are no required fields. The only constraint is minimum 10 characters (to prevent accidental empty submissions).

Q: How long does the AI take to generate a draft? Typically 5-15 seconds for a standard post (600-1,200 words) from a single log entry. Complex logs or deep-dive posts may take up to 25 seconds. The system times out at 45 seconds and shows a retry button. Voice prompt caching (enabled via AI Gateway) reduces repeat-call latency by 40-60%.

Q: What if I miss a day of logging? The system has no daily requirement. Submit logs whenever you have something worth capturing. You can also submit multiple days at once — just paste logs from multiple days into the textarea and the AI will synthesize them into a single coherent draft or multiple drafts depending on narrative threads detected.

Q: Can I connect this to my existing note-taking app? Not in V1. The app is designed as a standalone capture tool to minimize integration complexity. If you use Obsidian, Notion, or Apple Notes, the workflow is: capture in your existing tool throughout the day, then paste into /logs/new when you're ready to process. A future integration could pull directly from these apps via API, but manual copy-paste is the V1 pattern.


Citations Used

Blueprint Sources

Sources used in this Blueprint

Reference material used during the research and import process. Treat implementation details as assumptions until tested in your own environment.

63 sources referenced in this report
Collab365 Blueprint • Collab365 Spaces