npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@whfzgyx/ojo-local-canvas-server

v0.1.3

Published

Local OJO Canvas HTTP server for Codex and workspace-driven canvas previews.

Readme

@whfzgyx/ojo-local-canvas-server

Local OJO Canvas HTTP server for workspace-driven Canvas previews.

This package serves the Canvas frontend, exposes the minimal local /api/server/v1 contracts, watches workspace source changes, builds prototype output, publishes resources into a local data store, and emits local-events / local-version updates for the Canvas frontend.

Install

npm install @whfzgyx/ojo-local-canvas-server

CLI

The server serves multiple workspaces from one process. Directory names are project ids:

ojo-local-canvas-server \
  --workspaces-root /absolute/path/to/ojo-workspaces

Then open:

http://127.0.0.1:8787/p/<project-id>?mode=codex

Opening /p/<project-id> also works; the server redirects to the mode=codex URL required by the Canvas frontend.

Supported flags map to the existing env vars:

--host                  LOCAL_CANVAS_HOST
--port                  LOCAL_CANVAS_PORT
--workspaces-root       LOCAL_CANVAS_WORKSPACES_ROOT
--canvas-dist           LOCAL_CANVAS_CANVAS_DIST
--data-root             LOCAL_CANVAS_DATA_ROOT
--watch                 LOCAL_CANVAS_WATCH
--build-on-start        LOCAL_CANVAS_BUILD_ON_START

The legacy env-only launch style remains supported.

Node API

import {
  loadConfig,
  startLocalCanvasServer,
  type LocalCanvasConfig,
} from '@whfzgyx/ojo-local-canvas-server';

const config: LocalCanvasConfig = loadConfig({
  ...process.env,
  LOCAL_CANVAS_WORKSPACES_ROOT: '/absolute/path/to/workspaces',
  LOCAL_CANVAS_DATA_ROOT: '/absolute/path/to/.local-canvas-data',
});

const server = await startLocalCanvasServer(config);
console.log(server.url);

await server.close();

Exports:

  • createLocalCanvasServer(config?)
  • startLocalCanvasServer(config?)
  • loadConfig(env?)
  • validateConfig(config)
  • LocalCanvasConfig

HTTP Surface

Each project runtime is initialized lazily from LOCAL_CANVAS_WORKSPACES_ROOT/<projectId>.

Key routes:

  • GET /p/:projectId?mode=codex
  • GET /health
  • GET /__ojo_canvas_server/health
  • GET /__ojo_canvas_server/projects
  • GET /__ojo_canvas_server/projects/:projectId/status
  • POST /__ojo_canvas_server/projects/:projectId/reload
  • POST /__ojo_canvas_server/projects/:projectId/stop
  • GET /api/server/v1/projects/:projectId
  • GET /api/server/v1/projects/:projectId/draft
  • PUT /api/server/v1/projects/:projectId/draft
  • GET /api/server/v1/projects/:projectId/prototypes
  • GET /api/server/v1/projects/:projectId/state-page-revision
  • POST /api/server/v1/projects/:projectId/state-page-revision
  • POST /api/server/v1/projects/:projectId/state-page-revision:generate
  • GET /api/server/v1/projects/:projectId/local-version
  • GET /api/server/v1/projects/:projectId/local-events
  • GET /api/server/v1/projects/:projectId/prototype-dist/:manifestKey/:distPath
  • POST /api/server/v1/resources/batch-get-meta
  • GET /api/server/v1/local-resources?key=...

canvasDist

By default the npm package serves the bundled Canvas frontend from:

dist/canvas-dist

The bundled dist is pruned for local Codex canvas usage. It keeps the assets needed by /p/:projectId?mode=codex and excludes large public assets for unrelated dashboard, landing page, inspire, subscribe, and creation option routes.

canvasDist is still available as an override for local Canvas frontend development, usually:

irise-web-canvas-frontend/apps/canvas/dist

Use --canvas-dist or LOCAL_CANVAS_CANVAS_DIST only when you intentionally want a different Canvas frontend build than the one bundled in this package.

Build And Refresh Behavior

The package owns:

  • HTTP server
  • workspace watcher
  • install/build/publish pipeline
  • resource store
  • project state store
  • local-events
  • local-version
  • prototype-dist serving

When builds succeed, the server updates local project state and emits refresh events consumed by the Canvas frontend. When builds fail, it writes build_status=failed and preserves the previous usable canvas state so the iframe is not refreshed into a broken version.

Ignored watcher paths include generated output such as prototype/dist/**, plus .git/**, node_modules/**, and .local-canvas-data/**. Source changes should go through paths such as prototype/src/**, components/**, prototype config files, package manifests, or lockfiles.

Boundary With ojo-codex-plugin-better

This package is the reusable Canvas Server capability.

It should not contain:

  • Codex MCP gateway
  • Codex in-app widget resource
  • plugin-scoped singleton supervisor
  • Codex plugin manifest
  • multi-task plugin lifecycle management

ojo-codex-plugin-better should depend on this package, start it through the Node API or CLI, and keep singleton process coordination in the plugin layer.

Next Architecture Step

ProjectRuntimeRegistry / ProjectRuntime live in this package. Plugin-specific MCP/widget/supervisor logic should remain in ojo-codex-plugin-better.

Local Development

npm install
npm run typecheck
npm test
npm run pack:dry-run
npm pack

Do not publish automatically from CI or local scripts. Run npm publish --access public only after confirming package name, license, access, and release version.

Publishing Checklist

  • Confirm package name: @whfzgyx/ojo-local-canvas-server
  • Confirm npm scope access for @whfzgyx
  • Confirm license before public publish
  • Confirm bundled dist/canvas-dist is included in the package file list
  • Confirm version bump
  • Confirm npm pack --dry-run file list
  • Confirm smoke test passes from the generated .tgz