Skip to content

Latest commit

 

History

History
112 lines (87 loc) · 4.87 KB

File metadata and controls

112 lines (87 loc) · 4.87 KB

Contributing to evjs

Internal guide for developing the evjs monorepo.

Project Identity

  • Name: evjs (fullstack framework), @evjs/* (package scope)
  • Repository: evaijs/evjs
  • CLI command: ev (binary from @evjs/cli)
  • Linter: Biome (npx biome check --write)
  • Node: ESM-only ("type": "module" in all packages)

Package Map

Package Path Purpose
@evjs/cli packages/cli CLI binary (ev dev, ev build)
@evjs/ev packages/ev Config, plugin, and bundler types (defineConfig)
@evjs/create-app packages/create-app Project scaffolding (npx @evjs/create-app)
@evjs/shared packages/shared Runtime shared: errors, HTTP utils, constants
@evjs/client packages/client Client (React + TanStack)
@evjs/server packages/server Server (Hono)
@evjs/build-tools packages/build-tools Bundler-agnostic server function transforms (SWC)
@evjs/manifest packages/manifest Shared manifest schema types (ManifestV1)
@evjs/bundler-utoopack packages/bundler-utoopack Utoopack adapter (default)

Dependency Graph

@evjs/cli ──► @evjs/ev, @evjs/bundler-utoopack (default)
@evjs/bundler-utoopack ──► @evjs/ev, @evjs/build-tools, @evjs/manifest, @utoo/pack
@evjs/ev ──► @evjs/manifest, @evjs/shared

@evjs/shared (zero deps — runtime only)
@evjs/client ──► @evjs/shared, @tanstack/react-router, @tanstack/react-query
@evjs/server ──► @evjs/shared, hono, @hono/node-server

Coding Rules

  1. Imports: All imports at top of file. Use import type for type-only imports.
  2. Linting: Biome — no any, no import * as unless necessary.
  3. No manual server entries: The framework generates server entry dynamically.
  4. No manual bundler configs: Use ev.config.ts or convention-based defaults.
  5. Server function files: Must start with "use server";. We recommend the .server.ts suffix or placing them in src/api/.
  6. Server function exports: Must be named async function exports (no default exports).
  7. Module type: All packages are ESM ("type": "module"). Use .js extensions in relative imports within compiled output.
  8. Config file: Named ev.config.ts (not evjs.config.ts).
  9. Dependency resolution: CLI uses createRequire(import.meta.url) for reliable loader resolution.

Common Tasks

Add a new server function

  1. Create src/api/[name].server.ts
  2. Add "use server"; at the top
  3. Export named async functions
  4. Import and use in client with useQuery(fn) or useMutation(fn)

Add a new route

  1. Create a new file under src/pages/ (e.g. src/pages/about.tsx)
  2. Define route with createRoute({ getParentRoute, path, component }) and export it
  3. Import in src/main.tsx and add to route tree via parentRoute.addChildren([newRoute])

Add a new example

  1. Create directory under examples/
  2. Add package.json with "@evjs/ev": "*" and "@evjs/cli": "*" as devDeps, "private": true
  3. Add src/main.tsx + index.html
  4. Create symlink in packages/create-app/templates/../../../examples/[name]
  5. Add to packages/create-app/scripts/restore-templates.js symlink map
  6. Add an e2e test in e2e/cases/[name].ts

Release a new version

  1. Create a GitHub Release with a tag like v0.1.0
  2. The release workflow automatically syncs the version to all packages and publishes to npm
  3. Do NOT bump versions locally — the codebase keeps "*" for internal @evjs/* deps.

Monorepo Commands

npm run build              # Build all packages + examples
npm run test               # Unit tests (vitest)
npm run test:e2e           # E2E tests (playwright)
npm run dev                # Dev mode (turborepo)
npx biome check --write    # Fix lint/format

Build System Internals

ev build Flow

  1. loadConfig(cwd) — loads ev.config.ts or returns undefined for convention-based defaults
  2. Resolves the BundlerAdapter — utoopack (the only bundler)
  3. Calls BundlerAdapter.build() which drives the compilation
  4. The bundler adapter:
    • Discovers "use server" files
    • Applies SWC transforms (client + server variants)
    • Builds the server bundle
    • Emits dist/server/manifest.json and dist/client/manifest.json

ev dev Flow

  1. Same config resolution as ev build
  2. Calls BundlerAdapter.dev() which starts the dev server with HMR
  3. The adapter signals onServerBundleReady after server bundle is built
  4. The CLI core auto-starts the API server via @evjs/server/node
  5. Sets up proxy: /api/*localhost:3001

Agent Skills

The skills/ directory contains user-facing guides for building apps with evjs. If you change CLI commands, config options, or runtime APIs, please update the relevant skills.

Available skill references: init, dev, build, routing, server-fns, server-routes, config