~kris/dots

srice

ref: e98f3b030dc24445bd55c68d95d2d81933fd68b3 srice/doc/files/codexAudit.md -rw-r--r-- 16.0 KiB
e98f3b03 — Kris Yotam chore: sync local state after restore (push updates, no pull) a month ago

#Codex Structural Audit

Generated: 2026-05-20

Scope: structural issues in krisyotam.com, with emphasis on making the codebase leaner, easier to navigate, and safer to change by August. This audit does not cover visual design polish or content quality.

#Executive Summary

The main problem is not one bad subsystem. The project has several parallel sources of truth that have drifted:

  • Content type definitions are repeated across routing, sync scripts, feeds, sitemap, search, SEO, and tests.
  • SQLite path ownership is split between root data/ and stale public/data/ artifacts.
  • URL resolution exists in several forms: Next rewrites, canonical helpers, component fallbacks, sitemap, JSON-LD, and script utilities.
  • src/app mixes route modules with content payloads.
  • Client boundaries are broader than they need to be, especially around layout and listing pages.
  • public/scripts contains both browser assets and private operational tooling.
  • Large CSS and data modules have become catch-all files.

The highest-value August target is:

  1. One content registry.
  2. One database root.
  3. One canonical URL resolver.
  4. One script path helper.
  5. Route folders that only contain route code.
  6. Shared listing and tracking primitives instead of repeated page clients.

#Severity 1: Data and Routing Sources of Truth

#1. Content type lists are duplicated and inconsistent

Evidence:

  • src/app/(content)/[type]/config.ts
  • next.config.mjs
  • src/lib/seo.ts
  • src/lib/content.ts
  • src/lib/graph.ts
  • src/app/sitemap.ts
  • src/app/api/content/search/route.ts
  • src/app/api/content/md/[slug]/route.ts
  • src/app/api/system/utils/route.ts
  • public/scripts/dev/syncContent.js
  • public/scripts/dev/slugCollisions.js
  • public/scripts/prod/magic-urls.js
  • public/scripts/dev/generateMetadata.js

Why it matters:

Adding or changing a content type requires edits in many unrelated files. Some lists include documents, til, now, scripts, notebooks, or sequences; others exclude them. That makes behavior hard to predict across feeds, search, sitemap, sexy URLs, and sync.

Fix:

Create a single registry that defines each content surface:

  • table name
  • public route
  • canonical URL mode
  • sync source
  • date column
  • category column
  • tag relation
  • ratings support
  • feed/search/sitemap inclusion
  • MDX import directory

Suggested file:

  • src/config/contentRegistry.ts for app/runtime code.
  • scripts/lib/contentRegistry.mjs or generated JSON for CommonJS scripts and next.config.mjs.

First batch:

  1. Introduce the registry with current behavior only.
  2. Convert read-only consumers: src/lib/seo.ts, src/lib/content.ts, src/app/sitemap.ts, src/app/api/content/search/route.ts.
  3. Convert write/sync scripts after the registry is proven.

#2. Database artifact ownership is split

Evidence:

  • Runtime defaults use root data/ via src/lib/db.ts.
  • Root data/*.db is explicitly tracked by .gitignore.
  • public/data/content.db, public/data/media.db, and public/data/system.db exist as zero-byte files.
  • public/scripts/doc/syncDocs.js resolves ../../data/content.db from inside public/scripts/doc, which lands at public/data/content.db.
  • public/scripts/dev/syncNotebooks.js has the same public-data path issue.
  • public/scripts/dev/blogActivity.js and public/scripts/prod/magic-urls.js still reference public DB paths.

Why it matters:

The app reads one database root while some scripts mutate or inspect another. This creates silent drift and makes script output untrustworthy. It also keeps fake DB files under a web-served directory.

Fix:

Make root data/ the only SQLite root. Add a shared script helper:

  • scripts/lib/paths.mjs
  • exports PROJECT_ROOT, DATA_DIR, CONTENT_DIR, and dbPath(name)
  • honors KRISYOTAM_DATA_DIR and KRISYOTAM_CONTENT_DIR

First batch:

  1. Update syncDocs.js, syncNotebooks.js, blogActivity.js, and magic-urls.js to use the helper.
  2. Remove stale zero-byte public/data/*.db.
  3. Document which files in data/ are source snapshots and which are derived artifacts.
  4. Make git.js fail on core sync errors instead of catching and continuing.

#3. Canonical URL behavior is duplicated and drifting

Evidence:

  • next.config.mjs builds sexy URL rewrites directly from content.db.
  • src/lib/canonical-url.ts mirrors the type list and reserved slug rules.
  • src/app/(content)/[type]/[category]/[slug]/page.tsx uses /${slug} for metadata but hierarchical URLs for JSON-LD and breadcrumbs.
  • Shared components fall back to /${slug} in src/components/content/table.tsx, src/components/content/directory.tsx, and src/components/content/mediaCard.tsx.
  • Some clients pass route fields that are ignored by shared components.

Why it matters:

The site convention is sexy URLs. Today that rule is implemented partly by rewrite generation, partly by helper functions, and partly by UI component fallbacks. SEO, JSON-LD, sitemap, breadcrumbs, and client links can disagree.

Fix:

Normalize URLs server-side and pass item.url everywhere. Components should render one URL field instead of rebuilding URLs locally.

First batch:

  1. Add a server helper that maps DB rows to normalized content cards with url.
  2. Use getCanonicalContentUrl or a generated route manifest in metadata, JSON-LD, breadcrumbs, citations, and view trackers.
  3. Remove fallback URL building from table, directory, and media-card components after callers pass URLs.

#Severity 2: App Structure and Route Ownership

#4. src/app contains content payloads

Evidence:

  • src/app/(content)/til/content/*.mdx
  • src/app/(content)/now/content/*.mdx
  • src/app/(misc)/surveys/content/*.survey.md

Why it matters:

The App Router tree should show routing and rendering ownership. Source content inside route folders makes it harder to scan the app tree and blurs the line between code and authored content.

Fix:

Move these payloads to src/content/... or the external content repo, then keep src/app limited to route modules, layouts, loading states, route-local clients, and route-local styles.

First batch:

  1. Move TIL and Now content loaders behind src/lib/til.ts and src/lib/now.ts.
  2. Move the physical files only after imports are centralized.
  3. Repeat for surveys after the route behavior is covered by tests.

#5. TIL and Now detail pages load too much

Evidence:

  • src/app/(content)/til/page.tsx
  • src/app/(content)/til/[slug]/page.tsx
  • src/app/(content)/now/page.tsx
  • src/app/(content)/now/[slug]/page.tsx

Why it matters:

Index and detail pages repeat full-collection loading and MDX import logic. Detail routes should not scale with collection size.

Fix:

Extract loaders:

  • getTilEntries()
  • getTilEntry(slug)
  • getNowEntries()
  • getNowEntry(slug)

Then use collection loaders only for indexes and static params.

#6. Route groups have dead or unclear boundaries

Evidence:

  • src/app/(info) is empty.
  • src/app/(media) is empty.
  • Media-like pages live under (tracking).
  • Misc pages under (misc) include several unrelated page families.

Why it matters:

Empty and vague groups weaken the mental map. The App Router tree should answer "where does this page belong?" quickly.

Fix:

Remove empty route groups or add a short route ownership note in .config/.codex/docs/routes.md and the architecture map.

#Severity 2: Client Boundaries and Repeated UI State

#7. Layout header is client-side too high in the tree

Evidence:

  • src/components/layout/header.tsx starts with "use client".
  • It is imported broadly by server-rendered pages.

Why it matters:

Mostly static header markup should not widen the client boundary. The interactive part should be a small island.

Fix:

Split into:

  • server-safe header renderer
  • small client help or tooltip component
  • pure formatting helpers

#8. Listing clients repeat the same state machinery

Evidence:

  • src/app/(content)/[type]/client.tsx
  • src/app/(content)/til/client.tsx
  • src/app/(content)/now/client.tsx
  • src/app/(content)/scripts/client.tsx
  • src/app/(content)/sequences/client.tsx

Repeated logic includes:

  • search state
  • URL query view sync
  • category or tag option construction
  • date sorting
  • empty states
  • header data fallbacks
  • slug banners and single-entry modes

Why it matters:

Every new collection page copies decisions from older pages. Small behavior fixes then require many edits.

Fix:

Extract:

  • src/hooks/useContentListingState.ts
  • src/components/content/CollectionShell.tsx
  • src/components/content/FacetIndex.tsx

Keep route clients responsible only for data shape and item renderer choice.

#9. Tracking pages repeat browser scaffolding

Evidence:

  • src/components/media/tracking-overview.tsx already contains a shared renderer.
  • src/app/(tracking)/games/client.tsx still hand-rolls tabs, stat strips, sections, pagination, and empty states.
  • src/app/(tracking)/film/watched/client.tsx and src/app/(tracking)/anime/watched/client.tsx repeat filter and grid scaffolding.

Fix:

Extend TrackingOverview, then add a generic TrackingGridBrowser for watched/read/played lists.

#10. PageDescription owns too many jobs

Evidence:

  • src/components/layout/page-description.tsx

Current responsibilities:

  • markdown-link parsing
  • icon lookup
  • modal open state
  • sounds
  • compact modal markup
  • expanded modal markup

Fix:

Extract:

  • pure parseMarkdownLinks helper with tests
  • shared modal body component
  • narrow client shell for open and close state

#Severity 2: CSS and Theme Structure

#11. globals.css is a catch-all

Evidence:

  • src/app/globals.css is about 1,979 lines.
  • It contains imports, viewport behavior, code block overrides, hover-card primitives, typography, footer animation, comments, sidenotes, footnotes, lede cards, and print styles.

Why it matters:

Global CSS is now a shared junk drawer. It is hard to know whether a class is global by design, legacy, or route-specific.

Fix:

Move domain styles into src/app/styles/core/* and import them through a single file:

  • base.css
  • typography.css
  • code.css
  • comments.css
  • footnotes.css
  • sidenotes.css
  • print.css
  • cards.css
  • motion.css

Keep globals.css as the import root plus true app-wide tokens.

#12. Theme tokens duplicate fallback and class-based modes

Evidence:

  • src/app/styles/themes/default.css
  • duplicate no-JS dark-mode and .dark definitions
  • repeated pastel token blocks

Fix:

Use layered token groups or generate theme CSS from one source. The first target is no behavior change: reduce duplicate declarations while preserving fallback behavior.

#Severity 3: Scripts and Tooling Shape

#13. Private operational scripts live under public/

Evidence:

  • public/scripts/dev/*
  • public/scripts/doc/*
  • public/scripts/prose/*
  • public/scripts/verse/*
  • public/scripts/doc/filelist.txt

Why it matters:

Only browser-delivered scripts belong under public/. Commit tooling, DB mutators, importers, document sync, and prose tools should not be web-served.

Fix:

Target shape:

  • public/scripts/footnotes.js
  • public/scripts/sidenotes.js
  • public/scripts/prod/* only if browser-delivered or server-used from public path
  • scripts/dev/*
  • scripts/doc/*
  • scripts/prose/*
  • scripts/verse/*
  • scripts/lib/*

Migration needs compatibility shims because project memory currently says script subdirectories are fixed under public/scripts/{auth,dev,doc,prod,prose,verse}. This should be changed deliberately in the architecture docs when the migration starts.

#14. Script comments and hardcoded paths are stale

Evidence:

  • public/scripts/dev/syncContent.js still documents public/scripts/keep.
  • public/scripts/dev/generateMetadata.js hardcodes PROJECT_ROOT = '/home/krisyotam/dev/krisyotam.com'.
  • Several scripts hardcode DB or content locations instead of deriving from project root and env vars.

Fix:

After the path helper lands, convert scripts one family at a time and remove stale comments while touching each file.

#Severity 3: Large Data Modules and Testing

#15. Database modules are too broad

Evidence:

  • src/lib/media-db.ts is about 837 lines.
  • src/lib/data.ts is about 713 lines.
  • src/lib/system-db.ts is about 620 lines.
  • Direct SQL is spread across app routes, lib modules, and scripts.

Fix:

Split by domain once the registry exists:

  • content collections
  • content taxonomy
  • content detail lookup
  • media film
  • media tv
  • media anime and manga
  • media games
  • system roll pages
  • system social pages

Avoid splitting before the registry and DB path fixes, or it will preserve the same drift in more files.

#16. Tests cover utilities more than structure

Evidence:

  • vitest.config.ts uses Node environment only.
  • Existing tests focus on pure utility and config behavior.
  • Route clients, route handlers, URL normalization, DB path resolution, and theme tokens have little visible coverage.

Fix:

Start with tests that protect the refactors:

  1. Content registry consumers agree on valid types.
  2. DB path helper resolves root data/ by default.
  3. Canonical URL resolver returns sexy URLs and document overrides.
  4. Listing state hook filters and sorts deterministically.
  5. API route handlers return consistent error shapes.

Add jsdom only for components that actually need browser interaction.

#Proposed Work Division After Deduplication

This is the cleanest split between Claude and Codex without both agents touching the same files at once.

#Codex-owned first batch

Files likely touched:

  • src/lib/db.ts
  • new scripts/lib/paths.mjs
  • public/scripts/doc/syncDocs.js
  • public/scripts/dev/syncNotebooks.js
  • public/scripts/dev/blogActivity.js
  • public/scripts/prod/magic-urls.js
  • public/scripts/dev/git.js
  • tests for DB path behavior

Goal:

Fix DB root drift and make script path resolution trustworthy.

#Claude-owned first batch

Files likely touched:

  • src/app/(content)/[type]/config.ts
  • src/lib/seo.ts
  • src/lib/content.ts
  • src/app/sitemap.ts
  • src/app/api/content/search/route.ts
  • new content registry file
  • tests for registry consistency

Goal:

Create the content registry and convert read-only consumers.

#Codex-owned second batch

Files likely touched:

  • src/lib/canonical-url.ts
  • src/app/(content)/[type]/[category]/[slug]/page.tsx
  • src/app/(content)/[type]/page.tsx
  • src/components/content/table.tsx
  • src/components/content/directory.tsx
  • src/components/content/mediaCard.tsx

Goal:

Normalize canonical URLs once and pass item.url through shared components.

#Claude-owned second batch

Files likely touched:

  • src/app/(content)/til/page.tsx
  • src/app/(content)/til/[slug]/page.tsx
  • src/app/(content)/now/page.tsx
  • src/app/(content)/now/[slug]/page.tsx
  • new src/lib/til.ts
  • new src/lib/now.ts

Goal:

Extract TIL and Now loaders before moving content out of route folders.

#Later shared batches

  • CSS split: one agent owns globals.css extraction; the other only reviews imports.
  • Listing shell: one agent owns content listing state; the other owns tracking grid browser.
  • Script migration out of public/: do only after path helper and docs are updated.
  1. Fix DB root drift and path helper.
  2. Add content registry and convert read-only consumers.
  3. Normalize canonical URL generation and require item.url.
  4. Extract TIL and Now loaders.
  5. Split header and PageDescription client islands.
  6. Extract listing and tracking primitives.
  7. Split globals.css.
  8. Move private scripts out of public/.
  9. Split broad DB modules by domain.

#Notes for Merge With Claude Audit

No claudeAudit.md was present in the repo root when this file was written. When Claude's file appears, merge by theme rather than by agent:

  • Data and scripts
  • Content registry
  • Canonical URLs
  • Route tree ownership
  • Client boundaries
  • CSS and themes
  • Tests
  • Work division

Deduplicate by file path before assigning fixes. The files most likely to attract conflicts are:

  • src/app/(content)/[type]/config.ts
  • src/lib/seo.ts
  • src/lib/content.ts
  • src/lib/data.ts
  • src/lib/canonical-url.ts
  • next.config.mjs
  • src/app/globals.css
  • public/scripts/dev/git.js
  • public/scripts/dev/syncContent.js