Novus Technologies Novus Technologies design kit v0.9.0

Adopt the kit with an AI coding agent

Most teams meet this kit through a coding agent. Told only to "use the Novus kit", an agent guesses, and a portal ends up with its own side navigation, its own filter bar and its own idea of what blue means. This page gives the agent the same rules the kit enforces on itself, and gives you prompts to copy.

Rules are context, not enforcement. An agent can still get it wrong, so the last step of every prompt is a check you can read. The kit's own release gates remain the thing that actually blocks a mistake.

1. Give your agent the rules once

The package ships an instruction file for each agent, in the format that agent reads. Copy the one you use into your repository and your agent follows these rules in every session, without anyone restating them. Upgrading the package brings the updated rules with it.

AgentCopy this fileTo here
Claude Codenovus-design-kit/agents/claude/CLAUDE.mdCLAUDE.md
Claude Code reads CLAUDE.md at the project root, or .claude/CLAUDE.md. It also reads AGENTS.md when no CLAUDE.md is present, so use one or the other rather than both.
GitHub Copilotnovus-design-kit/agents/copilot/copilot-instructions.md.github/copilot-instructions.md
Applies to every request in the repository.
GitHub Copilot, console screensnovus-design-kit/agents/copilot/novus-design-kit.instructions.md.github/instructions/novus-design-kit.instructions.md
Path-scoped. The applyTo glob limits the console rules to interface files.
Cursornovus-design-kit/agents/cursor/novus-design-kit.mdc.cursor/rules/novus-design-kit.mdc
Must keep the .mdc extension: a plain .md file in .cursor/rules is ignored.
Any AGENTS.md readernovus-design-kit/agents/AGENTS.mdAGENTS.md
The cross-tool convention, read by Codex, Windsurf, Zed, Jules and others.

The files are generated from one source in the kit, so they cannot disagree with each other or with this page. Do not hand edit them: upgrade the package instead, and keep your own project rules in a separate file.

2. Work in this order

  1. Install and wire in. The package installs from public npm with no registry setup and no token. The theme script belongs in the document head so the theme applies before first paint.
  2. Convert one screen, not all of them. A single converted screen shows you what the agent understood, while a whole application converted at once is unreviewable.
  3. Read what came back. Check the screen at 1440px and at 375px, and with JavaScript off if the screen is meant to work without it.
  4. Then widen. Once one screen is right, the same prompt scales to the rest, and the instruction file keeps later sessions consistent.

3. Prompts to copy

Each prompt names the real files this release ships, so the agent has no reason to invent a path. Paste one as it is.

Adopt the kit in an application that already exists
Adopt the novus-design-kit design kit in this project.

1. Install it from public npm: npm install novus-design-kit
2. Wire it in. Each file has its own place:
   - novus-design-kit/tokens.css: import once at the application root, before your own styles.
   - novus-design-kit/console.css: import after tokens.css, on console and portal screens only.
   - novus-design-kit/js/novus-theme.js: load in the document head, so the theme applies before first paint.
   - novus-design-kit/js/novus-console.js: load at the end of the body. It enhances behaviour; every pattern still works when it does not run.
   - novus-design-kit/icons/novus-icons.svg: the icon sprite, referenced from markup. Serve it over http, because a browser blocks an external sprite from a file:// page.
   The markup for each pattern is in the catalog, not in the package: https://ui-kit.novustech.dev/components/overview.html
3. Convert exactly one screen to the kit, and stop there so I can review it.
4. Tell me which values in that screen had no token, if any.

Follow these rules while you work:
- Take every colour, size, spacing, radius and shadow from a token in tokens.css. If you are about to type a hex colour or a pixel value, there is a var(--...) for it.
- Surfaces are flat and monochrome: no gradients, and colour carries meaning rather than decoration.
- Use a component from the kit's catalog before writing new markup. The package ships the stylesheet, not the markup, so read the pattern's structure in the catalog at https://ui-kit.novustech.dev/components/overview.html rather than guessing it from class names.
- Short content stays on one line. Identifiers, names, chips, dates, amounts, buttons and column headers never wrap to two or three rows, and a table scrolls inside its own card instead of squeezing its columns.
- Do not cap portal text at a reading measure, and do not narrow descriptive text with a margin: a paragraph, a help line or any other descriptive copy spans the full width of its container, with inline margins of zero if any were going to be set. Only text deliberately marked as prose with the measure class takes a reading cap.
- Light is the default theme. Dark comes only from a choice the person made, which persists. Do not follow the operating system unless the app opts in explicitly.
- Header, navigation and body text render at one size. Headings step up by their documented ratio, and never further.
- Every control a person can press measures at least 44px at the 375px baseline, icon-only controls included. A control may look smaller if it carries an expanded hit area that still reaches 44px. Desktop density is a separate decision, so this floor is the phone baseline rather than every width.
- Motion is functional and lasts 0.2s or less, and it is removed under prefers-reduced-motion. The one exception is the slow ambient art on the sign-in panel, which also stops under reduced motion.
- Patterns keep working when JavaScript does not run. Menus, drawers, filter sheets and tabs are built on native elements first, with script only as an enhancement.
- Write plain copy. No em dashes anywhere in published text, and no marketing category jargon for the product. Add descriptive text only when it was asked for: no invented helper line, hint, explanation or tooltip filling a space the instruction left open. If a control needs no explanation, ship it without one.
- When generating a component, add no white space just to make a layout look symmetric: no empty element balancing one side against the other, no padding on one column to match its neighbour. Balance comes from the grid or flex rules the pattern already sets. Every other gap is deliberate too, coming from a spacing token or a container that carries it (.row spaces its children, .field pairs its label and control).
- A field's default edit mode is a real label above the control, the .field pattern. A placeholder is a hint that disappears once someone types, so it never stands in for the label, and an input ships with no placeholder-only field. Keep the placeholder for format examples, like name@novustech.com.sg.
- A field the person cannot edit carries no padlock icon. Say it with the control itself: readonly on an input the person may focus and copy from, disabled on one they cannot, and a .field__help line naming why it is locked, like Set by your administrator. The state stays legible from the styling the control already has, so no new icon joins the label.

Do not restyle anything outside the screen you convert, and do not edit files
inside node_modules.
Then check: the app still builds and runs; no hex colour or pixel value was introduced where a token exists; one screen is converted, not all of them.
Convert a hand-built admin screen to the console patterns
Rebuild this screen on the novus-design-kit console patterns.

Load novus-design-kit/console.css after novus-design-kit/tokens.css, then rebuild the
screen from the shipped patterns rather than the markup that is there now:
the console shell, the grouped side navigation, the page header with its
breadcrumb and end-aligned actions, the filter bar with its sub-filter sheet and
quick chips, and the list footer with its count and page controls.

Rules that apply everywhere:
- Take every colour, size, spacing, radius and shadow from a token in tokens.css. If you are about to type a hex colour or a pixel value, there is a var(--...) for it.
- Surfaces are flat and monochrome: no gradients, and colour carries meaning rather than decoration.
- Use a component from the kit's catalog before writing new markup. The package ships the stylesheet, not the markup, so read the pattern's structure in the catalog at https://ui-kit.novustech.dev/components/overview.html rather than guessing it from class names.
- Short content stays on one line. Identifiers, names, chips, dates, amounts, buttons and column headers never wrap to two or three rows, and a table scrolls inside its own card instead of squeezing its columns.
- Do not cap portal text at a reading measure, and do not narrow descriptive text with a margin: a paragraph, a help line or any other descriptive copy spans the full width of its container, with inline margins of zero if any were going to be set. Only text deliberately marked as prose with the measure class takes a reading cap.
- Light is the default theme. Dark comes only from a choice the person made, which persists. Do not follow the operating system unless the app opts in explicitly.
- Header, navigation and body text render at one size. Headings step up by their documented ratio, and never further.
- Every control a person can press measures at least 44px at the 375px baseline, icon-only controls included. A control may look smaller if it carries an expanded hit area that still reaches 44px. Desktop density is a separate decision, so this floor is the phone baseline rather than every width.
- Motion is functional and lasts 0.2s or less, and it is removed under prefers-reduced-motion. The one exception is the slow ambient art on the sign-in panel, which also stops under reduced motion.
- Patterns keep working when JavaScript does not run. Menus, drawers, filter sheets and tabs are built on native elements first, with script only as an enhancement.
- Write plain copy. No em dashes anywhere in published text, and no marketing category jargon for the product. Add descriptive text only when it was asked for: no invented helper line, hint, explanation or tooltip filling a space the instruction left open. If a control needs no explanation, ship it without one.
- When generating a component, add no white space just to make a layout look symmetric: no empty element balancing one side against the other, no padding on one column to match its neighbour. Balance comes from the grid or flex rules the pattern already sets. Every other gap is deliberate too, coming from a spacing token or a container that carries it (.row spaces its children, .field pairs its label and control).
- A field's default edit mode is a real label above the control, the .field pattern. A placeholder is a hint that disappears once someone types, so it never stands in for the label, and an input ships with no placeholder-only field. Keep the placeholder for format examples, like name@novustech.com.sg.
- A field the person cannot edit carries no padlock icon. Say it with the control itself: readonly on an input the person may focus and copy from, disabled on one they cannot, and a .field__help line naming why it is locked, like Set by your administrator. The state stays legible from the styling the control already has, so no new icon joins the label.

Rules for console and portal screens:
- Build console screens on the shipped shell: a header carrying the product lockup and an account menu, a grouped side navigation with line icons, and a page header with a breadcrumb and end-aligned actions.
- Pick one of the kit's two console shells rather than inventing a third. The grouped side navigation is the default and suits a console with many or deep top-level areas. The top-navigation bar suits a console with a handful of sections, up to about nine, each holding a short menu. Both use the same header, the same drawer on phones, and one navigation definition.
- The account menu is the last element in a console header. Nothing sits to the right of it, at any width.
- The Novus app switcher, <novus-app-switcher>, is the first control in a console header. Nothing sits to the left of it, and it is the only grid button on the bar.
- Collapsing the side navigation leaves a rail of icons, one per destination, with the current page still marked and each icon carrying its name for assistive technology. Never hide the navigation.
- Sign-in sits on the near-white ground with the ambient line art on the brand panel, single sign-on beside the password form, and no theme toggle on the page.
- A menu, popover or tooltip belonging to a table row renders outside the table's scroll wrap, not inside it. The wrap clips what it contains, so anything that needs to overflow the table has to live beyond it.
- Lists use the filter bar with its sub-filter sheet, active chips and quick chips with counts, and they end with the list footer: a count, page controls, and rows per page.
- Charts read their colours and fonts from the tokens at render time, redraw when the theme changes, and are accompanied by the same numbers as a table so a page without scripting still answers the question.
- Every amount carries its currency and a thousands separator, and the separator is a comma: 1,250,000.00 LKR, 1,250,000.00 USD, 1,250,000.00 EUR. Never bare digits, never a space or a decimal comma where the thousands comma goes, never a rounded abbreviation standing in for a total. Within a product one currency reads one way across every screen, table, chart and export: the ISO code, LKR or USD or EUR, never a local symbol or abbreviation like Rs.
- Buttons sit in a .row, which spaces them and wraps at narrow widths; a lone button gets the same treatment, and a dialog or form foot ends the row with inline justify-content: flex-end. A button carries no margin of its own, so a button never touches another button, a field, a table or any other component, above or below it. Where the container around a row carries no spacing, give the row one.
- Two actions that answer the same moment, like Cancel and Save or Resend and Back to sign in, sit side by side in one .row, never stacked one above the other. One of the pair is .btn--primary, the next step, and the other is .btn--secondary, the fallback; never two secondaries. The secondary keeps its outline, so it still reads as a button beside the filled one. In a dialog or form foot the primary ends the row. Only a row too narrow for both may wrap.

When you are done, list anything in the original screen that has no equivalent
in the kit, instead of inventing a component for it.
Then check: the screen uses the shell, not new layout markup; the side navigation collapses to a rail of icons rather than disappearing; no identifier, chip, amount or column header wraps to a second line.
Audit an existing screen against the kit's rules
Audit this screen against the novus-design-kit rules and report what
breaks them. Change nothing.

Check each of these, and for every failure give me the file, the line, the rule
it breaks, and the smallest fix:
- Take every colour, size, spacing, radius and shadow from a token in tokens.css. If you are about to type a hex colour or a pixel value, there is a var(--...) for it.
- Surfaces are flat and monochrome: no gradients, and colour carries meaning rather than decoration.
- Use a component from the kit's catalog before writing new markup. The package ships the stylesheet, not the markup, so read the pattern's structure in the catalog at https://ui-kit.novustech.dev/components/overview.html rather than guessing it from class names.
- Short content stays on one line. Identifiers, names, chips, dates, amounts, buttons and column headers never wrap to two or three rows, and a table scrolls inside its own card instead of squeezing its columns.
- Do not cap portal text at a reading measure, and do not narrow descriptive text with a margin: a paragraph, a help line or any other descriptive copy spans the full width of its container, with inline margins of zero if any were going to be set. Only text deliberately marked as prose with the measure class takes a reading cap.
- Light is the default theme. Dark comes only from a choice the person made, which persists. Do not follow the operating system unless the app opts in explicitly.
- Header, navigation and body text render at one size. Headings step up by their documented ratio, and never further.
- Every control a person can press measures at least 44px at the 375px baseline, icon-only controls included. A control may look smaller if it carries an expanded hit area that still reaches 44px. Desktop density is a separate decision, so this floor is the phone baseline rather than every width.
- Motion is functional and lasts 0.2s or less, and it is removed under prefers-reduced-motion. The one exception is the slow ambient art on the sign-in panel, which also stops under reduced motion.
- Patterns keep working when JavaScript does not run. Menus, drawers, filter sheets and tabs are built on native elements first, with script only as an enhancement.
- Write plain copy. No em dashes anywhere in published text, and no marketing category jargon for the product. Add descriptive text only when it was asked for: no invented helper line, hint, explanation or tooltip filling a space the instruction left open. If a control needs no explanation, ship it without one.
- When generating a component, add no white space just to make a layout look symmetric: no empty element balancing one side against the other, no padding on one column to match its neighbour. Balance comes from the grid or flex rules the pattern already sets. Every other gap is deliberate too, coming from a spacing token or a container that carries it (.row spaces its children, .field pairs its label and control).
- A field's default edit mode is a real label above the control, the .field pattern. A placeholder is a hint that disappears once someone types, so it never stands in for the label, and an input ships with no placeholder-only field. Keep the placeholder for format examples, like name@novustech.com.sg.
- A field the person cannot edit carries no padlock icon. Say it with the control itself: readonly on an input the person may focus and copy from, disabled on one they cannot, and a .field__help line naming why it is locked, like Set by your administrator. The state stays legible from the styling the control already has, so no new icon joins the label.

If the screen is a console or portal screen, also check:
- Build console screens on the shipped shell: a header carrying the product lockup and an account menu, a grouped side navigation with line icons, and a page header with a breadcrumb and end-aligned actions.
- Pick one of the kit's two console shells rather than inventing a third. The grouped side navigation is the default and suits a console with many or deep top-level areas. The top-navigation bar suits a console with a handful of sections, up to about nine, each holding a short menu. Both use the same header, the same drawer on phones, and one navigation definition.
- The account menu is the last element in a console header. Nothing sits to the right of it, at any width.
- The Novus app switcher, <novus-app-switcher>, is the first control in a console header. Nothing sits to the left of it, and it is the only grid button on the bar.
- Collapsing the side navigation leaves a rail of icons, one per destination, with the current page still marked and each icon carrying its name for assistive technology. Never hide the navigation.
- Sign-in sits on the near-white ground with the ambient line art on the brand panel, single sign-on beside the password form, and no theme toggle on the page.
- A menu, popover or tooltip belonging to a table row renders outside the table's scroll wrap, not inside it. The wrap clips what it contains, so anything that needs to overflow the table has to live beyond it.
- Lists use the filter bar with its sub-filter sheet, active chips and quick chips with counts, and they end with the list footer: a count, page controls, and rows per page.
- Charts read their colours and fonts from the tokens at render time, redraw when the theme changes, and are accompanied by the same numbers as a table so a page without scripting still answers the question.
- Every amount carries its currency and a thousands separator, and the separator is a comma: 1,250,000.00 LKR, 1,250,000.00 USD, 1,250,000.00 EUR. Never bare digits, never a space or a decimal comma where the thousands comma goes, never a rounded abbreviation standing in for a total. Within a product one currency reads one way across every screen, table, chart and export: the ISO code, LKR or USD or EUR, never a local symbol or abbreviation like Rs.
- Buttons sit in a .row, which spaces them and wraps at narrow widths; a lone button gets the same treatment, and a dialog or form foot ends the row with inline justify-content: flex-end. A button carries no margin of its own, so a button never touches another button, a field, a table or any other component, above or below it. Where the container around a row carries no spacing, give the row one.
- Two actions that answer the same moment, like Cancel and Save or Resend and Back to sign in, sit side by side in one .row, never stacked one above the other. One of the pair is .btn--primary, the next step, and the other is .btn--secondary, the fallback; never two secondaries. The secondary keeps its outline, so it still reads as a button beside the filled one. In a dialog or form foot the primary ends the row. Only a row too narrow for both may wrap.

Check the rendered result at 1440px and at 375px, not just the source. Report
findings in severity order, worst first, and say plainly if you found nothing.
Then check: findings name a file and a line; each finding names the rule it breaks; nothing was changed, only reported.

The rules themselves

This is what the instruction files contain, and what the prompts carry. Each rule says what breaks without it and where the kit checks it, so an agent can weigh a rule rather than following it blindly.

Rules that always apply

Rules for console and portal screens

These apply to admin consoles, dashboards and portals. They do not apply to a marketing page, which is why the path-scoped formats limit them.

Check a screen the way the kit checks itself

The rules tell an agent to confirm a screen at 1440px and at 375px. That is only fair if the check is available, so the kit ships the same audit it runs on its own pages. Point it at a built directory:

node node_modules/novus-design-kit/scripts/layout-audit.mjs --target dist

It renders every page at both widths in headless Chromium and reports short content that wrapped, pages that scroll sideways on a phone, controls under the 44px floor, and the console rules for headers, navigation and sign-in. It needs playwright-core and a Chromium; without them it says so and exits rather than pretending to pass.

An agent that cannot render a page should say that plainly instead of reporting a check it did not run.

If the result looks wrong