This guide covers the development workflow, conventions, and tooling for contributing to Renderify.
- Node.js >= 22.0.0
- pnpm >= 10.29.3
The preinstall script enforces pnpm usage. Running npm install or yarn install will error.
git clone https://github.com/unadlib/renderify.git
cd renderify
pnpm installrenderify/
├── packages/
│ ├── ir/ # @renderify/ir — Intermediate representation
│ ├── runtime/ # @renderify/runtime — Execution engine
│ ├── security/ # @renderify/security — Security policies
│ ├── mcp-app/ # @renderify/mcp-app — Offline MCP Apps adapter
│ ├── core/ # @renderify/core — Orchestration facade
│ ├── llm/ # @renderify/llm — LLM providers
│ ├── renderify/ # renderify — Official SDK facade
│ └── cli/ # @renderify/cli — CLI and playground
├── tests/ # Unit, integration, e2e, and benchmark tests
├── examples/ # Browser and runtime examples
├── scripts/ # Build and CI helper scripts
└── docs/ # Documentation
# Install dependencies
pnpm install
# Start development mode (tsup watch)
pnpm dev
# Start the playground
pnpm playground
# Type checking
pnpm typecheck
# Linting (biome)
pnpm lint
# Auto-format
pnpm format
# Unit tests
pnpm unit
# Compatibility tests (JSPM module resolution)
pnpm compat
# End-to-end tests (Playwright-based)
pnpm e2e
# Benchmarks
pnpm bench
# All quality gates (typecheck + unit)
pnpm test
# Full test suite (typecheck + unit + e2e)
pnpm test:all
# Build all packages
pnpm build
# Validate package metadata
pnpm validate
# Clean build artifacts
pnpm cleanThe dependency graph must be respected when making changes:
ir (no internal deps)
↑
security (depends on ir)
↑
runtime (depends on ir, security)
↑
core (depends on ir, security, runtime)
↑
llm (depends on core, ir)
↑
renderify (depends on core, ir, llm, runtime, security)
mcp-app (depends on ir, security, runtime, official MCP Apps SDK)
cli (depends on core, ir, llm, security, runtime)
Changes to @renderify/ir may affect all packages. Changes to renderify and @renderify/cli typically affect nothing downstream.
Changes to the MCP App plan surface, CSP, bridge lifecycle, or tool allowlist must update the feature spec and threat model and pass the official-bridge Chromium test without skipped cases.
The monorepo uses Turborepo for task orchestration with caching. Task dependencies are defined in turbo.json:
builddepends on all packages being validunitdepends ontypechecke2edepends onbuild(no caching)benchdepends ontypecheck(no caching)
tsup manages package builds:
- Generates CommonJS and ESM outputs for each package entrypoint
- Emits TypeScript declaration files alongside build outputs
- Supports package-local watch mode used by
pnpm dev
pnpm dev # Run tsup watch across all packages
pnpm build # Production build for all packages
pnpm validate # Check package metadata conventionsTypeScript project references are used for incremental compilation:
tsconfig.base.json— shared compiler optionstsconfig.build.json— references all package tsconfigstsconfig.tests.json— test-specific configuration- Each package has its own
tsconfig.json
Biome handles both linting and formatting:
pnpm lint # Check for lint issues
pnpm format # Auto-format all files
pnpm format:check # Check formatting without writingConfiguration is in biome.jsonc.
Husky runs lint-staged on pre-commit:
# Automatically runs on commit:
biome check --write --files-ignore-unknown=true --no-errors-on-unmatchedThe project uses Conventional Commits via Commitizen:
pnpm commit # Interactive commit message builderCommit types: feat, fix, docs, chore, test, refactor, perf, ci, build, style.
Tests use Node.js built-in test runner with tsx:
pnpm unitTest files are in tests/*.test.ts. Key test areas:
| File | Coverage |
|---|---|
core.test.ts |
RenderifyApp orchestration, streaming, abort |
ir.test.ts |
Node types, validation, path utilities, hashing |
runtime.test.ts |
Execution, modules, sandboxing, preflight |
security.test.ts |
Policy profiles, tag blocking, source analysis |
codegen.test.ts |
Plan generation, TSX extraction, streaming |
config.test.ts |
Environment variables, defaults |
llm.test.ts |
OpenAI, OpenAI Codex, Anthropic, Google, local providers |
ui.test.ts |
HTML rendering, XSS protection |
runtime-utils.test.ts |
Budget enforcement, template interpolation |
runtime-jspm.test.ts |
Module resolution, compatibility |
End-to-end tests use Playwright for browser testing:
pnpm e2eE2E tests cover:
- CLI commands (render-plan, probe-plan, plan)
- Playground API endpoints
- LLM provider integration (with fake servers)
- Hash deep-link loading in the browser
pnpm benchBenchmarks use tinybench and measure:
- Code generation throughput
- Plan execution performance
- Compilation speed
Results are output as Markdown tables. In CI, JSON artifacts are uploaded for tracking.
Renderify uses Changesets for versioning and publishing.
When your PR changes package behavior or API:
pnpm changesetThis creates a markdown file in .changeset/ describing the change and affected packages. CI enforces that package changes include a changeset entry.
# Apply version bumps and update changelogs
pnpm version-packages
# Publish to npm
pnpm releaseRelease automation publishes only from a valid SemVer tag such as v0.8.0.
The tag version must match packages/renderify/package.json. The release
workflow validates both values, runs formatting, lint, type, unit and
compatibility checks, then validates package metadata and built entry points
before publishing to npm with provenance.
The CI workflow (.github/workflows/ci.yml) runs on every push and PR:
- Lint — code quality checks
- Typecheck — TypeScript validation (Node 22 + 24 matrix)
- Unit tests — all test suites (Node 22 + 24 matrix)
- Compatibility tests — JSPM module resolution
- Build — package validation and build
- E2E tests — full integration tests
- Benchmarks — performance measurement with artifact upload
Concurrency is controlled per-branch to cancel in-progress runs on new pushes.
- Create the package directory in
packages/ - Add
package.jsonwith proper entry points and dependencies - Add
tsconfig.jsonreferencingtsconfig.base.json - Add the reference to
tsconfig.build.json - Run
pnpm devto link the package - Add tests in
tests/
- Keep packages focused — each package has a single responsibility
- Test thoroughly — aim for comprehensive coverage of happy paths and edge cases
- Validate security — any code that handles untrusted input must go through security checks
- Use TypeScript strictly — enable strict mode, use explicit types for public APIs
- Follow existing patterns — look at existing packages for conventions
- Document public APIs — exported types and functions should be self-documenting
- Avoid breaking changes — use changesets to communicate API changes