Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
387 commits
Select commit Hold shift + click to select a range
e1a9ee1
feat(approvals): RUN 21 — tiered approval ladder with promote / unsaf…
seungdo-keum Apr 28, 2026
fd7a93e
feat(aeo): RUN 22 Phase 2 — keyTakeaways UI + Article.abstract + Pers…
seungdo-keum Apr 28, 2026
15cf778
feat(aeo): RUN 22 Phase 3 — HowTo schema auto-detection + definition-…
seungdo-keum Apr 28, 2026
a8e89fe
test(e2e): RUN 23 — agent pipeline E2E spec (cron auth + llms-full.tx…
seungdo-keum Apr 28, 2026
f3482b9
feat(post-lovable): Batch A — founding counter UI + learned patterns …
seungdo-keum Apr 28, 2026
0ba80f2
feat(post-lovable): Batch B — FactEdge inference + 30-day freshness r…
seungdo-keum Apr 28, 2026
31a569b
feat(copy): Batch D — `monthly_no_lockin` hero variant from RUN-24 Re…
seungdo-keum Apr 28, 2026
576af1f
test(e2e) + docs(cycle): post-lovable Batch A/B/D verified on prod + …
seungdo-keum Apr 28, 2026
ecb8f15
fix(facc-landing): production QA fixes — broken nav, login visibility…
seungdo-keum Apr 28, 2026
3ffc3af
fix(deploy): remove --skip-generate from prisma db push (Prisma 7 inc…
seungdo-keum Apr 28, 2026
aae48de
fix(deploy): timeout-guard prisma db push + chore(cycle): refresh sta…
seungdo-keum Apr 28, 2026
10ada2e
fix(stripe): isStripeConfigured() was checking obsolete env var names…
seungdo-keum Apr 28, 2026
d9ac20b
feat(onboarding): POST /api/onboarding/sample re-seeds the Acme Coffe…
seungdo-keum Apr 28, 2026
d471da1
test(e2e): persona-journey 15/15 — full conversion funnel + chat valu…
seungdo-keum Apr 28, 2026
eddd113
feat(auth): password visibility toggle on /login + /signup; chore(cyc…
seungdo-keum Apr 28, 2026
114a40c
feat(security+perf): add security headers + cut /pricing TTFB from 2.…
seungdo-keum Apr 29, 2026
ca59fe4
feat(stripe+csp): founding-slot leak fix + CSP report sink + 15th cron
seungdo-keum Apr 29, 2026
e42c280
fix(csp+slack): emergency — disable Slack ping from /api/csp-report (…
seungdo-keum Apr 29, 2026
1924c94
feat(a11y+resilience): label associations + role=alert + 5 route boun…
seungdo-keum Apr 29, 2026
cab821f
test(e2e): Round 5 spec coverage — 49 pass / 2 skip / 0 fail on produ…
seungdo-keum Apr 29, 2026
c0edf5d
fix(agent-cron): trial users also get nightly briefings — closes audi…
seungdo-keum Apr 29, 2026
efa72e7
perf+a11y: Round 6 batch — /pricing 60→300s ISR, founding cron 60→120…
seungdo-keum Apr 29, 2026
c58d165
test(e2e): Round 7 auth-completeness spec — 91/110 pass on full suite
seungdo-keum Apr 29, 2026
87e7efd
feat(observability): /api/health readiness probe + spec
seungdo-keum Apr 29, 2026
9927c84
feat(onboarding): wire onboarding step 3 to the in-page Run-now CTA
seungdo-keum Apr 29, 2026
a4ce620
test(e2e): Round 9 token-flows spec — DB-write paths for verify-email…
seungdo-keum Apr 29, 2026
33734ee
perf(/app): parallelize 13 Prisma queries — cold TTFB target halved
seungdo-keum Apr 29, 2026
73b7fc7
test(e2e)+chore(cycle): Round 10 misc-endpoints spec + cycle close
seungdo-keum Apr 29, 2026
4d04006
docs(readme): rewrite for production-tier Practiq state (was outdated…
seungdo-keum Apr 29, 2026
76230c0
feat(observability): notifyServerError helper + wire signup/chat/onbo…
seungdo-keum Apr 29, 2026
c0a812c
fix(facc/digest-compactor): resolve haiku model id via registry
seungdo-keum Apr 29, 2026
b2b0c69
test(facc/e2e): broaden p09 matchers to fix sample-seed race flake
seungdo-keum Apr 29, 2026
736ee70
feat(facc/slack): severity tiers + test-recipient suppression + noise…
seungdo-keum Apr 29, 2026
2f1d3c5
fix(facc/llm): credit-balance fallback + GPT-4o pricing + L1 verifier
seungdo-keum Apr 29, 2026
b763a42
fix(facc/build): exclude scripts/ from Next type-check
seungdo-keum Apr 29, 2026
9b5c656
feat(facc/embeddings): insert-time hook + backfill cron + L2.A fix
seungdo-keum Apr 29, 2026
4866a30
fix(facc/llm): flip auto-provider default to OpenRouter primary
seungdo-keum Apr 29, 2026
7ff303e
feat(facc/billing): L4 — token budget + Stripe metered overage + demo…
seungdo-keum Apr 29, 2026
9169654
feat(facc/status): public /status page (production-tier signal)
seungdo-keum Apr 29, 2026
1a8979d
fix(facc/pricing): founding-member FAQ — 'vs $99' → 'vs $149' to matc…
seungdo-keum Apr 29, 2026
56ae745
fix(facc/pricing+status): stale price refs + status page audit action
seungdo-keum Apr 29, 2026
f6f618b
feat(facc/legal): AI advisory disclaimer + CSP enforce flip
seungdo-keum Apr 29, 2026
f95cec7
docs(facc/legal): privacy sub-processor list + ToS billing + DPA temp…
seungdo-keum Apr 29, 2026
11f3020
fix(facc/slack): isTestRecipient — also check email/userEmail/recipient
seungdo-keum Apr 29, 2026
48abc3a
feat(facc/beta): feedback widget + invite-only signup gate + DR runbo…
seungdo-keum Apr 29, 2026
37b8db6
feat(facc/ai-quality): eval suite + 0% hallucination verdict + system…
seungdo-keum Apr 29, 2026
130a3fb
fix(facc/analytics): wire AnalyticsProvider so $pageview beacon actua…
seungdo-keum May 6, 2026
35cde8d
feat(facc/observability): GET /api/admin/traffic-summary endpoint
seungdo-keum May 6, 2026
9867c7b
feat(facc/geo): GEO citation scanner + daily cron
seungdo-keum May 6, 2026
fb88301
feat(facc/observability): daily-traffic-report cron + vercel.json wiring
seungdo-keum May 6, 2026
6e2264a
fix(facc/analytics): filter e2e personas from admin dashboard queries
seungdo-keum May 6, 2026
dbe6c3b
feat(facc/analytics): instrument signup_form_submitted + signup_blocked
seungdo-keum May 6, 2026
6d6d03a
fix(facc/checkout): stitch stripe session_id + prefill customer_email…
seungdo-keum May 6, 2026
666b0f4
feat(facc/analytics): instrument stripe_checkout_abandoned to close f…
seungdo-keum May 6, 2026
7bad3ac
fix(facc/analytics): allow stripe_checkout_abandoned through /api/eve…
seungdo-keum May 6, 2026
f4fa512
feat(facc/agent): add read_document + find_in_document extraction pri…
seungdo-keum May 7, 2026
1d77b3b
feat(facc/agent): edit_document tool with OOXML tracked-changes round…
seungdo-keum May 7, 2026
74df44a
feat(facc/agent): citation contract with streaming sentinel parser
seungdo-keum May 7, 2026
51190ba
feat(facc/analytics): tier 5 user-journey tracking
seungdo-keum May 7, 2026
19bfc12
feat(facc/landing): add 5 boutique vertical landing pages with verbat…
seungdo-keum May 7, 2026
6e2fe11
feat(facc/landing): add /compare/mike standalone comparison page
seungdo-keum May 7, 2026
e9c00ec
feat(facc/landing): adopt boutique copy on pricing + signup hero surf…
seungdo-keum May 7, 2026
f8ab92d
feat(facc/analytics): tier 5 attach useFormTracking to signup/login +…
seungdo-keum May 7, 2026
754ca87
docs(facc/research): real-user engagement analysis 2026-05-07
seungdo-keum May 7, 2026
a1cb77a
feat(facc/retention): tier 4 lifecycle email sequence (welcome + day3…
seungdo-keum May 7, 2026
489bdc4
feat(facc/checkout): 14-day no-card trial on Solo + automatic_tax
seungdo-keum May 7, 2026
01dd385
feat(facc/analytics): mirror server events to PostHog + drain on flush
seungdo-keum May 7, 2026
d69ea5a
fix(facc/build): prepend prisma generate to build chain
seungdo-keum May 7, 2026
6a75b5d
fix(facc/analytics): mask PII in PostHog session replay
seungdo-keum May 7, 2026
d9ec2fb
feat(facc/analytics): firm-level group analytics in PostHog
seungdo-keum May 7, 2026
2ce61c6
feat(facc/analytics): capture Core Web Vitals at 10% sample
seungdo-keum May 7, 2026
3c52462
feat(facc/analytics): capture uncaught JS errors and rejections
seungdo-keum May 7, 2026
911a4c4
feat(facc/alerts): slack ping on cron and stripe webhook failures
seungdo-keum May 7, 2026
2c4fd0b
feat(facc/seo): GSC verification, IndexNow, schema audit, sample docs
seungdo-keum May 7, 2026
0269e6c
fix(facc/security): allow Google Fonts + PostHog domains in CSP
seungdo-keum May 7, 2026
d65b98c
feat(facc/onboarding): sample-document hooks in empty-state + welcome…
seungdo-keum May 7, 2026
4966c1d
feat(facc/evals): citation + redline + workflow evaluators + CI gate
seungdo-keum May 7, 2026
73cfa3a
fix(facc/security): prevent user enumeration via signup endpoint
seungdo-keum May 7, 2026
f584119
fix(facc/security): CSP allow Google Fonts + PostHog domains (re-apply)
seungdo-keum May 7, 2026
5c6e731
fix(facc/seo): add per-page metadata for /signup and /login
seungdo-keum May 7, 2026
79608c3
feat(harness+facc): mandate OpenRouter for all LLM API calls
seungdo-keum May 7, 2026
b186a58
feat(facc/marketing): unify operator signature across all 19 email te…
seungdo-keum May 8, 2026
d38a31b
feat(facc/marketing): manual cold outreach tooling + playbook (Instan…
seungdo-keum May 8, 2026
296fdd6
feat(facc/marketing): create-gmail-drafts + Apps Script auto-schedule…
seungdo-keum May 8, 2026
a1d81df
fix(facc/marketing): create-gmail-drafts reuses existing OAuth client…
seungdo-keum May 8, 2026
d7895f3
fix(facc/marketing): rewrite trade press pitches with correct boutiqu…
seungdo-keum May 8, 2026
139db6b
feat(facc/marketing): Vercel cron auto-sends Practiq outreach drafts …
seungdo-keum May 8, 2026
2b39361
feat(facc/marketing): add force_day / force_slug query overrides for …
seungdo-keum May 8, 2026
e92159f
fix(facc/marketing): suppress Slack noop notifications on quiet cron …
seungdo-keum May 8, 2026
cff4ce6
feat(facc/marketing): every-weekday outreach schedule + warmup ramp
seungdo-keum May 8, 2026
4afd907
chore(facc): empty commit to trigger Vercel redeploy after CRON_DRY_R…
seungdo-keum May 8, 2026
038fe59
feat(facc/marketing): demo-v1.mp4 — 60-sec programmatic Practiq expla…
seungdo-keum May 8, 2026
63f0b09
feat(facc/marketing): /demo — anonymous interactive Word redline trial
seungdo-keum May 8, 2026
9169791
feat(facc/outreach): reply-monitor + follow-up-send crons
seungdo-keum May 8, 2026
8d1f934
feat(facc/marketing): lead-pipeline v2 — 65 new contacts across 4 ver…
seungdo-keum May 8, 2026
ea4b765
fix(facc/marketing): remove fabricated proof claims from 117 outreach…
seungdo-keum May 8, 2026
fca6ede
chore(facc): resume outreach cron — CRON_DRY_RUN=false (drafts correc…
seungdo-keum May 8, 2026
2c829af
fix(facc/marketing): re-render demo-v1 with honest pre-launch voiceover
seungdo-keum May 9, 2026
fe5ff7a
feat(facc/marketing): demo-v2.mp4 with real /demo screen capture
seungdo-keum May 9, 2026
3860033
feat(facc/marketing): demo-{cpa,law,hr}.mp4 — vertical-specific Pract…
seungdo-keum May 9, 2026
f44eb88
fix(facc/demo): replace fabricated "5 firms in pilot" with honest pre…
seungdo-keum May 9, 2026
1341fb5
fix(facc/marketing): re-render 4 demo videos with fresh honest /demo …
seungdo-keum May 9, 2026
60832e0
feat(facc/landing): add 3 topic landing pages for SNS-driven traffic …
seungdo-keum May 12, 2026
3872d25
fix(facc/landing): wire waitlist_signed_up server-side + add lane/cta…
seungdo-keum May 12, 2026
a16da0d
feat(facc/admin): blog CMS — author + publish posts via /admin/blog w…
seungdo-keum May 12, 2026
72350dd
feat(facc/admin): blog draft preview route at /admin/blog/preview/[id]
seungdo-keum May 12, 2026
488a85d
fix(facc/admin): set admin session cookie at path "/" so /api/admin/*…
seungdo-keum May 12, 2026
133ed09
feat(facc/audit): self-serve workflow audit at /workflow-audit
seungdo-keum May 12, 2026
4da8541
feat(facc/demo): live demo workspace at /demo/workspace with 50-clien…
seungdo-keum May 12, 2026
fd018cf
fix(facc/audit): await workflow_audit_completed analytics write
seungdo-keum May 12, 2026
f2b8e02
feat(facc/tools): AI policy generator at /tools/ai-policy-generator
seungdo-keum May 12, 2026
5120f63
chore(facc): force redeploy to purge stale topic-page prerender cache
seungdo-keum May 12, 2026
d106abd
fix(facc/landing): topic landing pages serve empty HTML — refactor to…
seungdo-keum May 12, 2026
e89e42a
fix(facc/policy-generator): lazy PDF render to fix 504 timeout on /ap…
seungdo-keum May 12, 2026
bdec234
fix(facc/landing): DOM-safe analytics beacon serialization
seungdo-keum May 12, 2026
76a3109
feat(facc/landing): cross-link the 7 new tools surfaces from sitemap,…
seungdo-keum May 12, 2026
f02b4aa
fix(facc/policy-generator): tighten LLM output budget + add timing logs
seungdo-keum May 12, 2026
829f5c0
fix(facc/llms-txt): add Free tools + Thesis pages sections to the act…
seungdo-keum May 12, 2026
310de4f
fix(facc/landing+seo): SSR critical public pages + drop Bing per-URL …
seungdo-keum May 12, 2026
7fe6754
feat(facc/admin): tools-funnel dashboard at /admin/analytics/tools-fu…
seungdo-keum May 12, 2026
7fb4cb2
feat(facc/workflow-audit): +24h follow-up email cron
seungdo-keum May 12, 2026
0b6fa37
docs(facc/privacy): disclose data collection from workflow audit + AI…
seungdo-keum May 12, 2026
42515f6
fix(facc/seo): correct OG image path to /images/og-image.png
seungdo-keum May 12, 2026
dde5f36
docs(facc/privacy): disclose workflow audit follow-up email
seungdo-keum May 12, 2026
585da22
feat(facc/lead-gen): email validation pre-check for v2 cold cohort
seungdo-keum May 12, 2026
d54e87a
feat(facc/demo-workspace): warmer sample-mode upgrade path on approva…
seungdo-keum May 12, 2026
670c020
feat(facc/ops): real-time user-error Slack alerts + admin/incidents
seungdo-keum May 13, 2026
87ab24b
chore(facc/qa): add Playwright dogfood smoke script
seungdo-keum May 13, 2026
423aec6
fix(facc/policy-generator): bump marketing max_tokens + retry on trun…
seungdo-keum May 13, 2026
ae91f8e
feat(facc/billing): founding-member signup deep-link + /welcome landing
seungdo-keum May 13, 2026
ae209e5
feat(facc/admin): /admin/leads operator inbox
seungdo-keum May 13, 2026
e4d19da
chore(studio/env): document RESEND_WEBHOOK_SECRET placeholder
seungdo-keum May 13, 2026
9949ec1
fix(facc/policy-generator): bump function maxDuration to 120s for ret…
seungdo-keum May 13, 2026
d302aa1
chore(facc/comments): update stale SES references to Resend post-migr…
seungdo-keum May 13, 2026
f95eca2
fix(facc/policy-generator): surface real stop_reason + enforce minItems
seungdo-keum May 13, 2026
660b31f
chore(facc/env): remove SES env vars from example after Resend migration
seungdo-keum May 13, 2026
ad657a4
feat(facc/seo): programmatic per-surface OG images via Next.js ImageR…
seungdo-keum May 13, 2026
5e1b9e2
feat(facc/ops): Stripe webhook reliability monitoring + replay protec…
seungdo-keum May 13, 2026
9b388a8
feat(facc/policy-generator): capture raw LLM output excerpts on failure
seungdo-keum May 13, 2026
4196207
perf(facc/fonts): self-host Plus Jakarta + JetBrains Mono via next/fo…
seungdo-keum May 13, 2026
28c36e7
fix(facc/notifications): refresh request_body on user_error dedupe up…
seungdo-keum May 13, 2026
7374df8
fix(facc/policy-generator): coerce non-array sections/obligations fro…
seungdo-keum May 13, 2026
652fd98
fix(facc/a11y): partial fixes from Lighthouse audit followups
seungdo-keum May 13, 2026
641e008
feat(facc/policy-generator): widen failure diagnostic with sections e…
seungdo-keum May 13, 2026
e319114
feat(facc/ops): /api/health endpoint + health_checks history table
seungdo-keum May 13, 2026
375588f
chore(facc/qa): add end-to-end funnel dogfood journey script
seungdo-keum May 13, 2026
e19d312
fix(facc/policy-generator): coerce all non-array sections shapes + di…
seungdo-keum May 13, 2026
eae163b
feat(facc/ops): health-check cron + /admin/health + Slack alerts
seungdo-keum May 13, 2026
beb2e5e
feat(facc/ops): per-firm LLM spend ceiling on public hot paths
seungdo-keum May 13, 2026
55b6f6e
fix(facc/policy-generator): smarter string-coerce for sections recovery
seungdo-keum May 13, 2026
38fd197
fix(facc/workflow-audit): word-boundary trim email subject + ellipsis
seungdo-keum May 13, 2026
c6b17c6
fix(facc/a11y): Tier 3 WCAG sweep — skip link, main landmarks, contra…
seungdo-keum May 13, 2026
26d8eac
feat(facc/ops): billing incident ledger + Slack pipeline (Tier 3)
seungdo-keum May 13, 2026
fb574a9
fix(facc/pricing): honest $149 anchor + Most popular badge + tier dis…
seungdo-keum May 13, 2026
3530a5f
fix(facc/signup): inline error for required vertical select (a11y + d…
seungdo-keum May 13, 2026
286fd38
fix(facc/a11y): round-2 contrast lifts from Lighthouse production audit
seungdo-keum May 13, 2026
928858e
fix(facc/a11y): round-3 contrast lifts on /login /signup /demo /workf…
seungdo-keum May 13, 2026
716977c
feat(facc/email): wire P7-01 5-email founding-member onboarding drip
seungdo-keum May 13, 2026
392f7da
fix(facc/a11y): lift last blog-post contrast violation (newsletter ey…
seungdo-keum May 13, 2026
20c943b
fix(facc/forms): post-dogfood form UX — chevron, disabled state, foun…
seungdo-keum May 13, 2026
5c740dc
perf(facc/landing): skip RSC prefetch of /app from anonymous footer
seungdo-keum May 13, 2026
f0a5f71
fix(facc/a11y): brand mark scrapes "PPractiq" — split aria-label + ar…
seungdo-keum May 13, 2026
bf47c68
fix(facc/layout): pricing FAQ — mobile body weight + in-tier FAQ jump…
seungdo-keum May 13, 2026
768a8da
ci(facc): Lighthouse mobile gate on PRs against Vercel preview
seungdo-keum May 13, 2026
84be984
ci(facc/lighthouse): per-surface thresholds matching 2026-05-13 baseline
seungdo-keum May 13, 2026
136ce68
docs(facc/qa): 2026-05-13 R2 production dogfood — 11 findings
seungdo-keum May 13, 2026
0eb47e3
fix(facc/a11y): PPractiq scrape — drop "P" text node via ::before pse…
seungdo-keum May 13, 2026
661b2ec
docs(facc/qa): 2026-05-13 R3 production dogfood — 11 findings
seungdo-keum May 13, 2026
89241a0
fix(facc/signup): drop native required — restore dark-theme inline error
seungdo-keum May 13, 2026
c913591
fix(facc/bundle): scope auth+analytics providers and waitlist fetch o…
seungdo-keum May 13, 2026
d48ff10
feat(facc/app): mobile drawer for authenticated /app shell
seungdo-keum May 13, 2026
28ce1f4
feat(facc/seo): bespoke OG cards + sitemap + index for Practiq-vs-X p…
seungdo-keum May 13, 2026
fd87b40
test(facc/app): Playwright verification for mobile drawer + memory note
seungdo-keum May 13, 2026
fe60046
fix(facc/a11y): lift zinc-500 to zinc-400 on Practiq-vs-X pages
seungdo-keum May 13, 2026
0b3dd93
feat(facc/qa): authed E2E scaffold + 5 critical-path specs + CI workflow
seungdo-keum May 13, 2026
f2d001e
fix(facc/app): redirect bare /app/clients to /app workspace
seungdo-keum May 13, 2026
49b7744
fix(facc/admin): differentiate cold open from expired session
seungdo-keum May 13, 2026
31c99c6
fix(facc/api): stop leaking seeded flag from /api/founding/status
seungdo-keum May 13, 2026
ffc8017
fix(facc/auth-shells): segment-aware 404s for /app and /admin
seungdo-keum May 13, 2026
c3cb074
fix(facc/auth-shells): catch-all routes to actually invoke segment 404s
seungdo-keum May 13, 2026
3bd1da3
fix(facc/admin): use next/link for /admin/incidents/stripe references
seungdo-keum May 13, 2026
73c1d9e
chore(facc/gitignore): ignore tmp/ + remotion build outputs
seungdo-keum May 13, 2026
a56c283
fix(facc/app): mobile approval queue list-then-detail flow
seungdo-keum May 13, 2026
86a83a0
fix(facc/app): mobile-responsive client workspace hero + tabs
seungdo-keum May 13, 2026
65fca3d
docs(memory/design-engineer): Wave 15 /app inner-view mobile patterns
seungdo-keum May 13, 2026
d654938
feat(facc/seo): JSON-LD on /vs comparison pages
seungdo-keum May 13, 2026
3491788
feat(facc/deliverability): bounce/complaint alert pipeline with suppr…
seungdo-keum May 13, 2026
c897fbc
fix(facc/seo): numeric Offer.price for productComparisonJsonLd
seungdo-keum May 13, 2026
bb3fb31
fix(facc/seo): numeric Offer.price for practiqVsCompetitor + compare …
seungdo-keum May 13, 2026
fbaab13
copy(facc/for-verticals): Reddit-mined hero refresh for 5 personas
seungdo-keum May 13, 2026
48c4d65
copy(facc/hero): VoC variants for homepage A/B (staged, no rotation)
seungdo-keum May 13, 2026
c13ad42
feat(facc/hero): activate Wave 20 A/B 70/15/15 (control / context_los…
seungdo-keum May 13, 2026
7bcf564
feat(facc/pricing): shift to per-client pricing model display
seungdo-keum May 15, 2026
0b7686b
fix(facc/pricing): clean up residual per-seat copy after Stage 1
seungdo-keum May 15, 2026
0e095ac
fix(facc/pricing): full pricing sweep — remove last per-seat references
seungdo-keum May 15, 2026
3d07926
feat(facc/billing): Stage 3a — additive schema for per-client billing
seungdo-keum May 15, 2026
6ab197f
feat(facc/billing): Stage 3a' — Stripe price resolver shim
seungdo-keum May 15, 2026
bd9e425
feat(facc/billing): Stage 3b — per-client billing hook on /api/clients
seungdo-keum May 15, 2026
8fb6485
fix(facc): three Stage 3 follow-up patches (trial gate + globals + cl…
seungdo-keum May 15, 2026
cf686e2
revert(facc): restore globals.css em-dash (Vercel build regression fr…
seungdo-keum May 15, 2026
a0b576c
fix(facc/build): pin Tailwind to ~4.1.18 (Tailwind 4.2.2 build regres…
seungdo-keum May 15, 2026
99e6a59
chore(facc): add .gitattributes to lock CSS/MD/JSON line endings to LF
seungdo-keum May 15, 2026
ab43e1d
revert(facc): unpin Tailwind range — the v4.2.2 issue was never the c…
seungdo-keum May 15, 2026
dea131d
feat(facc/billing): Stage 3c — checkout + webhook rewrite for per-client
seungdo-keum May 15, 2026
a779e23
feat(facc/billing): Stage 3d — plan-gates + token-budget read per-cli…
seungdo-keum May 15, 2026
9cb985f
feat(facc/billing): Stage 3d.1 — wire consumeCredits into chat path
seungdo-keum May 15, 2026
07af98a
feat(facc/billing): Stage 3e (minimal) — /app/settings reads per-clie…
seungdo-keum May 15, 2026
8fc9e79
chore(facc/deploy): redeploy to pick up new STRIPE_PRICE_PER_CLIENT_*…
seungdo-keum May 15, 2026
7aaeb66
fix(facc/billing): drop payment_method_collection from credit_pack mode
seungdo-keum May 15, 2026
6939b5f
feat(facc/billing): Stage 3e (full) — Buy credits + Subscribe-foundin…
seungdo-keum May 15, 2026
412ff58
feat(facc/billing): Stage 3d.2 — agent dispatcher writes UsageEvent
seungdo-keum May 15, 2026
df22719
fix(facc/billing): two correctness improvements for per-client billing
seungdo-keum May 15, 2026
9a18b61
fix(facc/billing): signup founding-flow POSTs new per-client body
seungdo-keum May 15, 2026
15a3310
feat(facc/billing): re-enable Stripe checkout from /pricing CTA
seungdo-keum May 15, 2026
da192f1
fix(facc/billing): pricing CTA redirects to /signup not /auth/signup
seungdo-keum May 15, 2026
931ec33
fix(facc/budget): demo upgrade-url → /signup (was 404 /auth/signup)
seungdo-keum May 15, 2026
0476f2b
test(facc/budget): update demo-exceeded URL expectations to /signup
seungdo-keum May 15, 2026
6ea3b35
chore(facc/deploy): open beta signup (BETA_OPEN_SIGNUP=1)
seungdo-keum May 16, 2026
b3fc1e3
feat(facc/funnel): workflow-audit step instrumentation + /demo CTA pr…
seungdo-keum May 16, 2026
09835b6
fix(facc/seo): title/meta rewrite for top-impression zero-CTR posts
seungdo-keum May 16, 2026
027ee35
fix(facc/seo): NPS-controversy title rewrite for client-satisfaction-…
seungdo-keum May 16, 2026
7fd4809
feat(facc): real-prospect Slack + AEO content gap + directory priority
seungdo-keum May 17, 2026
6bf0f52
chore(facc): option-B cleanup — SEO titles + legacy checkout instrume…
seungdo-keum May 17, 2026
5043dc8
feat(facc/ops): daily-pulse — one-command observation-mode status
seungdo-keum May 17, 2026
f6491a9
feat(facc/ops): daily-pulse cron + operator/bot traffic filter
seungdo-keum May 17, 2026
e292d9d
docs(facc/playbooks): operator response playbooks for real-event trig…
seungdo-keum May 17, 2026
3ec4612
feat(facc/outreach): fully-automated discovery outreach pipeline
seungdo-keum May 17, 2026
d192457
fix(facc/outreach): trace .cycle/research dir for cron file enumeration
seungdo-keum May 18, 2026
4904dbb
feat(facc/outreach): GH Actions daily send pipeline (Vercel-fs replac…
seungdo-keum May 18, 2026
6c218a9
feat(facc/outreach+analytics): big batch (112 emails) + bot filter + …
seungdo-keum May 18, 2026
44b164e
feat(facc/outreach): role-based mailbox filter + git-history rescue
seungdo-keum May 18, 2026
8540d44
fix(facc/seo): rewrite GSC page-1-but-no-click titles + descriptions
seungdo-keum May 18, 2026
c762dcf
feat(facc/aeo): Product entity + canonical definition on programmatic…
seungdo-keum May 18, 2026
5973164
feat(facc/seo): long-form /vs/* pages for high-intent competitor queries
seungdo-keum May 18, 2026
dd0b85f
feat(facc/outreach): full-scale batch (412 verified emails, 5 new dra…
seungdo-keum May 18, 2026
877ac14
feat(facc/discovery): Wave-5+13 scrapers + master inventory tooling
seungdo-keum May 18, 2026
c4c6298
feat(facc/discovery): standalone signal-to-email enricher
seungdo-keum May 18, 2026
1f9bdc3
fix(facc/discovery): merge-all-sources — honest metric + git union (S…
seungdo-keum May 19, 2026
efc5492
feat(facc/discovery): JobSpy hiring trigger + healthcare mega-sweep y…
seungdo-keum May 19, 2026
e0a1771
chore(facc): recover 545K rows from partial JSONL + merge to master
seungdo-keum May 19, 2026
0ccbb16
fix(facc): stream partial JSONL conversion + checkpoint #4 (744K sign…
seungdo-keum May 19, 2026
5152fc4
feat(mcp): rename to @practiq/mcp + AGPL-3.0 + publish hardening
seungdo-keum May 26, 2026
952ba1a
fix(seo): env-var-ize IndexNow key (gitleaks false-positive cleanup)
seungdo-keum May 26, 2026
39e7b08
chore(harness): rename scope to @cliwant/practiq-mcp + github.com/cli…
seungdo-keum May 26, 2026
00c92ac
feat(oss): initial OSS scaffolding for @cliwant/practiq-oss
seungdo-keum May 26, 2026
6b36772
docs(seo): add llms-full.txt (concatenated docs for LLM indexing) (#6)
seungdo-keum May 27, 2026
0936c9c
fix(deps): restore @supabase/supabase-js — analytics layer is optiona…
seungdo-keum May 27, 2026
02bfa76
fix(selfhost): align Docker + smoke CI with flat repo layout (#8)
seungdo-keum May 27, 2026
e153bd9
docs: fix public-facing accuracy — flat-repo, working links, drop sol…
seungdo-keum May 28, 2026
968fa05
chore(deps): Bump fast-uri from 3.1.0 to 3.1.2 in /packages/mcp
dependabot[bot] May 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
98 changes: 89 additions & 9 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,16 +1,96 @@
# PostgreSQL (로컬)
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/fractional
# Practiq — self-host environment template.
#
# Copy to .env.local before `docker compose up`:
# cp .env.example .env.local
#
# Required values are marked REQUIRED. Everything else is optional —
# Practiq runs in degraded-but-functional mode when optional services
# are unavailable.

# Claude AI — Claude Code 구독 CLI 사용 시 API 키 불필요. API 직접 사용 시만 설정.
# ANTHROPIC_API_KEY=
# ─── REQUIRED ──────────────────────────────────────────────────────────

# NextAuth.js
# Cookie HMAC secret. Generate with:
# node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
NEXTAUTH_SECRET=

# At least one LLM provider key. Practiq routes all LLM calls through this.
# Sign up: https://openrouter.ai/ (recommended — single key, multi-provider)
# or https://console.anthropic.com/ (Anthropic direct)
OPENROUTER_API_KEY=
ANTHROPIC_API_KEY=

# ─── OPTIONAL — Database ───────────────────────────────────────────────
# Default values match the docker-compose.yml internal network. Override
# only if you're running an external Postgres (cloud-managed, etc.).
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=practiq
POSTGRES_PORT=5432

# ─── OPTIONAL — Public URL ─────────────────────────────────────────────
# Set this when deploying behind a domain (e.g. https://practiq.yourcompany.com).
# Defaults to http://localhost:3000 for local dev.
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-random-secret-here
WEB_PORT=3000

# Google OAuth (NextAuth Provider)
# ─── OPTIONAL — OAuth Sign-in providers ────────────────────────────────
# If unset, sign-in falls back to credentials (email+password).
# Each provider is conditionally registered — missing CLIENT_ID + SECRET
# silently drops it from the sign-in page.

# Google OAuth — https://console.cloud.google.com/apis/credentials
# Authorized redirect URI: ${NEXTAUTH_URL}/api/auth/callback/google
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

# FastAPI Document Service
DOCUMENT_SERVICE_URL=http://localhost:8000
# LinkedIn OAuth — https://www.linkedin.com/developers/apps
# Authorized redirect URI: ${NEXTAUTH_URL}/api/auth/callback/linkedin
LINKEDIN_CLIENT_ID=
LINKEDIN_CLIENT_SECRET=

# Microsoft Entra ID (Azure AD) — https://entra.microsoft.com/
# Authorized redirect URI: ${NEXTAUTH_URL}/api/auth/callback/microsoft-entra-id
MICROSOFT_ENTRA_ID_CLIENT_ID=
MICROSOFT_ENTRA_ID_CLIENT_SECRET=
MICROSOFT_ENTRA_ID_TENANT_ID=

# ─── OPTIONAL — Stripe billing ─────────────────────────────────────────
# Most self-hosters can ignore these. Practiq's billing UI is hidden
# when STRIPE_SECRET_KEY is unset, and all features remain available
# (since you self-host, you're not paying us anyway).
#
# If you want to expose paid tiers to your own users (multi-tenant SaaS
# scenario), follow docs/self-host/billing.md.
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=

# ─── OPTIONAL — Telemetry ──────────────────────────────────────────────
# OFF by default for self-hosters. If enabled, sends anonymized usage
# pings to telemetry.practiq.dev (you can self-host the receiver too —
# see docs/self-host/telemetry.md). No PII. No client data. Just:
# • Practiq version
# • Number of active users (count, not identities)
# • Number of clients in the system (count)
# • Crash reports (sanitized stack traces, no payloads)
#
# Set to "on" to opt in. Anything else (including empty) means OFF.
PRACTIQ_TELEMETRY=off

# ─── OPTIONAL — Email ─────────────────────────────────────────────────
# When unset, password-reset and email-verification fall back to a console-
# log "magic link" you can copy from `docker compose logs web`. Fine for
# single-user self-host; you'll want a real provider for a team deploy.
#
# Resend is what practiq.dev uses; any SMTP works via the standard env vars.
RESEND_API_KEY=
RESEND_FROM_EMAIL=

# ─── OPTIONAL — Pixels / analytics (zero by default) ──────────────────
# These ad pixels exist for practiq.dev's growth funnel. Self-hosters
# leave them empty — components render nothing with zero runtime cost.
NEXT_PUBLIC_POSTHOG_KEY=
NEXT_PUBLIC_POSTHOG_HOST=
NEXT_PUBLIC_META_PIXEL_ID=
NEXT_PUBLIC_LINKEDIN_PARTNER_ID=
NEXT_PUBLIC_X_PIXEL_ID=
23 changes: 23 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Force LF for line-ending-sensitive files. Without this, Windows checkouts
# convert to CRLF and Tailwind v4 / lightningcss / some serializers refuse
# to parse the file.
*.css text eol=lf
*.scss text eol=lf
*.json text eol=lf
*.md text eol=lf
*.yaml text eol=lf
*.yml text eol=lf
*.sh text eol=lf
*.bash text eol=lf
Dockerfile* text eol=lf
*.dockerfile text eol=lf
*.tgz binary
*.gz binary
*.zip binary
*.png binary
*.jpg binary
*.jpeg binary
*.ico binary
*.pdf binary
*.node binary
*.dll binary
48 changes: 48 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
name: Bug report
about: Something is broken
title: "[bug] "
labels: bug
assignees: ''
---

## What happened

A clear, concise description of the bug.

## Expected behavior

What you expected to happen.

## Reproduction

Minimum steps to reproduce:
1. ...
2. ...
3. ...

## Environment

- **Where**: cloud (practiq.dev) / self-hosted Docker / `@cliwant/practiq-mcp` npm / dev clone
- **MCP client** (if relevant): Claude Desktop X.Y / Claude Code X.Y / Cursor X.Y / other
- **OS**: macOS X.Y / Ubuntu X.Y / Windows X
- **Node version** (if relevant): `node -v`
- **Practiq version**: `npm view @cliwant/practiq-mcp version` or commit SHA
- **Browser** (if web app): Chrome X / Firefox X / Safari X

## Logs / error output

```
paste relevant log snippet, stack trace, or screenshot here
```

If on self-hosted Docker: `docker compose logs --tail=200 web`
If `@cliwant/practiq-mcp`: stderr from the MCP server (Claude Desktop logs it).

## Anything else

Optional — links to related issues, hypotheses about root cause, etc.

---

**Security?** Do not file a public issue for security bugs. See [SECURITY.md](../../SECURITY.md).
36 changes: 36 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
name: Feature request
about: Propose a new feature or improvement
title: "[feat] "
labels: enhancement
assignees: ''
---

## Problem

What problem does this solve? Why is the current state inadequate?

(Bad: "Add X." Good: "When I'm managing 120 clients during tax season, I currently
can't see <Y>, which means <Z>.")

## Proposed solution

What you'd like to see happen. Be specific — UI sketches, API shapes, tool signatures
all welcome.

## Alternatives considered

What else have you tried? What's the workaround today?

## Who benefits

Solo CPAs / mid-size accounting firms / law firms / HR advisory / consulting / agency / all?
Are you that user? (We weight feature requests from real practitioners heavily.)

## Scope / non-scope

What's explicitly NOT included in this proposal? (Helps reviewers calibrate.)

## Anything else

Links to similar features in other products, prior art, etc.
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/question.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: Question / help
about: Ask a question about using or self-hosting Practiq
title: "[q] "
labels: question
assignees: ''
---

> Please check first: **README.md**, **practiq.dev/docs**, and existing closed issues
> with the [`question`](https://github.com/cliwant/practiq-oss/issues?q=is%3Aissue+label%3Aquestion+is%3Aclosed) label.

## Question

What do you want to know?

## Context

What are you trying to do? What have you tried? What's confusing about the docs?
(Confusing docs are a bug — please tell us where you got stuck.)

## Environment (if relevant)

Same as the bug template — where you're running Practiq, which MCP client, OS, version.
39 changes: 39 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<!-- Thanks for the PR! See CONTRIBUTING.md for the full rules.
A few quick reminders so this PR can land fast: -->

## What & why

<!-- 1-3 sentences. The maintainer reads this first.
Bad: "Improved morning_briefing."
Good: "morning_briefing previously returned only the first 10 clients sorted
alphabetically. Now it sorts by priority score so a 120-client firm sees
their urgent clients first." -->

## How tested

<!-- Be honest about what you actually exercised.
- [ ] Manual smoke against my own ~/.practiq/ data
- [ ] Vitest unit test (commit hash)
- [ ] Playwright e2e (commit hash)
- [ ] CI green
- [ ] None — please review carefully -->

## Breaking change?

<!-- - [ ] No
- [ ] Yes — describe what callers must change.
If yes, also add the `breaking` label and bump the next release accordingly. -->

## Linked issue(s)

<!-- Closes #N / Refs #N -->

## Checklist

- [ ] Followed Conventional Commits in the PR title (`feat:`, `fix:`, `docs:`, ...)
- [ ] `npm run type-check` passes
- [ ] `npm run lint` passes
- [ ] New code has tests (or there's a good reason it doesn't)
- [ ] Docs updated if behavior changed
- [ ] No `.env`, secrets, or customer data added to the diff
- [ ] AGPL-3.0 compatible (no closed-source deps, no binary blobs without source)
100 changes: 100 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: CI

on:
pull_request:
branches: [main]
push:
branches: [main]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

permissions:
contents: read

jobs:
type-check:
name: Type check (TypeScript)
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install --no-audit --no-fund
# The Prisma client generates to src/generated/prisma (custom output);
# tsc needs it present or every prisma.* call resolves to `any`.
- run: npx prisma generate
- run: npm run type-check

lint:
name: Lint (eslint)
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install --no-audit --no-fund
- run: npm run lint

build:
name: Build (all workspaces)
runs-on: ubuntu-22.04
env:
# `next build` of this heavy app (pdfjs/exceljs/pptxgenjs/tiptap/...)
# exceeds the default V8 heap on the 7 GB runner → OOM. Raise it.
NODE_OPTIONS: --max-old-space-size=6144
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install --no-audit --no-fund
- run: npm run build

test:
name: Test (vitest)
runs-on: ubuntu-22.04
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: practiq_test
ports: ['5432:5432']
options: >-
--health-cmd="pg_isready -U postgres"
--health-interval=10s
--health-timeout=5s
--health-retries=5
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/practiq_test
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install --no-audit --no-fund
- run: npx prisma generate
- run: npm run test --if-present

mcp-pack-check:
name: '@cliwant/practiq-mcp — npm pack dry-run'
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install --no-audit --no-fund
- run: npm run build --workspace=packages/mcp
- name: Verify tarball contents
run: |
cd packages/mcp
npm pack --dry-run --json > /tmp/pack.json
echo "Tarball size: $(jq -r '.[0].size' /tmp/pack.json) bytes"
# Fail if tarball > 200KB — sanity check that we didn't accidentally ship src/
test "$(jq -r '.[0].size' /tmp/pack.json)" -lt 204800 || (echo "Tarball too large — check files/.npmignore" && exit 1)
Loading
Loading