Skip to content

Sprint 1 Readme

Sprint 1 — Deployable Files · AI Opportunity Audit

Section titled “Sprint 1 — Deployable Files · AI Opportunity Audit”

This Sprint 1 package is everything you need to wire the AI Opportunity Audit fulfillment pipeline end-to-end: intake → Claude analysis → branded deliverables → delivery → referral loop. All GHL-free. ~$0/mo recurring beyond your existing VPS.

Target markets: AU, EU, UAE, higher-tier APAC. Price in USD. Website: dwadlane.com.


File What it is Import target
supabase_schema.sql 10 tables + RLS + triggers + engagement-code generator Supabase SQL Editor
n8n_workflow.json 29-node fulfillment pipeline (importable) n8n → Import from File
claude_prompt_library.md 5 master Claude prompts + API key injection docs Reference (copy system prompts into n8n nodes)
email_swipe_file.md 5-part nurture sequence, Resend-ready Reference (copy into n8n Resend nodes)
notion_build_log_template.md Build-log database + page template Notion (manual setup)
README.md This file — wiring + setup sequence

Tally (intake) ──webhook──► n8n ──► Supabase (intake_responses)
+ automation_state.intake_completed
+ Resend ack email → cal.com booking
[you run interviews, transcripts land in interview_notes]
Admin trigger ──webhook──► n8n "Run Analysis"
──► Supabase: fetch engagement + intake + interviews
──► Claude Sonnet ×4: scoring → opportunities → roadmap → ROI
──► Claude Haiku ×1: Loom script draft
──► Supabase: analysis_drafts (status: in_review) + notify you
[you review + flip status → approved]
Approval webhook ──► n8n "Generate Deliverables"
──► Gotenberg: branded PDF ─┐
──► Placid: share graphic ├─► Supabase: deliverables row
─┘ + automation_state.deliverables_ready
──► Resend: delivery email (PDF + portal + Loom + debrief booking)
[you record Loom → webhook updates deliverables.loom_url]
──► Supabase: create referral row (15% / 12-mo tail)
──► Resend: referral email (24h delay)
──► Notion: auto-create build-log page

Source of truth: Supabase. n8n reads/writes via the PostgREST API using the service role key (bypasses RLS — n8n only). The Next.js client portal uses Supabase Auth + the anon/publishable key with RLS policies scoping reads to the client’s own engagement via portal_magic_token.


Service What you need Where
Supabase Project URL, service role key, anon key console.supabase.com → Settings → API
Anthropic API key (sk-ant-...) console.anthropic.com/settings/keys
Resend API key + verified domain (dwadlane.com) resend.com/domains
Placid API key + template ID (square + landscape) placid.app
Notion Internal integration token + database ID notion.so/my-integrations
Gotenberg (self-hosted, no key) Docker on VPS — see below
Tally Form ID + webhook URL tally.so
cal.com Booking page URL + (optional) API key cal.com
Stripe Secret key (checkout) dashboard.stripe.com → API keys
DocuSeal API key (e-sign) docusign.com → developers

Set these in your n8n instance (Docker env file or n8n Settings → Variables):

# Supabase
SUPABASE_URL=https://YOURPROJ.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ... # n8n only — full access, bypasses RLS
# (anon key is used by the portal frontend, not n8n)
# Anthropic (Claude) — model names are parameterized so you can bump versions
CLAUDE_SONNET_MODEL=claude-sonnet-4-5-20250929
CLAUDE_HAIKU_MODEL=claude-haiku-4-5-20251022
# Resend
RESEND_API_KEY=re_...
MAIL_FROM=dwad@dwadlane.com
# Placid
PLACID_API_KEY=...
PLACID_TEMPLATE_ID=...
# Notion
NOTION_API_KEY=ntn_...
NOTION_BUILDLOG_DB_ID=...
# Gotenberg (self-hosted on VPS, localhost only)
GOTENBERG_URL=http://localhost:3000
# App
SITE_URL=https://dwadlane.com
PORTAL_BASE_URL=https://dwadlane.com/portal
CALCOM_URL=https://cal.com/dwadlane/audit
INTERNAL_NOTIFY_EMAIL=dwad.lane@gmail.com
REFERRAL_PCT=15

n8n credentials (named, reusable) — create in n8n → Credentials

Section titled “n8n credentials (named, reusable) — create in n8n → Credentials”
Credential name Type Used by
anthropicApi Header Auth (x-api-key → your Anthropic key) All 5 Claude nodes
resendApi Header Auth (AuthorizationBearer re_...) All Resend nodes
placidApi Header Auth (AuthorizationBearer ...) Placid node

Why Header Auth instead of pasting keys in nodes? Each Claude/Resend/Placid node references the credential by name. Rotate a key once → all nodes update. The key never appears in the workflow JSON or this README.


This is the single most important wiring step. Three layers:

  1. Get the key from https://console.anthropic.com/settings/keys.
  2. Store it as an n8n credential named anthropicApi, type Header Auth:
    • Name: anthropicApi
    • Header name: x-api-key
    • Value: sk-ant-api03-... (paste your key here)
  3. Each of the 5 Claude nodes in n8n_workflow.json is pre-configured to use it:
    "authentication": "genericCredentialType",
    "genericAuthType": "httpHeaderAuth"
    When you open the node after import, select the anthropicApi credential from the dropdown. Done.

Never do:

  • Paste the key into the jsonBody of a node
  • Paste the key into claude_prompt_library.md
  • Commit the key to GitHub

Full details + cost guardrails in claude_prompt_library.md → section “API KEY INJECTION — WHERE & HOW”.


🔗 How Supabase tables hook into n8n logic

Section titled “🔗 How Supabase tables hook into n8n logic”

n8n talks to Supabase exclusively through the PostgREST API (/rest/v1/...) + Storage API (/storage/v1/...), authenticated with the service role key. Here’s the mapping of workflow nodes → tables:

Workflow node group Supabase table Operation
Tally intake webhook → “Supabase: Insert Intake” intake_responses INSERT
“Supabase: Mark Intake Done” automation_state PATCH (intake_completed=true)
“Run Analysis” → fetch nodes engagements, intake_responses, interview_notes SELECT
“Claude: Dimension Scoring” → “Assemble Draft” → “Store Analysis” analysis_drafts INSERT (all 5 prompt outputs in one row)
“Mark Analysis Ready” automation_state PATCH (analysis_ready=true)
Approval webhook → “Fetch Approved Analysis” analysis_drafts SELECT (status=approved)
“Gotenberg Render PDF” → “Supabase Storage: Upload PDF” Storage bucket deliverables PUT binary
“Store Deliverables” deliverables INSERT (pdf_url, graphic_url, portal_url, magic_token)
“Mark Deliverables Ready” / “Mark Delivered” automation_state PATCH
“Create Referral” referrals INSERT (ref_code, 15%, 12-mo tail)
Delivery / referral / nurture emails email_log INSERT (for nurture analytics)

Key relationships (foreign keys):

  • engagements.contact_idcontacts.id
  • intake_responses.engagement_idengagements.id
  • interview_notes.engagement_idengagements.id
  • analysis_drafts.engagement_idengagements.id
  • deliverables.engagement_idengagements.id
  • automation_state.engagement_idengagements.id (1:1, PK)
  • referrals.referrer_contact_id / referred_contact_idcontacts.id

Engagement code (ENG-2026-014) is auto-generated by the generate_engagement_code() trigger on insert — you never set it manually.

RLS: enabled on contacts, engagements, deliverables, automation_state. The service role key (n8n) bypasses RLS entirely. The portal uses anon key + the portal_read_own_deliverables / portal_read_own_state policies, scoped by portal_magic_token.


  1. Create a Supabase project (free tier is fine to start).
  2. SQL Editor → paste supabase_schema.sql → Run.
  3. Settings → API → copy Project URL, service role key, anon key.
  4. Storage → create a public bucket named deliverables (or private + signed URLs — your call).
  1. On your Hostinger VPS (or any Docker host), run n8n + Gotenberg via Docker Compose. Minimal:
    services:
    n8n:
    image: n8nio/n8n
    ports: ["5678:5678"]
    environment:
    - N8N_HOST=n8n.dwadlane.com
    - WEBHOOK_URL=https://n8n.dwadlane.com
    - GENERIC_TIMEZONE=Asia/Manila
    # + all the env vars from the section above
    env_file: .env
    volumes: ["n8n_data:/home/node/.n8n"]
    gotenberg:
    image: gotenberg/gotenberg:8
    ports: ["3000:3000"] # localhost only — n8n calls internally
    volumes: { n8n_data: {} }
  2. Put Cloudflare in front (DNS → your VPS, proxy on, Full SSL).
  3. Open n8n → Settings → Variables → add every env var listed above.
  4. Credentials → create anthropicApi, resendApi, placidApi (Header Auth types).
  5. Import workflow: n8n_workflow.json → open each Claude/Resend/Placid node → select the matching credential from the dropdown.
  1. Tally → build the deep intake form (see Asset 2 / Asset 9 for the question set). Add hidden field engagement_id. Integrate → Webhook → your n8n Tally webhook URL.
  2. cal.com → set up an “AI Audit Scoping” event type (30 min) + “Stakeholder Interview” (60 min). Copy the booking URLs into env vars.
  3. (Optional) DocuSeal → upload the SOW + NDA templates (Asset 4). Webhook on signature-complete → n8n → automation_state.signed_received=true.
  1. Stripe → create 3 Payment Links for the tiers ($1.5K / $3K / $5K).
  2. On checkout success, Stripe webhook → n8n → INSERT engagements (status: won) + INSERT automation_state row + Resend “You’re in” email with intake + booking links.
  1. Resend → verify dwadlane.com domain (add DNS records).
  2. Copy the 5 nurture emails from email_swipe_file.md into 5 n8n Resend nodes (or a Resend Audience sequence — see the file’s final section for the lighter path).
  1. Gotenberg is already running on the VPS. Build an HTML template for the branded report (see Asset 5 for the design spec). n8n’s “Gotenberg: Render PDF” node POSTs the HTML + the approved-analysis JSON.
  2. Placid → build 2 templates: square 1080×1080 + landscape 1200×627, both with {score}, {client_name}, {radar_data} layers. Copy the template ID into PLACID_TEMPLATE_ID.

7. Client portal (optional for Sprint 1, build in Sprint 2)

Section titled “7. Client portal (optional for Sprint 1, build in Sprint 2)”
  • Next.js on Vercel, dwadlane.com/portal/[engagement_id]?token=…
  • Reads automation_state + deliverables via anon key + magic token. Renders the radar chart, opportunity heatmap, roadmap tiles.
  • Until then, the delivery email links directly to the PDF + Loom — fully functional.
  1. Create the “AI Audit Build Logs” database with the properties in notion_build_log_template.md Section A.
  2. Set the page template (Section B) as the default.
  3. Notion → create internal integration → copy token into NOTION_API_KEY + database ID into NOTION_BUILDLOG_DB_ID.
  4. After “Supabase: Mark Delivered” in n8n, add a Notion node that auto-creates the build-log row (see Section D of the template).

✅ Smoke test (run before any paying client)

Section titled “✅ Smoke test (run before any paying client)”
  1. Self-audit first. Run the full pipeline on your own business (dwadlane.com / your LMS data). You’ll find every broken node before a client does.
  2. Walk through: Tally intake → intake_responses row exists → automation_state.intake_completed=true → ack email arrived → manually trigger Run Analysis → 5 Claude calls succeed → analysis_drafts row exists with all 5 fields → review email arrived → flip status to approved → PDF renders + graphic generates + deliverables row exists → delivery email arrives → referral row created → build-log page appears in Notion.
  3. Verify the JSON parse step works (Claude sometimes wraps output in fences — the Code node in claude_prompt_library.md handles this).

🧭 What’s NOT in Sprint 1 (deferred to Sprint 2)

Section titled “🧭 What’s NOT in Sprint 1 (deferred to Sprint 2)”
  • Client portal UI (radar/heatmap/roadmap tiles) — functional via email links until then
  • Metabase benchmark analytics dashboard
  • Automated Wise payout for referral commissions (manual for now)
  • DocuSeal auto-signing flow wired into n8n (templates ready in Asset 4)
  • The scorecard lead-magnet pipeline (ScoreApp → nurture) — spec is in Asset 3 Pipeline 1; the nurture emails you need are already in this package

Symptom Fix
Claude node returns 401 anthropicApi credential not selected on the node, or wrong header name (x-api-key)
Claude output fails JSON.parse Add the Code node from claude_prompt_library.md (strips markdown fences)
Supabase 401 on insert Using anon key instead of service role key in the node headers
Tally webhook not firing Form must be published; webhook URL must be the n8n production webhook URL (not test)
Gotenberg PDF blank HTML template not attached as files multipart field; check the node’s inputDataFieldName
Placid 401 placidApi credential uses Authorization: Bearer ..., not x-api-key
Engagement code not generating Trigger trg_engagement_code only fires on INSERT when engagement_code IS NULL — ensure you don’t set it manually

Section titled “📍 Related assets (in workspace root, not this folder)”
  • Asset_3_n8n_Pipeline_Spec.md — the full spec this workflow implements
  • Asset_2_ScoreApp_Questionnaire.md — the scorecard question set + scoring logic
  • Asset_5_PDF_Deliverable_Template.md — the branded report design spec
  • Asset_9_Execution_Playbook.md — the cold-beginner execution guide
  • Asset_12_Master_Playbook_v2.md — the integrated strategy doc
  • Asset_13_Productization_roadmap.md — the $5K “how to sell AI audits” product plan

Sprint 1 status: 6/6 files complete. Ready for import + smoke test.