---
package: "@webjsdev/cli"
version: 0.1.1
date: 2026-04-22T01:07:47+05:30
commit_count: 27
---
## Features

- **webjs test, webjs check, webjs create with AI guardrails** [`6e85e5d`](https://github.com/webjsdev/webjs/commit/6e85e5d)
  - webjs test: discovers and runs unit + E2E tests
  - webjs check: validates app against 6 convention rules
  - webjs create: scaffolds opinionated project with CONVENTIONS.md,
    cross-agent configs (.cursorrules, .windsurfrules, copilot-instructions),
- **default theme to system across website, docs, blog, and scaffolder** [`7257b49`](https://github.com/webjsdev/webjs/commit/7257b49)
  Theme toggle defaults to 'system' instead of 'light'. Bootstrap scripts
  no longer force data-theme — they only set it when the user has an
  explicit localStorage preference. CSS prefers-color-scheme handles the
  default. Updated all three apps + the webjs create scaffolder template.
- **migrate client tests to WTR + Playwright, real browser testing** [`1ce3888`](https://github.com/webjsdev/webjs/commit/1ce3888)
  Added @web/test-runner + @web/test-runner-playwright + playwright.
  Client-side tests (renderer, directives, Shadow DOM) now run in real
  Chromium — no more linkedom/jsdom fake DOM. Server tests stay on
  node:test (they need Node APIs).
- **add Playwright MCP server for browser debugging** [`4c5746e`](https://github.com/webjsdev/webjs/commit/4c5746e)
  Added Microsoft's @playwright/mcp as both user-level (global) and
  project-level MCP server. End users get it via webjs create (.claude.json).
  
  Playwright MCP gives AI agents direct browser control: navigate, click,
- **git pre-commit hook blocks commits on main/master** [`ca31525`](https://github.com/webjsdev/webjs/commit/ca31525)
  Added .git/hooks/pre-commit locally and .hooks/pre-commit in the
  scaffolder template. webjs create now runs git init + configures
  core.hooksPath to .hooks/ so the hook is tracked in the repo and
  works for everyone who clones it.
- **add .env.example for scaffolder and blog example** [`9994261`](https://github.com/webjsdev/webjs/commit/9994261)
  Shows all convention-over-configuration env vars: PORT, SESSION_SECRET,
  REDIS_URL (auto-scales everything), S3_BUCKET (cloud storage),
  DATABASE_URL. Includes generation command for SESSION_SECRET.
- **NextJs-style cache + NextAuth-style auth + WebSocket broadcast** [`19418b3`](https://github.com/webjsdev/webjs/commit/19418b3)
  Removed: storage (s3/disk), background jobs — not core framework.
  
  Added:
  - cache(fn, { revalidate, tags }) + revalidateTag() — NextJs-style
- **scaffold templates (full-stack + API) and code generators** [`b8f569b`](https://github.com/webjsdev/webjs/commit/b8f569b)
  webjs create <name> --template api    Backend-only: route wrappers over
                                        typed server actions, no pages/SSR
  
  webjs generate page|module|action|query|component|route <name>
- **SaaS template — webjs create --template saas** [`1ab8ea0`](https://github.com/webjsdev/webjs/commit/1ab8ea0)
  Scaffolds a complete SaaS starter with auth, dashboard, Prisma:
  - app/login, app/signup — auth pages
  - app/dashboard with middleware auth guard + settings page
  - app/api/auth/[...path]/route.ts — auth API handlers
- **auto-scope ALL CSS selectors for light DOM components** [`bdb3280`](https://github.com/webjsdev/webjs/commit/bdb3280)
  scopeCSS() now prefixes every CSS rule with the component tag name:
    input { color: red } → comments-thread input { color: red }
    :host { display: block } → comments-thread { display: block }
- **typed component props via defineComponent + .d.ts overlay** [`9f0b09a`](https://github.com/webjsdev/webjs/commit/9f0b09a)
  The existing static-properties pattern carried no compile-time type
  information, so authors had to duplicate every field as `declare x: T`
  for editor intellisense. This adds a TypeScript overlay plus a tiny
  runtime helper so the descriptor map is the single source of truth for
- **Class.register() — drop the import.meta.url argument** [`283c2b5`](https://github.com/webjsdev/webjs/commit/283c2b5)
  Authors no longer write `Counter.register(import.meta.url)`; the call
  is just `Counter.register()`. Module URLs (used by SSR to emit
  `<link rel=modulepreload>` hints) are derived server-side at boot by
  scanning the app tree for `class X extends WebComponent { static tag =
- **adopt standard customElements.define — drop static tag + .register()** [`bb61186`](https://github.com/webjsdev/webjs/commit/bb61186)
  The web-standard registration convention (same shape Lit uses for its
  non-decorator form):
  
    class Counter extends WebComponent { ... }
- **Counter.register('my-counter') as the idiomatic registration** [`a0f1f68`](https://github.com/webjsdev/webjs/commit/a0f1f68)
  Adds a `static register(tag)` method on WebComponent. Delegates to the
  internal registry (which in turn calls customElements.define / the
  server shim), so every registration still lands in the native
  customElements map and webjs's mirror map. Authors write:
- **rename core package webjs → @webjs/core for npm publish** [`49e2d6b`](https://github.com/webjsdev/webjs/commit/49e2d6b)
  The unscoped `webjs` name is already taken on npm (webjs@0.6.1, unrelated
  project). Moving to the `@webjs` scope lets us publish `@webjs/core`,
  `@webjs/server`, and `@webjs/cli` together.
- **rescope @webjs → @webjskit (org name 'webjs' unavailable on npm)** [`316e2be`](https://github.com/webjsdev/webjs/commit/316e2be)
  The @webjs organization is not available on npm (likely reserved because
  the unscoped `webjs` package is held by an unrelated project). Switching
  to the @webjskit scope, which we own.
- **favicon for all three apps + Prisma/SQLite in every scaffold** [`e6ba242`](https://github.com/webjsdev/webjs/commit/e6ba242)
  **Favicon**
  - scripts/generate-favicon.mjs renders the header-logo artwork
    (accent-orange linear gradient, rounded square, 1px inner highlight)
    at 512×512 via puppeteer and writes favicon.svg + favicon.png into

## Fixes

- **dev mode uses node --watch for reliable file change detection** [`792cde0`](https://github.com/webjsdev/webjs/commit/792cde0)
  Root cause: Node's ESM module cache has no public invalidation API.
  When loadModule() cache-busts a page with ?t=timestamp, only the
  top-level module is re-imported. Transitive imports (server actions,
  queries, components, utils) resolve to the SAME cached URL and return
- **enforce commit-often and bypass-mode in all end-user templates** [`016d39f`](https://github.com/webjsdev/webjs/commit/016d39f)
  - guard-main-merge.sh template now respects bypass mode
  - CLAUDE.md template: commit-often is step 1 of the workflow
  - CONVENTIONS.md template: commits listed first in required checklist
  - .cursorrules, .windsurfrules, copilot-instructions: COMMIT OFTEN
- **enforce commit-AND-push in all agent instructions** [`286ce7f`](https://github.com/webjsdev/webjs/commit/286ce7f)
  Commit without push is half the job. Updated CLAUDE.md, all templates
  (CLAUDE.md, CONVENTIONS.md, .cursorrules, .windsurfrules, copilot-
  instructions.md) to say 'commit AND push' everywhere.
- **branch-context hook must ALWAYS fire, even in bypass mode** [`c7a35b5`](https://github.com/webjsdev/webjs/commit/c7a35b5)
  The bypass-mode early-exit was defeating the entire purpose of the
  branch guard. Editing on main is a safety issue — the hook should
  always prompt, regardless of mode. Merge/push guard can respect
  bypass (those are approval prompts), but branch check is a safety net.
- **merging ALWAYS requires user permission, even in bypass mode** [`a74450e`](https://github.com/webjsdev/webjs/commit/a74450e)
  Removed all 'auto-merge' language from AGENTS.md, CLAUDE.md, and every
  agent config template (.cursorrules, .windsurfrules, copilot-instructions,
  CONVENTIONS.md). Merge guard hook no longer respects bypass mode — it
  always prompts. Merging is irreversible and must never be autonomous.
- **all hooks respect bypass mode — no prompts in autonomous mode** [`24dd724`](https://github.com/webjsdev/webjs/commit/24dd724)
  Both guard-main-merge.sh and guard-branch-context.sh (local + templates)
  now respect skipDangerousModePermissionPrompt. In bypass mode: no prompts
  for edits, merges, or pushes. The agent follows best practices via
  AGENTS.md instructions, not hook interruptions.
- **clean permission model — feature branches are free, only merge asks** [`9aa740e`](https://github.com/webjsdev/webjs/commit/9aa740e)
  Hooks: on feature branches, commit/push are fully free (no prompts).
  Only merging into main prompts for approval. Bypass mode allows
  everything including merges.
- **update all end-user templates for WTR + Playwright test stack** [`06b77c7`](https://github.com/webjsdev/webjs/commit/06b77c7)
  Updated CONVENTIONS.md (browser test section, test matrix table),
  .cursorrules, .windsurfrules, copilot-instructions.md to reference
  WTR + Playwright instead of Puppeteer/E2E. Removed stale WEBJS_E2E
  references.
- **revert blog components with bare selectors to shadow DOM** [`a36400d`](https://github.com/webjsdev/webjs/commit/a36400d)
  Components with bare element selectors (input, button, ul, h2, a)
  MUST use shadow DOM — bare selectors would leak to the whole page
  in light DOM. Reverted: comments-thread, auth-forms, chat-box,
  new-post, error-card.
- **remove auto-scope CSS hack, clean shadow/light DOM convention** [`f91ceb0`](https://github.com/webjsdev/webjs/commit/f91ceb0)
  Shadow DOM = scoped styles (static styles = css, adoptedStyleSheets).
  Light DOM = global styles (Tailwind, global CSS, no static styles).
  Pick one. Don't fake shadow DOM scoping with regex.
