Files
freno-dev/package.json
Paperclip Agent 89f56fc78a metrics: stand up the weekly funnel job (FRE-202)
`marketing/metrics/weekly.md` has been a placeholder since the marketing tree
landed — it promised a funnel and the one thing that moved, and nothing
produced it. This adds the producer: one command reads the live databases and
rewrites the file.

`scripts/weekly-metrics.ts` writes `marketing/metrics/weekly.md` from
`VisitorAnalytics` (visits, downloads, campaigns) and the-nook's `trials`,
`licenses`, `activations` (the paid funnel). It needs four env vars —
TURSO_DB_URL/TOKEN and NOOK_DB_URL/TOKEN — and imports no server env, so the
job runs from a checkout that has no Stripe or Apple secrets.
`src/server/weekly-metrics.ts` holds the queries and the renderer, taking both
connections as arguments; the tests run them against an in-memory SQLite shaped
like production, the same way the backfill suite does.

The campaign breakdown groups exactly as `getAnalyticsSummary.topCampaigns`
does (top 10, untagged excluded), so the weekly read and /analytics cannot
drift into different label sets.

The first real report says more about the instrumentation than about demand,
and the renderer computes that rather than asserting it:

- every addressed row the table has ever held (12,035 of 12,048) is loopback,
  so "unique visitors" is one host and per-channel reach cannot be read;
- the landing door and the file route both write `/api/downloads/thenook`, so
  "download click" and "DMG served" are one label — one served click writes two
  rows, a failed click one, a Sparkle update one;
- `POST /api/the-nook/checkout` records nothing, so checkout start is only a
  page-view proxy;
- `VisitorAnalytics` has no host dimension, so the Nook's `/` is freno.me's `/`.

Those three gaps are reported beside the numbers, not papered over. Week 0
(2026-10-22 → 2026-10-29): visit 61, download 156, trial 2, checkout 0,
purchase 0, activation 0 — and the one thing that moved is the download stage,
0 → 156, because the label was introduced that week.

Tests: `bun test src/server/weekly-metrics.test.ts` — 12 pass, 0 fail. The full
suite's 15 failures are pre-existing: this checkout's .env lacks
NOOK_LICENSE_PRIVATE_KEY, NOOK_STRIPE_SK/WEBHOOK/PRICE and LINEAGE_JWT_SECRET,
and every failure is that env validation.

Scripts/ is gitignored, so `scripts/weekly-metrics.ts` was added with `-f`, the
way the existing tracked scripts are.

FRE-202
2026-10-29 15:58:51 +00:00

75 lines
2.5 KiB
JSON

{
"name": "freno.(dev/me)",
"type": "module",
"scripts": {
"dev": "vinxi dev",
"dev-flush": "vinxi dev --env-file=.env",
"build": "vinxi build",
"start": "NODE_OPTIONS='--import ./public/instrument.server.mjs' vinxi start",
"test": "bun test",
"test:security": "bun test src/server/security/",
"test:watch": "bun test --watch",
"test:coverage": "bun test --coverage",
"perf": "bun run scripts/perf-test.ts",
"perf:compare": "bun run scripts/perf-compare.ts",
"metrics:weekly": "bun --env-file=.env scripts/weekly-metrics.ts",
"nook:grant": "NODE_ENV=production bun --env-file=.env scripts/grant-nook-license.ts"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.953.0",
"@aws-sdk/s3-request-presigner": "^3.953.0",
"@libsql/client": "^0.15.15",
"@sentry/solidstart": "^10.67.0",
"@solidjs/meta": "^0.29.4",
"@solidjs/router": "^0.15.0",
"@solidjs/start": "^1.1.0",
"@tailwindcss/vite": "^4.0.7",
"@tiptap/core": "^3.14.0",
"@tiptap/extension-code-block-lowlight": "^3.14.0",
"@tiptap/extension-details": "^3.14.0",
"@tiptap/extension-details-content": "^2.26.2",
"@tiptap/extension-details-summary": "^2.26.2",
"@tiptap/extension-image": "^3.14.0",
"@tiptap/extension-link": "^3.14.0",
"@tiptap/extension-subscript": "^3.14.0",
"@tiptap/extension-superscript": "^3.14.0",
"@tiptap/extension-table": "^3.14.0",
"@tiptap/extension-table-cell": "^3.14.0",
"@tiptap/extension-table-header": "^3.14.0",
"@tiptap/extension-table-row": "^3.14.0",
"@tiptap/extension-task-item": "^3.14.0",
"@tiptap/extension-task-list": "^3.14.0",
"@tiptap/extension-text-align": "^3.14.0",
"@tiptap/pm": "^3.14.0",
"@tiptap/starter-kit": "^3.14.0",
"@trpc/client": "^10.45.2",
"@trpc/server": "^10.45.2",
"@tursodatabase/api": "^1.9.2",
"bcrypt": "^6.0.0",
"es-toolkit": "^1.43.0",
"fast-diff": "^1.3.0",
"google-auth-library": "^10.5.0",
"highlight.js": "^11.11.1",
"jose": "^6.1.3",
"mermaid": "^11.12.2",
"motion": "^12.23.26",
"solid-js": "^1.9.5",
"solid-tiptap": "^0.8.0",
"ua-parser-js": "^2.0.7",
"uuid": "^13.0.0",
"vinxi": "^0.5.7",
"zod": "^4.2.1"
},
"engines": {
"node": "24.x"
},
"devDependencies": {
"@sentry/vite-plugin": "^5.4.0",
"@tailwindcss/typography": "^0.5.19",
"@types/bcrypt": "^6.0.0",
"playwright": "^1.57.0",
"prettier": "^3.7.4",
"prettier-plugin-tailwindcss": "^0.7.2"
}
}