Skip to main content

Engineering conventions

These are the standing rules for working in the ContentsVision repo. They live in full in the repo's CLAUDE.md; this page summarizes them so the whole team shares the same expectations. They apply to everyone, including AI assistants working in the codebase.

Run the tests after every change

The hard rule, repeated because it matters: run ./run_tests.sh after any change, and keep it green before considering the work done. A change with no test is incomplete. Show real failing output; never claim green when it is red. Full detail in testing.

Writing style: no em dashes

Never use em dashes anywhere: UI copy, code comments, commit messages, chat. Use a period, comma, colon, or parentheses instead. (This handbook follows the same rule.)

Frontend UI conventions

Use the existing design system in frontend/src/app/globals.css rather than hand-rolling Tailwind for common controls. Skim globals.css first, and add a new component class there rather than inlining styles.

ElementUseNot
Inputs.as-input (or .as-input-sm)raw <input className="border ...">
Selectsthe shared <StyledSelect> componenta native <select> (breaks the visual language)
Buttons.btn-primary / .btn-secondary / .btn-danger (+ .btn-sm, .press)ad-hoc button styles
Surfaces.card, .stat-cardbespoke panels
Labels.filter-label, .col-header, .eyebrowone-off label styles

.as-select exists only as a legacy fallback and should be migrated to StyledSelect.

Motion

Every user action should have a subtle animation; stillness reads as broken. Anything that mounts, unmounts, expands, collapses, or moves must animate in and out.

  • Use Framer Motion for conditionally rendered elements: wrap in <AnimatePresence> and give explicit initial, animate, and exit. Do not use a bare {cond && <div/>} for visible elements (the exit will not animate).
  • The CSS keyframe utilities (.animate-slide-down, .animate-fade-in, etc.) only animate the enter side; use them for things that mount once and stay.
  • Keep durations short (120-220ms). Use Material standard easing [0.4, 0, 0.2, 1] for panel/height transitions and easeOut for fades and pops.
  • Add .press to clickable elements for tactile feedback.
  • Re-key a list's container on sort/filter/pagination changes so rows re-mount and re-trigger their enter animation.

Add new keyframes under the "Motion primitives" section of globals.css, not as ad-hoc inline @keyframes.

Help Center articles

The in-app Help Center (distinct from this handbook) has its own house style:

  • Short, verb-first headings; one task per heading; terse steps and bullets.
  • Every article starts from the home Dashboard and tells the reader how to navigate to where the article begins.
  • Concise to the point that removing one more word would break the sentence.
  • Use many screenshots, one under each step a reader might get stuck on.
  • Explain every feature in the flow; if it is not explained, it does not exist to the user.
  • When the reader might have more questions, point them to [email protected].

Handoff prompts

Never save a handoff prompt or "paste this into the next session" text to a file. Put it directly in the chat reply, inside a single fenced code block, so it can be copied. Do not split it across sections or create files for it.

Why these exist

The conventions keep the product coherent: one visual language, motion that signals state, copy in one voice, and a test suite that stays trustworthy. They also let any contributor (or any AI session) pick up work without re-litigating style. When in doubt, match the surrounding code's idiom, comment density, and naming.