# Contributor handoff — Chalarangelo/30-seconds-of-code

> Canonical page: https://codevetter.com/unpack/30-seconds-of-code/agent-handoff

# Contributor handoff — Chalarangelo/30-seconds-of-code

Scanned commit bd756f8b2283a38560efe83cb30af38324d4e9e9 (2026-09-09). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Conventions: ESM everywhere, #src/#spec import aliases, single quotes + semicolons + multiline trailing commas, class-static utility style, and ActiveRecord-ish model scopes. Safe edit boundary is content/ for content work (CONTRIBUTING restricts PRs to content/snippets and content/collections) and src/ for pipeline code — never edit generated paths (.content/, public/search-data.json, src/astro/timestamp.js, etc. — all gitignored). Before touching rendering, read settings.js, contentUtils/config.js, extractor.js, the modelWorkers, and the relevant model+adapter pair. Run 'npm test' (Vitest) after changes; use Loader.buildFactories in specs. Traps: global model registry, class-name coupling, scheduled-vs-published filtering differences between dev and prod, and the mandatory prepare step before any astro command.
- Always run the prepare step before astro commands: 'npm run dev'/'npm run build' chain it via pre-hooks, but a bare 'astro dev', 'astro build', or editor-driven vitest run against a missing .content/ will crash — .content is gitignored so fresh clones must generate it. — [package.json#L44-51](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/package.json#L44-L51) [.gitignore](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/.gitignore) [src/astro/pages/index.astro#L13-14](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/astro/pages/index.astro#L13-L14)
- Import style: use the '#src/…' and '#spec/…' aliases declared in package.json 'imports' (mirrored in jsconfig.json paths); the codebase is 'type': 'module' and requires Node >=22.14.0. — [package.json#L35-42](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/package.json#L35-L42) [package.json#L69-71](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/package.json#L69-L71) [jsconfig.json](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/jsconfig.json)
- Code style is enforced by eslint flat config: single quotes (avoidEscape ok), semicolons, always-multiline comma-dangle (functions never), as-needed arrow-parens, 1tbs braces, plus prettier with prettier-plugin-astro — match surrounding style since CI does not lint. — [eslint.config.js](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/eslint.config.js) [.prettierrc](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/.prettierrc) [globals.js](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/globals.js)
- Recommended read order for pipeline work: src/config/settings.js → src/lib/contentUtils/config.js → extractor.js → modelWorkers/* → src/models/* → src/adapters/page* → src/serializers/* → src/astro/pages/*. (inferred) — [src/config/settings.js](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/config/settings.js) [src/lib/contentUtils/extractor.js](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/lib/contentUtils/extractor.js) [src/models/models.js](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/models/models.js) [src/adapters/page.js](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/adapters/page.js)
- In specs, construct records via Loader.loadModules() + Loader.buildFactories() with named traits (e.g. SnippetFactory.create('published', {id: 'x'})) — never new models directly without understanding that each construction registers globally in Model.instances. — [spec/models/snippet.test.js#L5-30](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/spec/models/snippet.test.js#L5-L30) [src/lib/loader.js#L56-76](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/lib/loader.js#L56-L76) [src/core/model.js#L55](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/core/model.js#L55)
- Do not rename model classes, page adapters, or serializers: Page.from uses object.constructor.name, the content.json reviver uses the 'model' string field, and serializeAs concatenates names — renaming requires updating all three conventions at once. — [src/adapters/page.js#L10-13](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/adapters/page.js#L10-L13) [src/lib/loader.js#L47-50](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/lib/loader.js#L47-L50) [src/models/contentModel.js#L118-127](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/models/contentModel.js#L118-L127)
- Dev/prod asymmetry: NODE_ENV=development includes scheduled (future dateModified) snippets in generated pages; production excludes them — verify dateModified front-matter when a snippet 'disappears' after deploy. — [src/lib/astroContent.js#L45-49](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/lib/astroContent.js#L45-L49) [src/models/snippet.js#L180-186](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/models/snippet.js#L180-L186)
- CONTRIBUTING ground rules restrict content PRs to content/snippets and content/collections; content should follow the writing guidelines (US spelling, short sentences, Grade-10 level, imperative code docs) in CONTRIBUTING.md. — [CONTRIBUTING.md](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/CONTRIBUTING.md)
- Use 'bin/prepare dev --fast-highlight' (Prism) for local iteration — Shiki highlighting is the slow path reserved for full builds; remember Prism mode appends a script tag to rendered HTML so markup differs slightly between modes. — [bin/prepare#L69-74](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/bin/prepare#L69-L74) [src/lib/contentUtils/markdownParser/markdownParser.js#L113-118](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/lib/contentUtils/markdownParser/markdownParser.js#L113-L118)
- Generated outputs to never hand-edit: .content/**, src/astro/timestamp.js, public/search-data.json, public/sitemap.xml, public/feed.xml, public/_redirects, public/components, public/assets — all produced by bin/prepare and listed in .gitignore. — [.gitignore](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/.gitignore) [src/config/settings.js#L43-54](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/config/settings.js#L43-L54)
- Debugging/exploration tool: 'npm run console' opens a REPL with all models, serializers, pages, PreparedQueries functions, and a prebuilt documentIndex — the fastest way to inspect the hydrated content graph. — [bin/console](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/bin/console) [src/lib/preparedQueries.js](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/lib/preparedQueries.js)
- When editing the markdown pipeline, respect documented plugin ordering: highlightCode, embedCodepensFromLinks, transformArticleEmbeds must run before remarkRehype (mdast phase); linkInlineCode must run before safeguardExternalLinks; transformHeadings handles only h2-h4 and adds the linkable ids TocReader later matches with a regex. — [src/lib/contentUtils/markdownParser/markdownParser.js#L52-95](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/lib/contentUtils/markdownParser/markdownParser.js#L52-L95) [src/lib/contentUtils/tocReader.js#L5-7](https://github.com/Chalarangelo/30-seconds-of-code/blob/bd756f8b2283a38560efe83cb30af38324d4e9e9/src/lib/contentUtils/tocReader.js#L5-L7)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
