third-audience-mdx 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CLAUDE.md +41 -0
  2. package/INSTALLATION.md +367 -0
  3. package/README.md +303 -0
  4. package/WORKLOG.md +162 -0
  5. package/dist/cli/index.d.mts +1 -0
  6. package/dist/cli/index.d.ts +1 -0
  7. package/dist/cli/index.js +208 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/cli/index.mjs +185 -0
  10. package/dist/cli/index.mjs.map +1 -0
  11. package/dist/dashboard/auth.d.mts +16 -0
  12. package/dist/dashboard/auth.d.ts +16 -0
  13. package/dist/dashboard/auth.js +123 -0
  14. package/dist/dashboard/auth.js.map +1 -0
  15. package/dist/dashboard/auth.mjs +87 -0
  16. package/dist/dashboard/auth.mjs.map +1 -0
  17. package/dist/dashboard/routes/analytics-api-route.d.mts +6 -0
  18. package/dist/dashboard/routes/analytics-api-route.d.ts +6 -0
  19. package/dist/dashboard/routes/analytics-api-route.js +180 -0
  20. package/dist/dashboard/routes/analytics-api-route.js.map +1 -0
  21. package/dist/dashboard/routes/analytics-api-route.mjs +145 -0
  22. package/dist/dashboard/routes/analytics-api-route.mjs.map +1 -0
  23. package/dist/dashboard/routes/api-key-route.d.mts +8 -0
  24. package/dist/dashboard/routes/api-key-route.d.ts +8 -0
  25. package/dist/dashboard/routes/api-key-route.js +173 -0
  26. package/dist/dashboard/routes/api-key-route.js.map +1 -0
  27. package/dist/dashboard/routes/api-key-route.mjs +137 -0
  28. package/dist/dashboard/routes/api-key-route.mjs.map +1 -0
  29. package/dist/dashboard/routes/citation-route.d.mts +14 -0
  30. package/dist/dashboard/routes/citation-route.d.ts +14 -0
  31. package/dist/dashboard/routes/citation-route.js +202 -0
  32. package/dist/dashboard/routes/citation-route.js.map +1 -0
  33. package/dist/dashboard/routes/citation-route.mjs +166 -0
  34. package/dist/dashboard/routes/citation-route.mjs.map +1 -0
  35. package/dist/dashboard/routes/llms-txt-route.d.mts +6 -0
  36. package/dist/dashboard/routes/llms-txt-route.d.ts +6 -0
  37. package/dist/dashboard/routes/llms-txt-route.js +119 -0
  38. package/dist/dashboard/routes/llms-txt-route.js.map +1 -0
  39. package/dist/dashboard/routes/llms-txt-route.mjs +84 -0
  40. package/dist/dashboard/routes/llms-txt-route.mjs.map +1 -0
  41. package/dist/dashboard/routes/login-route.d.mts +6 -0
  42. package/dist/dashboard/routes/login-route.d.ts +6 -0
  43. package/dist/dashboard/routes/login-route.js +313 -0
  44. package/dist/dashboard/routes/login-route.js.map +1 -0
  45. package/dist/dashboard/routes/login-route.mjs +284 -0
  46. package/dist/dashboard/routes/login-route.mjs.map +1 -0
  47. package/dist/dashboard/routes/markdown-route.d.mts +15 -0
  48. package/dist/dashboard/routes/markdown-route.d.ts +15 -0
  49. package/dist/dashboard/routes/markdown-route.js +239 -0
  50. package/dist/dashboard/routes/markdown-route.js.map +1 -0
  51. package/dist/dashboard/routes/markdown-route.mjs +204 -0
  52. package/dist/dashboard/routes/markdown-route.mjs.map +1 -0
  53. package/dist/dashboard/routes/okf-route.d.mts +13 -0
  54. package/dist/dashboard/routes/okf-route.d.ts +13 -0
  55. package/dist/dashboard/routes/okf-route.js +184 -0
  56. package/dist/dashboard/routes/okf-route.js.map +1 -0
  57. package/dist/dashboard/routes/okf-route.mjs +149 -0
  58. package/dist/dashboard/routes/okf-route.mjs.map +1 -0
  59. package/dist/dashboard/routes/sitemap-ai-route.d.mts +6 -0
  60. package/dist/dashboard/routes/sitemap-ai-route.d.ts +6 -0
  61. package/dist/dashboard/routes/sitemap-ai-route.js +134 -0
  62. package/dist/dashboard/routes/sitemap-ai-route.js.map +1 -0
  63. package/dist/dashboard/routes/sitemap-ai-route.mjs +99 -0
  64. package/dist/dashboard/routes/sitemap-ai-route.mjs.map +1 -0
  65. package/dist/dashboard/ui/components/Sidebar.d.mts +5 -0
  66. package/dist/dashboard/ui/components/Sidebar.d.ts +5 -0
  67. package/dist/dashboard/ui/components/Sidebar.js +102 -0
  68. package/dist/dashboard/ui/components/Sidebar.js.map +1 -0
  69. package/dist/dashboard/ui/components/Sidebar.mjs +68 -0
  70. package/dist/dashboard/ui/components/Sidebar.mjs.map +1 -0
  71. package/dist/dashboard/ui/globals.css +175 -0
  72. package/dist/dashboard/ui/pages/BotAnalyticsPage.d.mts +5 -0
  73. package/dist/dashboard/ui/pages/BotAnalyticsPage.d.ts +5 -0
  74. package/dist/dashboard/ui/pages/BotAnalyticsPage.js +269 -0
  75. package/dist/dashboard/ui/pages/BotAnalyticsPage.js.map +1 -0
  76. package/dist/dashboard/ui/pages/BotAnalyticsPage.mjs +232 -0
  77. package/dist/dashboard/ui/pages/BotAnalyticsPage.mjs.map +1 -0
  78. package/dist/dashboard/ui/pages/BotManagementPage.d.mts +13 -0
  79. package/dist/dashboard/ui/pages/BotManagementPage.d.ts +13 -0
  80. package/dist/dashboard/ui/pages/BotManagementPage.js +177 -0
  81. package/dist/dashboard/ui/pages/BotManagementPage.js.map +1 -0
  82. package/dist/dashboard/ui/pages/BotManagementPage.mjs +153 -0
  83. package/dist/dashboard/ui/pages/BotManagementPage.mjs.map +1 -0
  84. package/dist/dashboard/ui/pages/LlmTrafficPage.d.mts +5 -0
  85. package/dist/dashboard/ui/pages/LlmTrafficPage.d.ts +5 -0
  86. package/dist/dashboard/ui/pages/LlmTrafficPage.js +203 -0
  87. package/dist/dashboard/ui/pages/LlmTrafficPage.js.map +1 -0
  88. package/dist/dashboard/ui/pages/LlmTrafficPage.mjs +168 -0
  89. package/dist/dashboard/ui/pages/LlmTrafficPage.mjs.map +1 -0
  90. package/dist/dashboard/ui/pages/SettingsPage.d.mts +8 -0
  91. package/dist/dashboard/ui/pages/SettingsPage.d.ts +8 -0
  92. package/dist/dashboard/ui/pages/SettingsPage.js +181 -0
  93. package/dist/dashboard/ui/pages/SettingsPage.js.map +1 -0
  94. package/dist/dashboard/ui/pages/SettingsPage.mjs +157 -0
  95. package/dist/dashboard/ui/pages/SettingsPage.mjs.map +1 -0
  96. package/dist/dashboard/ui/pages/SystemHealthPage.d.mts +5 -0
  97. package/dist/dashboard/ui/pages/SystemHealthPage.d.ts +5 -0
  98. package/dist/dashboard/ui/pages/SystemHealthPage.js +183 -0
  99. package/dist/dashboard/ui/pages/SystemHealthPage.js.map +1 -0
  100. package/dist/dashboard/ui/pages/SystemHealthPage.mjs +148 -0
  101. package/dist/dashboard/ui/pages/SystemHealthPage.mjs.map +1 -0
  102. package/dist/index.d.mts +84 -0
  103. package/dist/index.d.ts +84 -0
  104. package/dist/index.js +372 -0
  105. package/dist/index.js.map +1 -0
  106. package/dist/index.mjs +346 -0
  107. package/dist/index.mjs.map +1 -0
  108. package/package.json +125 -0
package/CLAUDE.md ADDED
@@ -0,0 +1,41 @@
1
+ # Project Rules
2
+
3
+ ## Scope
4
+ - Everything in this project's sessions stays inside THIS project folder only.
5
+ - Never create, modify, or move files outside this folder for this project's work.
6
+ - Whatever is typed in a session is scoped to this project — no spillover to other projects.
7
+
8
+ ## Worklog
9
+ - After every meaningful task, append to WORKLOG.md: date, what was asked, what was done, files touched.
10
+
11
+ ## Global Rules
12
+ - No deviation from the plan. No mock data.
13
+ - No database changes — no insert, no update, no delete, no drop. Query only.
14
+
15
+ ---
16
+
17
+ ## Execution: Ultracode & Workflows
18
+
19
+ - **Ultracode** is a session-scoped effort setting (`/effort ultracode`) that pairs max (xhigh) reasoning with automatic multi-agent workflow orchestration. Only the user can turn it on. When on, default to authoring and running a workflow for every substantive task (often several in sequence: understand → design → implement → review). Token cost is not a constraint in that mode. Drop back with `/effort high` or `/effort xhigh`.
20
+
21
+ - **Dynamic Workflows** are JavaScript scripts that orchestrate many subagents deterministically (primitives: `agent()`, `pipeline()` [default, no barrier], `parallel()` [barrier], `phase()`, `log()`, `budget()`). Intermediate results live in script variables, not context. Runs in the background; watch/control via `/workflows`. Default to `pipeline()`; use a barrier only for a genuine cross-item dependency (dedup/merge-all, early-exit on zero, cross-finding comparison). Caps: ~16 concurrent agents, 1000 per run.
22
+
23
+ - Even when ultracode is **OFF**, reach for a workflow WITHOUT asking when a task is clearly multi-part and parallelizable AND large enough to justify it — e.g. codebase-wide audits or bug sweeps, large migrations/refactors across many files, multi-source research, or drafting/comparing several independent plans. For anything smaller (single-file edits, quick fixes, one-off questions), just do it directly or use a single Agent. When unsure, briefly say what you'd run and roughly what it'd cost, then ask.
24
+
25
+ - Useful quality patterns to compose inside workflows: adversarial/perspective-diverse verification, judge panels, loop-until-dry discovery, multi-modal sweeps, and a final completeness critic. Never silently cap coverage — `log()` anything dropped.
26
+
27
+ - One-off workflow trigger: the keyword `ultracode` in a message, or "use a workflow".
28
+
29
+ ---
30
+
31
+ ## Discipline: Verify, Don't Guess
32
+
33
+ - You cannot see what the user sees. When you change anything with a visible or runnable result — UI, layout, rendered page, a chart, generated output, a file — editing the code is NOT evidence the result is correct. Do not reason that it "should look fixed" and report success.
34
+
35
+ - Before claiming any such change works: actually produce the result and inspect it. Open the browser, run the thing, open the file, take a screenshot — then do a genuine, critical look, hunting for what is still broken rather than confirming your own work.
36
+
37
+ - Never say "it looks fixed now," "that's resolved," or "done" on the strength of reasoning alone. If the actual result has not been observed, say exactly that: "I changed X; I have not verified the result yet."
38
+
39
+ - This generalizes past visuals: tests are not passing until you have run them, a build is not working until it built, a bug is not fixed until you have reproduced the original failure and watched it stop. Prefer observed truth over inferred truth every time you can observe.
40
+
41
+ - When you genuinely cannot verify (no browser, no way to run it), do not fake confidence. State the limitation, say what you would check, and tell the user exactly what to look at.
@@ -0,0 +1,367 @@
1
+ # Installation Guide
2
+
3
+ Complete step-by-step guide for adding `third-audience-mdx` to an existing Next.js App Router project.
4
+
5
+ ---
6
+
7
+ ## Prerequisites
8
+
9
+ - Node.js 18+
10
+ - Next.js 13+ (App Router)
11
+ - MDX content files (`.mdx` or `.md`) in a content directory
12
+
13
+ ---
14
+
15
+ ## Step 1 — Install the package
16
+
17
+ ```bash
18
+ npm install third-audience-mdx
19
+ ```
20
+
21
+ Or with pnpm / yarn:
22
+ ```bash
23
+ pnpm add third-audience-mdx
24
+ yarn add third-audience-mdx
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Step 2 — Run the setup wizard (recommended)
30
+
31
+ ```bash
32
+ npx third-audience init
33
+ ```
34
+
35
+ The wizard will:
36
+ 1. Detect your Next.js project
37
+ 2. Ask for your content directory (e.g. `content`)
38
+ 3. Ask for your data directory (e.g. `data`)
39
+ 4. Ask for a dashboard secret
40
+ 5. Write `middleware.ts` if it doesn't exist
41
+ 6. Append to `.env.local`
42
+ 7. Create the `data/` directory and update `.gitignore`
43
+
44
+ After the wizard, skip to [Step 6 — Add API routes](#step-6--add-api-routes).
45
+
46
+ ---
47
+
48
+ ## Step 3 — Wrap your Next.js config
49
+
50
+ **`next.config.ts`**
51
+ ```ts
52
+ import { withThirdAudience } from 'third-audience-mdx'
53
+ import type { NextConfig } from 'next'
54
+
55
+ const nextConfig: NextConfig = {
56
+ // your existing config here
57
+ }
58
+
59
+ export default withThirdAudience(
60
+ {
61
+ contentDir: 'content', // folder where your .mdx files live
62
+ dataDir: 'data', // folder for analytics logs
63
+ dashboard: true,
64
+ dashboardSecret: process.env.THIRD_AUDIENCE_SECRET,
65
+ },
66
+ nextConfig
67
+ )
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Step 4 — Add middleware
73
+
74
+ Create (or update) **`middleware.ts`** in your project root:
75
+
76
+ ```ts
77
+ export { thirdAudienceMiddleware as middleware } from 'third-audience-mdx'
78
+
79
+ export const config = {
80
+ matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
81
+ }
82
+ ```
83
+
84
+ This handles:
85
+ - `GET /any-page.md` → serves Markdown of the matching MDX file
86
+ - `Accept: text/markdown` header → serves Markdown automatically
87
+ - `/llms.txt`, `/sitemap-ai.xml`, `/okf/` → rewrites to the correct API handlers
88
+
89
+ If you already have a `middleware.ts`, call `thirdAudienceMiddleware` inside your existing function and return its result when it produces a response.
90
+
91
+ ---
92
+
93
+ ## Step 5 — Set environment variables
94
+
95
+ **`.env.local`**
96
+ ```
97
+ # Required
98
+ THIRD_AUDIENCE_SECRET=choose-a-strong-secret-here
99
+ NEXT_PUBLIC_SITE_URL=https://yoursite.com
100
+
101
+ # Optional (defaults shown)
102
+ TA_CONTENT_DIR=content
103
+ TA_DATA_DIR=data
104
+ ```
105
+
106
+ `THIRD_AUDIENCE_SECRET` protects the `/third-audience/` dashboard. Leave it blank only during local development.
107
+
108
+ ---
109
+
110
+ ## Step 6 — Add API routes
111
+
112
+ Create these files inside your `app/` directory. Each one is a one-liner that re-exports the handler from the package.
113
+
114
+ **`app/api/third-audience/markdown/[...slug]/route.ts`**
115
+ ```ts
116
+ export { GET } from 'third-audience-mdx/routes/markdown'
117
+ ```
118
+
119
+ **`app/api/third-audience/okf/[...path]/route.ts`**
120
+ ```ts
121
+ export { GET } from 'third-audience-mdx/routes/okf'
122
+ ```
123
+
124
+ **`app/api/third-audience/llms-txt/route.ts`**
125
+ ```ts
126
+ export { GET } from 'third-audience-mdx/routes/llms-txt'
127
+ ```
128
+
129
+ **`app/api/third-audience/sitemap-ai/route.ts`**
130
+ ```ts
131
+ export { GET } from 'third-audience-mdx/routes/sitemap-ai'
132
+ ```
133
+
134
+ **`app/api/third-audience/citation/route.ts`**
135
+ ```ts
136
+ export { GET, POST } from 'third-audience-mdx/routes/citation'
137
+ ```
138
+
139
+ **`app/api/third-audience/analytics/route.ts`**
140
+ ```ts
141
+ export { GET } from 'third-audience-mdx/routes/analytics'
142
+ ```
143
+
144
+ **`app/api/third-audience/bots-config/route.ts`**
145
+ ```ts
146
+ export { GET, POST } from 'third-audience-mdx/routes/bots-config'
147
+ ```
148
+
149
+ ---
150
+
151
+ ## Step 7 — Add the dashboard
152
+
153
+ Create these files to mount the dashboard at `/third-audience/`.
154
+
155
+ **`app/third-audience/layout.tsx`**
156
+ ```tsx
157
+ import type { ReactNode } from 'react'
158
+ import { Sidebar } from 'third-audience-mdx/dashboard/ui/components/Sidebar'
159
+ import 'third-audience-mdx/dashboard/ui/globals.css'
160
+
161
+ export const metadata = { title: 'Third Audience Dashboard' }
162
+
163
+ export default function DashboardLayout({ children }: { children: ReactNode }) {
164
+ return (
165
+ <html lang="en">
166
+ <body>
167
+ <div className="ta-layout">
168
+ <Sidebar />
169
+ <main className="ta-main">{children}</main>
170
+ </div>
171
+ </body>
172
+ </html>
173
+ )
174
+ }
175
+ ```
176
+
177
+ **`app/third-audience/page.tsx`** — Bot Analytics
178
+ ```tsx
179
+ import { BotAnalyticsPage } from 'third-audience-mdx/dashboard/ui/pages/BotAnalyticsPage'
180
+ export const dynamic = 'force-dynamic'
181
+ export default function Page() { return <BotAnalyticsPage /> }
182
+ ```
183
+
184
+ **`app/third-audience/citations/page.tsx`** — LLM Traffic
185
+ ```tsx
186
+ import { LlmTrafficPage } from 'third-audience-mdx/dashboard/ui/pages/LlmTrafficPage'
187
+ export const dynamic = 'force-dynamic'
188
+ export default function Page() { return <LlmTrafficPage /> }
189
+ ```
190
+
191
+ **`app/third-audience/bots/page.tsx`** — Bot Management
192
+ ```tsx
193
+ import { BotManagementPage } from 'third-audience-mdx/dashboard/ui/pages/BotManagementPage'
194
+ import fs from 'fs'
195
+ import path from 'path'
196
+ export const dynamic = 'force-dynamic'
197
+
198
+ export default function Page() {
199
+ const dataDir = process.env.TA_DATA_DIR ?? 'data'
200
+ const configPath = path.join(process.cwd(), dataDir, 'ta-bots-config.json')
201
+ const config = fs.existsSync(configPath)
202
+ ? JSON.parse(fs.readFileSync(configPath, 'utf-8'))
203
+ : { allowlist: [], blocklist: [], track_unknown: true }
204
+ return <BotManagementPage config={config} />
205
+ }
206
+ ```
207
+
208
+ **`app/third-audience/health/page.tsx`** — System Health
209
+ ```tsx
210
+ import { SystemHealthPage } from 'third-audience-mdx/dashboard/ui/pages/SystemHealthPage'
211
+ export const dynamic = 'force-dynamic'
212
+ export default function Page() { return <SystemHealthPage /> }
213
+ ```
214
+
215
+ ---
216
+
217
+ ## Step 8 — Add client-side citation tracker
218
+
219
+ Copy the script to your public folder:
220
+
221
+ ```bash
222
+ cp node_modules/third-audience-mdx/src/public/citation-tracker.js public/citation-tracker.js
223
+ ```
224
+
225
+ Add to your root layout (`app/layout.tsx`):
226
+
227
+ ```tsx
228
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
229
+ return (
230
+ <html lang="en">
231
+ <body>
232
+ {children}
233
+ <script src="/citation-tracker.js" async />
234
+ </body>
235
+ </html>
236
+ )
237
+ }
238
+ ```
239
+
240
+ This detects when users arrive from ChatGPT, Perplexity, Claude, Gemini, or Copilot and records the citation.
241
+
242
+ ---
243
+
244
+ ## Step 9 — Set up admin login
245
+
246
+ The dashboard at `/third-audience/` is protected by a login page. On first access, initialise the admin store:
247
+
248
+ ```bash
249
+ npx third-audience init-admin
250
+ ```
251
+
252
+ Or run the Node snippet manually:
253
+
254
+ ```bash
255
+ node -e "
256
+ const crypto = require('crypto');
257
+ const fs = require('fs');
258
+ const secret = process.env.THIRD_AUDIENCE_SECRET || 'ta-salt';
259
+ const password = 'Chang3M3Now!';
260
+ const hash = crypto.createHash('sha256').update(secret + password).digest('hex');
261
+ fs.mkdirSync('data', { recursive: true });
262
+ fs.writeFileSync('data/ta-admin.json', JSON.stringify({
263
+ passwordHash: hash,
264
+ isDefaultPassword: true,
265
+ createdAt: new Date().toISOString(),
266
+ lastLoginAt: null
267
+ }, null, 2));
268
+ console.log('Admin store created. Default password: Chang3M3Now!');
269
+ "
270
+ ```
271
+
272
+ **Default password: `Chang3M3Now!`**
273
+
274
+ On first login you will be immediately redirected to a password reset form. The dashboard shows a red warning banner until the default password is changed.
275
+
276
+ Add the login route:
277
+
278
+ **`app/api/third-audience/login/route.ts`**
279
+ ```ts
280
+ export { GET, POST } from 'third-audience-mdx/routes/login'
281
+ ```
282
+
283
+ ---
284
+
285
+ ## Step 10 — Update `.gitignore`
286
+
287
+ ```
288
+ # Third Audience — keep analytics local, not in git
289
+ data/ta-visits.jsonl
290
+ data/ta-citations.jsonl
291
+ data/ta-cache/
292
+ data/ta-admin.json
293
+ ```
294
+
295
+ The `data/ta-bots-config.json` file (your allowlist/blocklist) can optionally be committed.
296
+
297
+ ---
298
+
299
+ ## Step 10 — Verify everything works
300
+
301
+ ```bash
302
+ npx third-audience health
303
+ ```
304
+
305
+ Then start your dev server and check:
306
+
307
+ | URL | Expected |
308
+ |---|---|
309
+ | `/llms.txt` | Plain text list of all your content |
310
+ | `/sitemap-ai.xml` | XML sitemap with AI metadata |
311
+ | `/okf/` | Markdown index of all content |
312
+ | `/your-first-post.md` | Clean Markdown of that MDX file |
313
+ | `/third-audience/` | Bot Analytics dashboard |
314
+ | `/third-audience/health` | System Health page |
315
+
316
+ ---
317
+
318
+ ## Troubleshooting
319
+
320
+ **`.md` URLs return 404**
321
+ Make sure `middleware.ts` is at the project root (not inside `app/`) and the matcher covers the URL pattern.
322
+
323
+ **Dashboard shows no data**
324
+ Bot visits only appear after a real AI crawler hits your site. Use `curl -A "ClaudeBot/1.0" http://localhost:3000/` to simulate one.
325
+
326
+ **`contentDir` not found**
327
+ Set `TA_CONTENT_DIR` in `.env.local` to the correct path relative to your project root.
328
+
329
+ **Citation tracker not recording**
330
+ Confirm `citation-tracker.js` is in `public/` and the `<script>` tag is in your root layout. Test by visiting your site with `?utm_source=chatgpt` appended to the URL.
331
+
332
+ **Dashboard is open (no auth)**
333
+ Set `THIRD_AUDIENCE_SECRET` in `.env.local` and restart the dev server.
334
+
335
+ ---
336
+
337
+ ## Directory structure after setup
338
+
339
+ ```
340
+ your-nextjs-project/
341
+ ├── app/
342
+ │ ├── api/
343
+ │ │ └── third-audience/
344
+ │ │ ├── analytics/route.ts
345
+ │ │ ├── bots-config/route.ts
346
+ │ │ ├── citation/route.ts
347
+ │ │ ├── llms-txt/route.ts
348
+ │ │ ├── markdown/[...slug]/route.ts
349
+ │ │ ├── okf/[...path]/route.ts
350
+ │ │ └── sitemap-ai/route.ts
351
+ │ ├── third-audience/
352
+ │ │ ├── layout.tsx
353
+ │ │ ├── page.tsx
354
+ │ │ ├── citations/page.tsx
355
+ │ │ ├── bots/page.tsx
356
+ │ │ └── health/page.tsx
357
+ │ └── layout.tsx ← add citation-tracker.js <script> here
358
+ ├── public/
359
+ │ └── citation-tracker.js ← copied from node_modules
360
+ ├── data/ ← created by init wizard
361
+ │ ├── ta-visits.jsonl
362
+ │ ├── ta-citations.jsonl
363
+ │ └── ta-cache/
364
+ ├── middleware.ts
365
+ ├── next.config.ts
366
+ └── .env.local
367
+ ```