Conventions & AI Workflow
WebJs is an AI-first framework. It ships an opinionated conventions system that both humans and AI agents follow. The conventions are enforced via config files, CLI commands, and guardrails that ensure consistent, high-quality code across the entire project, whether written by a person or an agent.
Where the conventions live
The project conventions ship as prose in the cross-agent skill, .agents/skills/webjs/SKILL.md (a routing skill), plus the git, test, and review workflow rules in .agents/rules/workflow.md. There is no separate CONVENTIONS.md file. All AI agents read the skill and AGENTS.md before writing code. The conventions define:
- Module architecture: where actions, queries, and components go.
- Testing rules: when unit vs E2E tests are required.
- Component patterns: light DOM by default with Tailwind, shadow DOM opt-in,
Class.register('tag'), and the class-prefix rule for light-DOM custom CSS. - Styling convention: a static compiled Tailwind stylesheet (
css:build) +@themetokens, JS helpers inlib/utils/ui.tsto dedupe repeated class bundles, no@apply. - Server action patterns: one function per file,
ActionResultenvelope. - Code style: TypeScript extensions, const/let preferences, async/await patterns.
How to Override Architectural Conventions
The conventions are prose, so you customize them by editing the skill (.agents/skills/webjs/SKILL.md) or the workflow rules (.agents/rules/workflow.md) to match your team's preferences. For example, if you prefer shadow DOM components by default (the scaffold defaults to light DOM + Tailwind), state that in the component-patterns section:
# Component patterns - Opt in to shadow DOM (static shadow = true) for every component - Author styles via static styles = css`...` - Always call register()
AI agents read the skill and AGENTS.md before every task and follow them. Together they are the source of truth for project conventions: how code is organized, named, and tested. These are preferences you can change, so they are guidance, not a hard gate.
webjs check: correctness, not conventions
The webjs check command is a separate tool from the conventions. It runs only correctness checks: rules that catch objectively broken code, such as a browser global in render() that crashes SSR, a non-public process.env read that leaks a secret, a reactive prop that silently breaks reactivity, a server-only .server.ts import reaching a page that ships to the browser (a runtime crash the elision verdict lets the check catch statically), a 'use server' file that exports no callable action (so a client import resolves to nothing and the call 404s), or non-erasable TypeScript that fails the type-strip. Every rule always runs.
The dividing line
One test decides where something belongs: could a sensible app legitimately want this to pass? If yes, it is a convention (it lives in the skill and AGENTS.md as guidance). If no, it is a check (it lives in webjs check and always runs). That is why checks are not overridable, they catch real breakage, and conventions are not enforced by a tool, they are judgment.
# Validate the project (correctness only) webjs check # List the correctness checks and their descriptions webjs check --rules
Workflow for AI agents
- Read the skill (
.agents/skills/webjs/SKILL.md) andAGENTS.mdfor the project conventions and follow them by judgment. - Run
webjs checkand fix every violation: they are correctness bugs, not style. - To change a convention, edit the prose in the skill or
.agents/rules/workflow.md. There is nopackage.jsonswitch and nothing to toggle. - Run
webjs checkbefore every commit. AI agents run it automatically as part of their workflow.
webjs test
WebJs ships a testing setup based on node:test and WTR + Playwright.
Unit Tests
# Run all unit tests
webjs test
# Test files live in test/unit/*.test.{ts,js}
Unit tests use node:test and node:assert/strict. Test server actions (via direct import), component rendering (via renderToString), and utility functions:
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { html } from '@webjsdev/core';
import { renderToString } from '@webjsdev/core/server';
test('renders heading', async () => {
const result = await renderToString(html`<h1>Hello</h1>`);
assert.ok(result.includes('Hello'));
});
test('action validates input', async () => {
const result = await createPost({ title: '', body: '' });
assert.equal(result.success, false);
assert.equal(result.status, 400);
});
E2E Tests
# Run unit + E2E tests
webjs test --e2e
# Test files live in test/browser/*.test.{ts,js}
E2E tests use WTR + Playwright to launch a real browser and test complete user flows: navigation, form submission, auth, and live interactions.
Convention: Always Write Tests
When implementing any feature, tests are mandatory:
- Unit tests for server actions, queries, and component rendering.
- E2E tests for user-facing features (navigation, forms, auth flows).
Tests-per-feature is a project convention (guidance), not a webjs check rule.
AI Agent Guardrails
WebJs enforces disciplined AI workflows through config files and hooks. These guardrails apply to all agents: Claude, Cursor, Copilot, Antigravity, and others.
Branch Checking
AI agents must never commit directly to main or master. Before any edit, the agent checks what branch it is on:
- If on
main: stop immediately and create a feature branch. - If on a feature branch: verify it matches the current task.
- Before starting work: sync with the parent branch (
git fetch origin && git rebase origin/main).
The Claude Code hook (.claude/hooks/guard-branch-context.sh) enforces this programmatically by intercepting Edit/Write calls when on main.
Merge Approval
Agents never merge without explicit user permission. Before any merge, the agent asks:
Ready to merge <branch> into <target>? After merging, should <branch> be deleted or kept?
The agent waits for approval before proceeding.
Automatic Tests & Docs
Every code change includes the following, automatically, without the user asking:
- Tests: unit tests for logic, E2E tests for user-facing behavior.
- Documentation: updates to
AGENTS.mdfor API changes, the skill (.agents/skills/webjs/SKILL.md) for convention changes, anddocs/for user-facing features. - Convention validation:
webjs checkruns and violations are fixed.
The user should never have to say "also write tests" or "also update the docs." That is the default behavior in a WebJs project.
Agent Config Files
When you scaffold a project with webjs create, it generates config files for every major AI coding agent:
| File | Agent | Purpose |
|---|---|---|
AGENTS.md | All agents (Cursor, opencode, Antigravity, Copilot coding agent read it natively) | Framework API, conventions, recipes (the source of truth) |
.agents/skills/webjs/SKILL.md | All agents | The shipped routing skill carrying the framework context and project conventions (guidance, customizable in the prose) |
.agents/rules/workflow.md | All agents | Git, test, and review workflow rules |
CLAUDE.md | Claude Code | Thin bridge pointing at AGENTS.md |
GEMINI.md | Gemini CLI | Thin bridge pointing at AGENTS.md |
.claude/settings.json | Claude Code | PreToolUse hook guarding git merge/push to main |
.github/copilot-instructions.md | Copilot in VS Code | Thin bridge pointing at AGENTS.md |
.github/pull_request_template.md | All (via GitHub) | PR checklist: tests, docs, convention check |
.editorconfig | All editors | Consistent indent/encoding/line endings |
All config files encode the same rules: the framework conventions, git workflow, and quality expectations. Each is formatted for its target agent's native config format.
Autonomous Mode
When an agent runs in sandbox or bypass-permissions mode, it follows these defaults instead of asking questions:
| Decision | Autonomous Default |
|---|---|
On main, need a branch | Auto-create feature/<task-slug> |
| Parent branch has new commits | Auto-rebase before starting |
| Ready to merge | Auto-merge (no prompt) |
| Delete branch after merge? | Delete feature/fix branches, keep long-lived branches |
| Commit message | Auto-generate meaningful message |
| Tests failing | Fix them, don't ask |
| Convention violations | Fix them, don't ask |
The principle: in autonomous mode, the agent is more disciplined, not less. It follows every rule but makes decisions instead of blocking on questions.
webjs create
The scaffolding command generates a complete project with all conventions, config files, and example tests pre-configured:
npm i -g webjsdev webjs create my-app cd my-app && npm run dev
This generates:
app/with root layout + pagemodules/skeleton for feature-scoped codecomponents/with a theme toggle componentdb/schema.server.ts: the Drizzle schema, SQLite by default, exampleUsermodel.db/connection.server.tsexports thedbconnection.test/unit/andtest/browser/with example tests.agents/skills/webjs/SKILL.md: the shipped routing skill with the framework context and editable project conventions.agents/rules/workflow.md: git, test, and review workflow rulesAGENTS.md: full framework API reference- Thin bridges pointing at AGENTS.md (
CLAUDE.md,GEMINI.md,.github/copilot-instructions.md) .editorconfigfor consistent formattingpackage.jsonwith scripts (dev,build,start,test,check,db:migrate,db:generate,db:studio)
Every file is ready to use immediately. The project works out of the box with webjs dev, and every AI agent that opens the project will automatically read the config files and follow the conventions.
The Complete Workflow
When a user tells an AI agent "add a contact page" in a WebJs project, the agent automatically delivers:
app/contact/page.ts # the page modules/contact/actions/send-message.server.ts # the server action modules/contact/types.ts # type definitions test/unit/contact.test.ts # unit test for the action test/browser/contact.test.ts # E2E test for the form flow AGENTS.md # updated if new API/conventions docs/app/docs/contact/page.ts # doc page (if docs/ exists)
Plus: a git commit with a meaningful message, passing tests, and valid conventions. The user never has to ask for tests, docs, or a commit. That is the default behavior.
Next Steps
- Getting Started: quick start guide
- Architecture: app layout, modules, and file conventions
- Testing: detailed testing guide