Thanks for taking an interest. This document covers getting the project running, the checks a change has to pass, and how the codeyam workflow this project is built with fits in.
You need Node.js 24 (the version CI runs) and git. You do not need a database, a hosting account, or an API key.
git clone https://github.com/codeyam-ai/thinking-map && cd thinking-map
npm run setup # install dependencies, provision PostgreSQL, push the schema, seed
npm run dev # http://localhost:3000With no DATABASE_URL set, setup starts a local PostgreSQL server of its own
and writes the connection string to .env.local. Set DATABASE_URL yourself and
that database is used instead, untouched. See DATABASE.md for the
full picture, including where credentials go and how to deploy.
Credentials never go in .env. That file is committed and holds documented
placeholders only. Real connection strings and keys belong in .env.local, which
is gitignored and overrides every value in .env.
Run these before opening a pull request. CI
(.github/workflows/ci.yml) runs the same three on
every PR, so anything that passes locally passes there.
npx prisma generate # the Prisma client is generated, not committed — run this first
npx tsc --noEmit # type-check; must be clean
npm test # vitest, ~1150 tests
npm run build # next buildA few things worth knowing:
npx prisma generatefirst, always. The generated client is not in git. A type error naming a model field that plainly exists inprisma/schema.prismaalmost always means the client on disk is stale.- The DB-backed tests provision their own PostgreSQL and stop it afterwards
(
app/lib/testDatabase.ts), so you do not need to run a database for them. SetTEST_DATABASE_URLonly to point them at a database you already have — and use a direct connection, sincedb pushneeds a real session. npm teststill needsDATABASE_URLset to something, even though nothing connects to it.app/lib/prisma.tsresolves it at module load, so a pure unit test that importsmapStoreorexchangefor a database it never touches throws before any test runs.npm run setupwrites a real value into.env.local, so this only bites a clone that skipped setup — and CI, which passes a placeholder. If you seeDATABASE_URL is not setfrom a test with no database in sight, that is this, not your change.npm run lintdoes not pass yet. The ESLint config was unrunnable for most of this project's life; it works now, and 14 React Compiler violations remain to be cleared. That work is tracked in.codeyam/plans/lint-runs-and-ci-keeps-it-running.md, and lint is deliberately not a CI gate until it is clean. Please don't add new violations, and don't silence the rules wholesale.
- Every
it()block has a//comment directly above it explaining what the test verifies and why it matters — not a restatement of the title. These descriptions are read by tooling and shown in the codeyam UI. - Test behavior, not implementation. Assert on output and observable effects so tests survive refactors.
- Tests must not depend on what is running on your machine. No fixed shared ports, no assumptions about a neighbouring dev server.
- Branch off
main. - Keep the change focused — one concern per PR.
- Make sure the four checks above pass.
- Fill in the pull request template. It asks what changed and how you verified it; both are genuinely read.
- Explain why in the description. What the diff does is visible; what problem it solves is not.
Commit messages are for a technical audience: concise, information-dense, focused on what changed and why.
This project is built with codeyam-editor — code and runnable data scenarios are authored side by side against a live preview. You do not need it to contribute; the npm commands above are the whole story.
If you do use it, note that .codeyam/ holds generated capture and scenario
scripts. They are rewritten by the tool, are excluded from linting, and are not
somewhere to make changes by hand.
Two quirks that look like bugs and are not:
package.jsonrunsnext dev --webpack. Next 16 defaults to Turbopack, and Turbopack's dev output does not hydrate through the codeyam preview proxy. This is deliberate.- A plain
npm run devdoes not serve/isolated-components/*, the fixture pages scenario captures render from — they would fill a dev session with convincing fake maps. UseCODEYAM_APP_PORT=1 npm run devif you want them. - Internal links are plain
<a>elements withsuppressHydrationWarning, notnext/link. The preview proxy serves the app under a path prefix and rewriteshrefin the server HTML, sonext/linkwould hydrate against a different href on every capture. Please keep that pattern.
If your change touches auth, file uploads, email, or another external service,
read FEATURE_PATTERNS.md first — it records decisions
already made so you don't have to relitigate them.
If your change touches how an agent attaches to a map, read
AGENT_CONTRACT.md.
Open an issue using one of the templates. A bug report that includes what you expected, what happened, and how to reproduce it is worth ten that don't.
This project ships a Code of Conduct. By participating you agree to uphold it.
By contributing, you agree that your contributions are licensed under the MIT License that covers this project.