A small Fastify + Shiki microservice that
renders code into static, themed HTML. The WordPress plugin in ../nodecode-plugin
calls this service when a post is saved, caches the HTML, and serves it with zero JS on
the frontend.
Licensed under the Apache License, Version 2.0 (see LICENSE).
- Node.js 18+
- Runs on the same machine as WordPress and binds to
127.0.0.1by default.
cd nodecode-service
cp .env.example .env # edit NODECODE_API_KEY etc.
npm install
npm run build
npm start # or: npm run dev (watch mode)Verify it is up:
curl http://127.0.0.1:9527/healthAll config is via environment variables (or a .env file). See .env.example:
| Variable | Default | Description |
|---|---|---|
NODECODE_HOST |
127.0.0.1 |
Bind address. Keep on localhost. |
NODECODE_PORT |
9527 |
Port. |
NODECODE_API_KEY |
(empty) | Shared secret; must match the plugin setting. |
NODECODE_LIGHT_THEME |
github-light |
Light theme name. |
NODECODE_DARK_THEME |
github-dark |
Dark theme name. |
NODECODE_EXTRA_LANGS |
(empty) | Extra languages to preload, comma separated. |
NODECODE_MAX_CODE_LENGTH |
200000 |
Max characters accepted per code block. |
Production env template for systemd: deploy/nodecode.env.example.
Returns { "status": "ok", "loaded": <number> }. No auth required.
Returns the list of currently loaded language ids. Requires X-Api-Key if a key is set.
Request body:
{
"code": "console.log('hi')",
"lang": "javascript",
"title": "example.js",
"showLineNumbers": true,
"wrap": false
}Response: { "html": "<pre class=\"shiki nodecode-pre ...\">...</pre>", "lang": "javascript" }.
Token colors are emitted as --nodecode-light / --nodecode-dark CSS variables
(defaultColor: false), so the plugin's stylesheet drives the active theme.
Body { "blocks": [ { code, lang, ... }, ... ] }, response { "results": [ { html, lang } | { error } ] }.
Used by the plugin to render all blocks of a post in a single round-trip.
Full step-by-step guide (Node.js install, /etc/nodecode.env, boot persistence, WordPress
plugin, troubleshooting):
Production deployment (Ubuntu + systemd)
Quick install:
sudo cp deploy/nodecode.env.example /etc/nodecode.env
# edit /etc/nodecode.env — set NODECODE_API_KEY, chmod 600
sudo cp deploy/nodecode-service.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now nodecode-service
curl http://127.0.0.1:9527/healthUse systemctl enable so the service starts after server reboots.
Not the default for this project. If you use PM2, you must pass NODECODE_* variables
yourself (the bundled ecosystem.config.cjs only sets NODE_ENV):
npm install -g pm2
npm run build
# export NODECODE_API_KEY=... and other vars, or extend ecosystem.config.cjs env
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup # follow the printed instructions for boot persistence- Bind to
127.0.0.1so only the local WordPress can reach it. - Set a long random
NODECODE_API_KEYand configure the same value in the plugin. - If you must run it on a separate host, put it behind TLS and treat the API key as required.