@activatus/code-standards
v3.3.6
Published
The Activatus code standards: the rules as Markdown, and the config files to copy. Install it so an AI agent can read the standards from node_modules.
Readme
🦘 Activatus Code Standards
👋 About Code Standards
One way of doing things, written down, so nobody has to guess.
This is the rulebook for how we write code at Activatus. It's a docs site, a pile of copy-paste config files, and a set of lint rules that'll dob you in before your reviewer has to.
The whole point: you should be able to wander into any Activatus project at 4pm on a Friday and know exactly where everything lives, like walking into a mate's shed and finding the 10mm socket first go.
🤔 Why this exists
Every team says they've got standards. Most of them live in one bloke's head and a Slack thread from 2022.
Ours live here. If it's not in this repo, it's not a standard, it's an opinion.
- 🧠 Readable by humans. If a new starter can't follow a file, the file's wrong, not the new starter.
- 🤖 Readable by AI. Claude Code and friends follow the same rules we do. No special treatment.
- 🚨 Enforced by the linter where we can. Rules that rely on everyone remembering are rules that get forgotten.
📦 Using it in a project
The standards ship as an npm package, published on npm (npmjs.com) and installed with pnpm, so an AI agent reads the exact version a project uses, straight from node_modules:
pnpm add -D @activatus/code-standards@latestThen tell your agent: "Follow the Activatus Code Standards. Start with node_modules/@activatus/code-standards/docs/Guides/setup.md." It prints a numbered list of the standards, you say which ones you don't want, and it sets up the rest. You never touch the terminal.
The package version is the standards version, and a project records it in full, such as 3.3.2, so the agent always knows where the project's up to.
🔢 Updating a project to newer standards? Run
pnpm add -D @activatus/code-standards@latest, then point the agent at the Version History: it reads only the entries newer than the project's version, does exactly what each one says, and records the new version. Cheaper than shouting the whole pub a round.
🚀 Get it running
You'll need Node 20+ and pnpm.
pnpm install
pnpm start
pnpm serveThat fires up the site locally with hot reload. Easy as.
The live site is at activatus-code-standards.vercel.app. That's the link to share.
| Command | What it does |
| ---------------- | -------------------------------------------- |
| pnpm start | 🔥 Dev server with hot reload |
| pnpm build | 📦 Builds the static site into build/ |
| pnpm serve | 👀 Serves the built site so you can check it |
| pnpm typecheck | 🔍 Runs TypeScript over the site config |
| pnpm format | ✨ Formats everything with Prettier |
🔎 Search only works on the built site. Run
pnpm buildthenpnpm serveif you want to test it. It won't show up inpnpm start, so don't go thinking you've broken it.
🐌 Install carking it on a slow connection? One of the packages is a big unit. Run
pnpm install --fetch-timeout 600000and go put the kettle on.
📚 What's in the box
| Section | What you'll find |
| ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| 📋 Templates | Ready-to-copy AGENTS.md, ESLint, Prettier, Stylelint and friends |
| 📖 Ontology | The code words we use and what each one means |
| 🔢 Version History | What changed in each version, and what a project has to do about it. Updating a project? Read only the versions newer than the one in its AGENTS.md |
| 🧭 Guides | Setting up a new project, dragging an old one up to scratch, and how design becomes code |
| 📏 Standards | Readable code, linting, formatting, styling, the tech stack and AI agent rules |
| 🏗️ Structure | Folders, components, naming, imports and API routes |
| 🧩 Design System Components | Every standard component and its props, so each project builds them the same way |
⚡ The rules, at pub-yarn speed
The full detail's on the site. This is the version you'd tell someone over a schooner.
✍️ Writing code
- 📄 No file over 300 lines. If it's longer, it's doing two jobs. Split it. (Test files get a leave pass.)
- 🗣️ Every name is real English words. Variables, props, form fields, types, files, folders, the lot.
button, notbtn. We're not paying by the letter. The one exception: names someone else owns, like Linear'sidor Node'scwdoption. - 🔒 Always
const. Needlet? Fine, but leave a comment saying why, or the linter knocks it back. - 🏹 Arrow functions everywhere.
const Button = () => {}. The wordfunctionis clutter, so we don't use it. - 🧹 Imports sort themselves. Prettier puts them in order every time you format, so nobody burns an afternoon shuffling them by hand.
- 🔄 No circular imports. Ever. If two files import each other, pull the shared bit into a third file.
- 🎯 A function does one thing. If you need the word "and" to describe it, it's two functions.
- 🧪 Every function and component gets a test file. One test file, one thing tested. No test, not finished.
- 🚫 Functions, never classes. Not even a little one.
- 📦 One parameter per function. Need more? Pass an object, so the call explains itself.
- 🚪 Return early. Deal with the dodgy cases up top instead of nesting four
ifs deep like a set of Russian dolls. - 🔢 No magic numbers.
MAXIMUM_RETRY_ATTEMPTS, not a random3sitting there like it owns the place. - 🗃️ Links go in
r, words people see go ins. Everything else sits at the top of the file that uses it until something else needs it too. Not sure where a value goes? The agent parks it inunsortedValues.tsand asks you at the end, instead of stopping the job to have a yarn about it. - 🏷️ Type names end in
PropsorType. So you can tell what you're looking at. - 💬 Comments explain why, not what. And no commented-out code. Git remembers, you don't have to.
🎨 Styling
- 🌬️ Tailwind for everything.
- 📐 Flexbox first. Split layouts into child components. Only use CSS grid if someone specifically asks for it.
- 🎨 Colours come from the global palette. Full stop. No hard-coded hex, no one-off values. If the colour's not in the palette, it's not in the build.
📖 Docs
- 📝 Docs are plain Markdown in
docs/, and every file is a Decision Doc. Same folders in every project. Agents read the files; humans browse them at/docs. - 🔒
/docsonly exists whenDOCS_URLis set. It's never set in production, so the docs never leak onto a live site. - ✅ Not finished until the docs are updated. Change how something works, fix the doc in the same change.
🤖 Workflow is the project's call
- 🧭 Branches, commit messages, Pull Requests and whether AI agents may commit are up to each project. Every team runs its work differently, so it goes in the project's own
AGENTS.mdand docs, not here. These standards are the base for the code itself.
🚦 Status circles
Setup asks if you want them. Say yes, and the agent reports every ticket or piece of work as one line, with a circle that tells you at a glance whether you need to lift a finger:
| Circle | Means | | ------ | ---------------------------------------------------------------------------- | | ✅ | Merged, in UAT or done. Nothing to do | | 🟢 | Pull Request ready for you to review and merge. The link is the Pull Request | | 🟣 | The agent's working on it | | 🟡 | Done and checked, but not committed yet. You commit it, or tell the agent to | | 🟠 | Waiting on another ticket or Pull Request first | | 🔴 | Blocked, or you need to do something. It says what | | ⚪ | Not started |
A line looks like this:
🟢 ACT-12 Short title: #19The ticket ID links to the ticket and the number links to the Pull Request. Only what you need to act on makes the list: no essay about what it did while you were at smoko. Full detail in Working with Agents.
📦 Third-party code
- 📦 Third-party code is exempt. Anything in
node_modules/orvendor/isn't ours. Don't lint it, don't tidy it, leave it be.
🗂️ Structure
- 🐫 Code files are camelCase. Components are PascalCase (
Button.tsx) inside a camelCase folder (button/). - 🔗 If it becomes a URL, it's kebab-case. Route folders and doc files (
background-jobs.md). CSS variables too. - 🧰 Reusable functions live in
utils/. Global, section or component level, one folder per function, with anindex.tsso imports stay tidy. - 📍 Components live where they're used. Design System Components in
components/ui/, anything used on more than one page incomponents/shared/, and one-page components in that page's owncomponents/folder. No feature folders. - 🧱 Components follow the same order every time. Imports, component, variables, state, effects, render. No inline functions in the render.
- 🔀 Server and client code live in separate files. The server one wraps the client one.
📋 Just want the files?
Fair enough. Head to the Templates page on the site, or grab them straight from static/templates/:
static/templates/
├── AGENTS.md # 🤖 Context file for AI agents
├── skills/ # 🛠️ Eight ready-made agent skills
├── docs/ # 📖 The full set of Decision Doc templates, one per standard folder
├── docsSite/ # 🌐 Docusaurus viewer that shows docs/ at /docs
├── eslint/ # 🚨 Four flavours: base, typescript, react, nextjs
├── stylelint/ # 💅 CSS and SCSS
├── prettier.config.mjs # ✨ Formatting
├── .prettierignore # 🙈 What Prettier leaves alone
├── globals.css # 🎨 Tailwind + starter colour palette
├── .editorconfig # ⌨️ Editor whitespace rules
└── .nvmrc / .envrc # 🟢 Node version switchingCopy them. Don't retype them. The ESLint ones have been run against real code, so they actually work, which is more than you can say for most configs floating around the internet.
🗺️ Finding your way around this repo
.
├── docs/ # 📝 Every page on the site, as Markdown
│ ├── Guides/
│ ├── Standards/
│ └── Structure/
├── static/
│ ├── images/ # 🖼️ Logo and favicon
│ └── templates/ # 📋 The copy-paste files
├── src/css/custom.css # 🎨 Site theme overrides
├── docusaurus.config.mjs # ⚙️ Site config
└── sidebars.mjs # 📑 Sidebar (builds itself from docs/)Built with Docusaurus. The sidebar generates itself from the folders, so there's no menu file to forget about.
✏️ Changing a standard
Reckon a rule's wrong, or there's one missing? Good. Standards that never change are standards nobody reads.
- 🌿 Branch off
main, named after the ticket (ACT-14-update-eslint-page), ortype/short-descriptionif there's no ticket (docs/update-eslint-page). - 📝 Edit or add a Markdown file in
docs/. Name it in kebab-case (naming-conventions.md, notnamingConventions.md), because the file name becomes the page's URL. Yes, we follow our own rules here. - 📋 Changing a config? Edit the file in
static/templates/and the matching page indocs/Standards/so the two don't drift apart. For an ESLint config, runpnpm check:eslint-templates: it lints each config against itself and fails if the ESLint page shows an old copy. Add--update-docsto copy the configs onto the page. - 🔢 Add a version to
docs/version-history.md: what changed, and what a project has to do about it. Bumppackage.jsonto match: the first number when most projects rework most of their code, the middle when files move, the last when only the inside of files changes. See How versions are numbered. Publish it to npm (npmjs.com) once it's merged. We use pnpm for everything, so that'spnpm publish, which lands in the same npm registry asnpm publish. Projects read only the new versions, so if it's not in there, nobody hears about it. - 🔨 Run
pnpm build. It fails on broken links, so you'll know quick smart if you've stuffed one. - 🚀 Open a pull request and say why the change makes life better.
A good rule of thumb: if you can't explain the rule to a new starter in one sentence, it's not ready.
🚧 Before this goes live
- [ ] 🖼️ Swap in the real logo.
static/images/logo.svgis a stand-in.
💚 The short version
Write code the next person can read. Test it. Keep it small. Follow the pattern.
Do that and we'll all get home on time.
