CodePress Engine
Deprecated, and optional. CodePress visual editing works on cloud previews of a plain dev server with no build plugin: the preview runtime locates elements from their DOM position, text and framework hints, and edits are applied by an agent that commits to your branch. Local-device previews still need the plugin for now. You do not need to install this package for cloud previews. If your app already uses it, nothing changes: the editor still reads the
codepress-data-fpattribute and uses it as the first hint for where an element lives. No new features are planned for the plugins.
TypeScript-powered instrumentation for the CodePress visual editor. The package ships a Babel plugin, SWC plugin, development server, and CLI so React or Next.js projects can expose file-level context to the editor.
Requirements
- Node.js 18.17.0 or newer (Fastify v5 + diagnostics channel support)
- npm 8+ (or any compatible package manager)
- Git available on the host machine (repository & branch detection)
Automated tests run under Node 16 and skip Fastify-specific assertions when the runtime lacks the required APIs. For production usage we strongly recommend Node 18+.
Installation
npm install @codepress/codepress-engine
Next.js usage
// next.config.mjs
import { createSWCPlugin } from "@codepress/codepress-engine/swc";
import CodePressWebpackPlugin from "@codepress/codepress-engine/webpack-plugin";
const nextConfig = {
// SWC plugin for code transformation (existing)
experimental: {
swcPlugins: [createSWCPlugin()],
},
// Webpack plugin for production module mapping (new)
webpack: (config, { isServer, dev }) => {
config.plugins.push(new CodePressWebpackPlugin({ isServer, dev }));
return config;
},
};
export default nextConfig;
How it works
The plugin:
- Automatically skips server builds (
isServer: true) and dev builds (dev: true) - Runs during webpack compilation for production client builds
- Builds a mapping:
{ 33: "react", 92: "react-dom", ... } - Injects
window.__CP_MODULE_MAP__into the main bundle - Enables O(1) module resolution instead of scanning all modules
Bundle size impact
- Typical app (1000 modules): +3-4KB gzipped
- Large app (3000 modules): +8-10KB gzipped
When to use
- Required: Production builds where you need HMR to work
- Optional: Development (already has named module IDs)
- Alternative: Set
moduleIds: 'named'in webpack config (larger bundle, exposes file structure)
Note: When using ESM (next.config.mjs), prefer the named import above due to CJS interop. For CommonJS configs you can use:
// next.config.cjs
const { createSWCPlugin } = require("@codepress/codepress-engine/swc");
The SWC plugin auto-detects your repository and branch from git and common CI env vars. WASM selection is automatic based on your Next.js / @swc/core version; see the WASM exports below for manual overrides.
Optional options for createSWCPlugin (all are optional; omit to use auto-detection):
| Option | Type | Default | Purpose |
|---|---|---|---|
repo_name | string | auto-detected from git remote | Force repository id in owner/repo form |
branch_name | string | auto-detected from env/git | Force branch name |
Babel plugin usage
// babel.config.mjs
export default {
plugins: ["@codepress/codepress-engine"],
};
Each JSX element receives a codepress-data-fp attribute whose value encodes the relative path and start/end line numbers. On the first root container (html, body, or div), the plugin also injects repository and branch metadata.
Optional options for the Babel plugin (all are optional; omit to use auto-detection):
| Option | Type | Default | Purpose |
|---|---|---|---|
repo_name | string | auto-detected from git remote | Force repository id in owner/repo form |
branch_name | string | auto-detected from env/git | Force branch name |
Entry points exposed by the package:
| Export | Description |
|---|---|
@codepress/codepress-engine/babel | Compiled Babel plugin (CommonJS) |
@codepress/codepress-engine/swc | SWC plugin factory & WASM helpers |
@codepress/codepress-engine/webpack-plugin | Webpack plugin for production module map |
@codepress/codepress-engine/server | Fastify development server factory |
@codepress/codepress-engine/cli | CLI used by the codepress binary |
Project layout
| Path | Details |
|---|---|
src/ | TypeScript sources for the Babel plugin, CLI, dev server, and utils |
dist/ | Compiled JavaScript + declaration files (npm run build) |
babel/ | Lightweight proxy that re-exports the compiled Babel plugin |
swc/ | Versioned WASM binaries for the Next.js 14, 15.5+ within 15.x, and 16.3 SWC host ABIs, plus the plugin entry |
tests/, test/ | Jest suites covering Babel, SWC, and server helpers |
Build & test workflow
# Install dependencies
npm install
# Compile TypeScript into dist/
npm run build
# Run Jest (ts-jest powered)
npm test
The build step must run before publishing or linking locally because Babel and CLI entry points load from dist/. Jest automatically performs type-checking and skips Fastify integration tests when the runtime does not support diagnostics channels.
Local development
Run the local CodePress server alongside your app to visually edit code on disk (no GitHub commits):
# npm
npx codepress && npm start
# pnpm
pnpm dlx codepress && pnpm start
# yarn
yarn dlx codepress && yarn start
Useful commands:
# Show available commands
npx codepress help
# Launch the server explicitly on port 4321
npx codepress server
# Scaffold .env entries required by the server
npx codepress setup
Environment variables (from .env when present):
| Variable | Default | Purpose |
|---|---|---|
CODEPRESS_DEV_PORT | 4321 | Fastify listen port |
CODEPRESS_BACKEND_HOST | localhost | CodePress backend hostname |
CODEPRESS_BACKEND_PORT | 8007 | Backend REST port |
CODEPRESS_API_TOKEN | unset | API token used for authenticated proxy calls |
The server performs git-aware writes and enriches responses with repository metadata. It writes changes to your local filesystem and is not used in production builds.
Publishing a built site as a CodePress App
codepress publish publishes a directory you have already built (it does not run your build) as a CodePress App:
codepress publish ./dist --org <org> --app <app> [--publish] [--message "..."] [--no-wait]
--organd--apptake a UUID or a slug.--publishalso releases the deployed files as the App's public website.--message/-msets the commit message.--no-waitprints the deployment id after finalize and exits 0 without waiting for the job. If the deployment had already ended without succeeding, for example expired during a long upload, it reports that and exits 1.
The command walks the directory and hashes every file. It then begins a deployment with a manifest of {path, sha256, size}, and uploads only the files the organization does not already hold, eight at a time, straight to storage. Finally it finalizes the deployment and prints each stage and its progress until the deployment finishes.
Exit codes. The command exits 0 when the deployment succeeds. It exits 1 when the deployment fails, is interrupted or expires, printing the error class and message, for example branch_moved: .... It also exits 1 when the API refuses a request, printing the typed reason, for example deployment_in_progress or deployment_unsupported_delivery_mode. The second one is for an organization that reviews generated Apps through pull requests; those organizations keep publishing from an agent session.
Reruns. Running the same directory again is cheap. Files the organization already holds are not uploaded. An identical manifest attaches to the deployment that is still open. Shortly after a success, it returns that deployment as deduped and does no new work. If an upload URL expires, the command re-mints it once and retries that file once.
What gets published. The directory is walked the way an agent's commit_app walks a build output. Every regular file is included, dotfiles too, and index.html must be at the root. A symlink or other special file is refused, so copy the asset in as a regular file. The server enforces the App limits: 512 files, 20 MiB per file and 50 MiB in total.
Status commands:
codepress deployments <app> --org <org> [--limit N] # recent deployments, newest first
codepress deployment <deployment-id> --org <org> --app <app>
| Variable | Default | Purpose |
|---|---|---|
CODEPRESS_TOKEN | required | Credential, sent as Authorization: Bearer |
CODEPRESS_API_URL | https://api.codepress.dev | API origin (with or without /v1) |
CODEPRESS_DEPLOY_POLL_INTERVAL_MS | 2000 | How often the command polls the deployment while it runs |
Getting a token
The deployment API accepts a CodePress login token, the same session token the web app and CodePress Terminal use, or a platform API key (see CI / long-lived keys below). You can get a login token in either of these ways:
- From CodePress Terminal. Signed-in Terminal keeps it as
webAuthTokenin~/.codepress-terminal/settings.json. - From an email and password account. Call
POST /v1/auth/jwt/loginwith{"email", "password"}and takeaccess_tokenfrom the response.
A login token lasts 14 days. When it is close to expiring, the API returns a refreshed one in the X-New-Token header. The command uses that refreshed token for the rest of the run and prints a reminder, but it cannot update your environment, so replace CODEPRESS_TOKEN before the old one expires.
CI / long-lived keys. The command never inspects the token; it only sends it as a Bearer credential. For CI, use a CodePress platform API key (cpk_..., created under Settings > Integrations > Platform MCP) with both the apps:write scope (begin and finalize) and the apps:read scope (status and list). A 403 names the scope the key is missing. The slug lookups accept only a login token, so with a key the command asks for the organization and App UUIDs: pass UUIDs to --org and --app.
Migrating from commit-code + publish scripts
Scripts that read every file into one POST /v1/app-code/organizations/{org}/apps/{app}/commit-code request and then call POST /v1/websites/{app}/publish hold a request open for minutes on a large site. Replace both calls with:
CODEPRESS_TOKEN=... codepress publish ./dist --org <org> --app <app> --publish
--publish takes over from the separate website publish call, so you no longer read the generation and artifact SHA first. Nothing is sent inline: each file is uploaded once, and an unchanged file is never uploaded again. Any timeout you raised for the old commit request can go, because no request stays open while the server commits. The old routes keep working while you migrate.
SWC package exports and WASM selection
| Export | Target |
|---|---|
./swc | ./dist/swc/index.js |
./swc/wasm | ./swc/codepress_engine.v42.wasm |
./swc/wasm-v42 | ./swc/codepress_engine.v42.wasm |
./swc/wasm-turbopack | ./swc/codepress_engine.turbopack.wasm |
./swc/wasm-v73 | ./swc/codepress_engine.v73.wasm |
./swc/wasm-turbopack-v73 | ./swc/codepress_engine.turbopack-v73.wasm |
./swc/wasm-v26 | ./swc/codepress_engine.v26.wasm |
./swc/wasm-v0_82_87 | ./swc/codepress_engine.v0_82_87.wasm |
The helper automatically selects the correct WASM binary based on the detected Next.js / @swc/core version. Next.js 15.5 and later 15.x releases use the swc_core 42 exports; Next.js 16.3.x uses the swc_core 73 exports, with a dedicated Turbopack artifact in each family. Unsupported Next.js 16 minors fail with an actionable compatibility error instead of loading an ABI-mismatched binary. Override detection with CODEPRESS_SWC_WASM=<package specifier> or CODEPRESS_SWC_ABI_BAND=<v42|turbopack|v73|turbopack-v73|v26|v0_82_87> after verifying the selected artifact against the host compiler.
Feature comparison
| Capability | Babel plugin | SWC plugin |
|---|---|---|
| Git-aware attributes | ✅ | ✅ |
| Encoded path security | XOR + base64 | XOR + base64 |
| Line number tracking | ✅ start–end range | ✅ (optional) |
| Performance | Baseline | 20–70× faster |
| Output medium | String literal attribute | [wasmSpecifier, config] array |
Additional references
INSTALL.md– linking the package locally & publishing guidanceMODULE_MAP_INTEGRATION.md– detailed guide for webpack plugin integration and troubleshootingscripts/build-swc.mjs– rebuild the WASM binaries (requires Rust toolchain)tests/– examples of mocking git, fetch, and file IO when validating the plugin
Contributing
PRs are welcome. Please ensure:
npm run buildnpm test
are both green before submitting. Mention in the PR description if Fastify integration tests were skipped due to running on Node < 18.
CodePress Engine is released under the MIT license (see LICENSE).