Skip to content

feat: add preview command - #1082

Open
btea wants to merge 5 commits into
nodejs:mainfrom
btea:feat/add-preview-script
Open

btea wants to merge 5 commits into
nodejs:mainfrom
btea:feat/add-preview-script

Conversation

@btea

@btea btea commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Description

Add a unified startup preview script to facilitate quick previewing and verification of changes on the page after modifying the code logic.

Validation

Related Issues

Check List

  • I have read the Contributing Guidelines and made commit messages that follow the guideline.
  • I have run node --run test and all tests passed.
  • I have check code formatting with node --run format:check & node --run lint.
  • I've covered new added functionality with unit tests if necessary.

@btea
btea requested a review from a team as a code owner September 4, 2026 05:07
@vercel

vercel Bot commented Sep 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
api-docs-tooling Ready Ready Preview Oct 28, 2026 1:28am UTC

Request Review

@codecov

codecov Bot commented Sep 4, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 58.55856% with 138 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.18%. Comparing base (560c042) to head (6fdc776).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
packages/cli/bin/commands/preview.mjs 0.00% 84 Missing ⚠️
packages/cli/bin/commands/generate.mjs 0.00% 37 Missing ⚠️
packages/cli/src/serve.mjs 87.90% 15 Missing ⚠️
packages/cli/bin/commands/index.mjs 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1082      +/-   ##
==========================================
- Coverage   93.44%   93.18%   -0.27%     
==========================================
  Files         278      281       +3     
  Lines       27815    28127     +312     
  Branches     2789     2813      +24     
==========================================
+ Hits        25993    26211     +218     
- Misses       1800     1894      +94     
  Partials       22       22              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

api-links Generator

Performance estimate (single CI run)

  • Generation time: 47.7% slower (650.00 ms → 960.00 ms)
  • Peak memory: 1.7% higher (302.18 MB → 307.35 MB)

json Generator

Performance estimate (single CI run)

  • Generation time: 21.5% faster (7.48 s → 5.87 s)
  • Peak memory: 4.6% lower (1.21 GB → 1.15 GB)

legacy-html Generator

Performance estimate (single CI run)

  • Generation time: 6.7% faster (14.67 s → 13.68 s)
  • Peak memory: 1.6% lower (1.84 GB → 1.81 GB)

legacy-json Generator

Performance estimate (single CI run)

  • Generation time: 51.2% slower (5.82 s → 8.80 s)
  • Peak memory: 2.7% lower (1.26 GB → 1.23 GB)

llms-txt Generator

Performance estimate (single CI run)

  • Generation time: 30.6% faster (7.57 s → 5.25 s)
  • Peak memory: 1.8% higher (1.14 GB → 1.16 GB)

orama-db Generator

Output size: 1 file changed · net -1.00 B

File size details
File Main PR Change
orama-db.json 29.15 MB 29.15 MB -1.00 B (-0.0%)

Performance estimate (single CI run)

  • Generation time: 58.8% slower (5.65 s → 8.97 s)
  • Peak memory: 2.5% lower (1.33 GB → 1.30 GB)

web Generator

Output size: 136 files changed · net -105.83 KB

File size details
File Main PR Change
assets/style-p1XZsxjB.css 138.55 KB — -138.55 KB (-100.0%)
assets/style-oesv8pX0.css — 138.33 KB +138.33 KB
assets/SearchBox-DjNnuz7W.js 84.67 KB — -84.67 KB (-100.0%)
assets/SearchBox-DTgvswXx.js — 84.66 KB +84.66 KB
all.html 34.70 MB 34.65 MB -47.94 KB (-0.1%)
assets/dist-DruvUqXN.js 30.42 KB — -30.42 KB (-100.0%)
assets/dist-DdRW6U-0.js — 30.42 KB +30.42 KB
assets/SideBar-DaKBoTPQ.js 25.62 KB — -25.62 KB (-100.0%)
assets/SideBar-B0UOYazc.js — 25.61 KB +25.61 KB
assets/client-CN48fyBn.js — 25.08 KB +25.08 KB
assets/client-DxC3O6Ca.js 24.91 KB — -24.91 KB (-100.0%)
assets/Combination-d5oRXla-.js 16.11 KB — -16.11 KB (-100.0%)
assets/Combination-CF9SP3Ox.js — 16.11 KB +16.11 KB
assets/ThemeToggle-DpnhQLP6.js — 13.69 KB +13.69 KB
assets/ThemeToggle-DVZdvZ7l.js 13.65 KB — -13.65 KB (-100.0%)
assets/dist-DVEbYasF.js 10.20 KB — -10.20 KB (-100.0%)
assets/dist-C4cOGgJI.js — 10.20 KB +10.20 KB
assets/Layout-C5yPmBoc.js 10.13 KB — -10.13 KB (-100.0%)
assets/compat-ByVaDh64.js 10.13 KB — -10.13 KB (-100.0%)
assets/compat-CRpDNe6I.js — 10.13 KB +10.13 KB
assets/Layout-Baelj3Rz.js — 10.13 KB +10.13 KB
assets/Tooltip-C41LEB8U.js 7.93 KB — -7.93 KB (-100.0%)
assets/Tooltip-BihYWOgD.js — 7.93 KB +7.93 KB
assets/dist-DNbUuC3x.js 6.99 KB — -6.99 KB (-100.0%)
assets/dist--JetRd52.js — 6.99 KB +6.99 KB
assets/jsx-runtime-CW012A50.js 5.67 KB — -5.67 KB (-100.0%)
assets/jsx-runtime-C0TYVyIX.js — 5.67 KB +5.67 KB
assets/dist-cDFsq_2f.js 3.93 KB — -3.93 KB (-100.0%)
assets/dist-DUFvaFVR.js — 3.93 KB +3.93 KB
assets/CodeTabs-DT17uorw.js 3.89 KB — -3.89 KB (-100.0%)
assets/CodeTabs-CVoR5u6O.js — 3.89 KB +3.89 KB
fs.html 2.32 MB 2.32 MB -3.76 KB (-0.2%)
assets/CodeBox-BNILFdqT.js 3.44 KB — -3.44 KB (-100.0%)
assets/CodeBox-DY__QP-Y.js — 3.44 KB +3.44 KB
assets/hooks.module-BbOQEtt2.js 3.40 KB — -3.40 KB (-100.0%)
assets/hooks.module-Bi5KVIws.js — 3.40 KB +3.40 KB
quic.html 987.77 KB 985.17 KB -2.60 KB (-0.3%)
crypto.html 2.04 MB 2.04 MB -2.44 KB (-0.1%)
assets/FunctionSignature-BQoQjJ6P.js 2.28 KB — -2.28 KB (-100.0%)
assets/FunctionSignature-i_hL4Go6.js — 2.28 KB +2.28 KB
http.html 1.23 MB 1.23 MB -2.21 KB (-0.2%)
deprecations.html 609.02 KB 606.82 KB -2.21 KB (-0.4%)
assets/Banner-Zf4myBWm.js 2.13 KB — -2.13 KB (-100.0%)
assets/Banner-C8jSOz62.js — 2.13 KB +2.13 KB
cli.html 675.86 KB 673.88 KB -1.98 KB (-0.3%)
buffer.html 1.82 MB 1.82 MB -1.95 KB (-0.1%)
http2.html 1.31 MB 1.31 MB -1.91 KB (-0.1%)
zlib.html 998.52 KB 996.72 KB -1.80 KB (-0.2%)
webcrypto.html 681.72 KB 679.92 KB -1.80 KB (-0.3%)
assets/ChangeHistory-C3DUcRCX.js 1.77 KB — -1.77 KB (-100.0%)
assets/ChangeHistory-Bmrp4p_7.js — 1.77 KB +1.77 KB
process.html 1.20 MB 1.19 MB -1.69 KB (-0.1%)
perf_hooks.html 912.49 KB 910.85 KB -1.64 KB (-0.2%)
stream.html 1.27 MB 1.27 MB -1.41 KB (-0.1%)
net.html 670.90 KB 669.50 KB -1.40 KB (-0.2%)
util.html 1.27 MB 1.26 MB -1.39 KB (-0.1%)
test.html 1.44 MB 1.44 MB -1.33 KB (-0.1%)
n-api.html 1.05 MB 1.05 MB -1.28 KB (-0.1%)
errors.html 570.94 KB 569.72 KB -1.22 KB (-0.2%)
globals.html 303.02 KB 301.86 KB -1.16 KB (-0.4%)
webstreams.html 566.50 KB 565.36 KB -1.13 KB (-0.2%)
events.html 869.10 KB 868.12 KB -1004.00 B (-0.1%)
worker_threads.html 663.11 KB 662.16 KB -977.00 B (-0.1%)
tls.html 549.71 KB 548.75 KB -976.00 B (-0.2%)
assets/DataTag-CTUSGgLj.js 856.00 B — -856.00 B (-100.0%)
sqlite.html 543.81 KB 542.98 KB -851.00 B (-0.2%)
assets/DataTag-DRIfqmpN.js — 844.00 B +844.00 B
assets/DocumentationIndex-D_jFywVL.js 833.00 B — -833.00 B (-100.0%)
assets/DocumentationIndex-DHETdn97.js — 833.00 B +833.00 B
v8.html 575.25 KB 574.47 KB -789.00 B (-0.1%)
dns.html 442.76 KB 442.01 KB -765.00 B (-0.2%)
diagnostics_channel.html 554.16 KB 553.44 KB -739.00 B (-0.1%)
assert.html 673.69 KB 673.00 KB -714.00 B (-0.1%)
child_process.html 699.34 KB 698.64 KB -710.00 B (-0.1%)
stream_iter.html 795.87 KB 795.19 KB -696.00 B (-0.1%)
url.html 534.56 KB 533.89 KB -690.00 B (-0.1%)
vm.html 657.44 KB 656.77 KB -688.00 B (-0.1%)
readline.html 381.45 KB 380.82 KB -644.00 B (-0.2%)
dtls.html 316.25 KB 315.63 KB -631.00 B (-0.2%)
assets/ArrowUpRightIcon-BSpTwAaB.js 618.00 B — -618.00 B (-100.0%)
assets/ArrowUpRightIcon-DKje7Eu2.js — 618.00 B +618.00 B
assets/Badge-CZF-RiB7.js 616.00 B — -616.00 B (-100.0%)
assets/Badge-Dm2qTRYc.js — 607.00 B +607.00 B
assets/AlertBox-BNnsWt2b.js 591.00 B — -591.00 B (-100.0%)
assets/AlertBox-C9F09zDJ.js — 591.00 B +591.00 B
dgram.html 314.05 KB 313.49 KB -574.00 B (-0.2%)
module.html 530.78 KB 530.22 KB -571.00 B (-0.1%)
cluster.html 318.27 KB 317.74 KB -545.00 B (-0.2%)
assets/CodeBracketIcon-TvXI-m3T.js 512.00 B — -512.00 B (-100.0%)
assets/CodeBracketIcon-WqbRSzug.js — 512.00 B +512.00 B
inspector.html 225.65 KB 225.17 KB -498.00 B (-0.2%)
assets/dist-D1kGHM6c.js 477.00 B — -477.00 B (-100.0%)
assets/dist-69KlTVXP.js — 477.00 B +477.00 B
assets/ChevronDownIcon-BOnMJQ3A.js 468.00 B — -468.00 B (-100.0%)
assets/ChevronDownIcon-DCzxoxn4.js — 468.00 B +468.00 B
assets/renderLabel-CdEZo9LC.js 447.00 B — -447.00 B (-100.0%)
assets/renderLabel-CilEyGdH.js — 447.00 B +447.00 B
timers.html 192.67 KB 192.25 KB -431.00 B (-0.2%)
console.html 194.58 KB 194.17 KB -427.00 B (-0.2%)
async_context.html 330.35 KB 329.94 KB -420.00 B (-0.1%)
os.html 173.79 KB 173.40 KB -408.00 B (-0.2%)
https.html 250.52 KB 250.13 KB -398.00 B (-0.2%)
modules.html 238.40 KB 238.01 KB -396.00 B (-0.2%)
bench.html 213.82 KB 213.44 KB -386.00 B (-0.2%)
vfs.html 213.93 KB 213.55 KB -384.00 B (-0.2%)
ffi.html 204.00 KB 203.64 KB -371.00 B (-0.2%)
tty.html 114.10 KB 113.74 KB -367.00 B (-0.3%)
esm.html 196.41 KB 196.06 KB -362.00 B (-0.2%)
path.html 186.51 KB 186.18 KB -344.00 B (-0.2%)
repl.html 314.32 KB 314.00 KB -331.00 B (-0.1%)
packages.html 229.71 KB 229.39 KB -320.00 B (-0.1%)
async_hooks.html 293.41 KB 293.14 KB -278.00 B (-0.1%)
wasi.html 84.21 KB 83.98 KB -241.00 B (-0.3%)
punycode.html 68.48 KB 68.25 KB -234.00 B (-0.3%)
tracing.html 131.22 KB 130.99 KB -234.00 B (-0.2%)
single-executable-applications.html 166.12 KB 165.90 KB -226.00 B (-0.1%)
querystring.html 70.41 KB 70.20 KB -220.00 B (-0.3%)
domain.html 131.41 KB 131.21 KB -208.00 B (-0.2%)
string_decoder.html 69.13 KB 68.93 KB -196.00 B (-0.3%)
debugger.html 148.42 KB 148.24 KB -189.00 B (-0.1%)
report.html 238.26 KB 238.07 KB -187.00 B (-0.1%)
typescript.html 52.81 KB 52.64 KB -175.00 B (-0.3%)
addons.html 389.90 KB 389.73 KB -170.00 B (-0.0%)
assets/Blockquote-C7yOM0SI.js 167.00 B — -167.00 B (-100.0%)
assets/Blockquote-DX5chJYP.js — 167.00 B +167.00 B
permissions.html 94.13 KB 93.97 KB -166.00 B (-0.2%)
embedding.html 73.14 KB 72.98 KB -163.00 B (-0.2%)
documentation.html 30.02 KB 29.87 KB -157.00 B (-0.5%)
environment_variables.html 39.57 KB 39.42 KB -155.00 B (-0.4%)
assets/useRemoteConfig-DRPTLZY3.js 151.00 B — -151.00 B (-100.0%)
index.html 28.06 KB 27.91 KB -151.00 B (-0.5%)
intl.html 58.89 KB 58.74 KB -151.00 B (-0.3%)
assets/useRemoteConfig-CRXuIucx.js — 151.00 B +151.00 B
404.html 22.80 KB 22.66 KB -144.00 B (-0.6%)
assets/withIsland-C7ctRfG5.js 105.00 B — -105.00 B (-100.0%)
assets/withIsland-BSYDIejr.js — 105.00 B +105.00 B

Performance estimate (single CI run)

  • Generation time: 42.3% faster (24.88 s → 14.36 s)
  • Peak memory: 1.1% higher (2.04 GB → 2.06 GB)

Comment thread scripts/preview.mjs Outdated

@bmuenzenmeyer bmuenzenmeyer left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've come around to this after observing a mentee interact with this repository. There is a lot of intimidating work to get all this to work together, and for the unfamiliar, it's a lot.

Comment thread scripts/preview.mjs Outdated

@ovflowd ovflowd left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO our dev command/preview command should still follow/support doc-kit args (Supplying input folder, supplying generators... It shouldn't be locked for Node.js it should be agnostic) since we want to make a generic preview/dev command for doc-kit itself instead of bounding it to Node.js

So our dev/preview command IMO shouldn't be scripts (scripts) but be commands part of doc-kit CLI

(We should avoid using 3rd party NPM packages, http:serve is enough)

@btea

btea commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

Makes sense — a generic preview command in the doc-kit CLI beats a Node.js-bound script. Before I rework the PR, two quick questions:

  1. Should doc-kit preview take the same options as generate (-i,-t, -o, ...) plus --port, building before serving? Or just serve an existing output directory and leave building to generate?
  2. Is dev (watch mode) in scope here, or a follow-up? I'd prefer a follow-up to keep this PR small.

Either way: serving via node:http, no new dependencies, and I'll drop scripts/preview.mjs.

@bmuenzenmeyer

Copy link
Copy Markdown
Contributor

my opinions

  • Should doc-kit preview take the same options as generate (-i,-t, -o, ...) plus --port, building before serving? Or just serve an existing output directory and leave building to generate?

I like the idea of it attempting to build at the presence of any flag besides --port - that gives flexibility in both cases.

  • Is dev (watch mode) in scope here, or a follow-up? I'd prefer a follow-up to keep this PR small.

follow up

@btea btea changed the title feat: add preview:docs & preview:node scripts feat: add preview command Oct 26, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: make it clear on docs that this is NOT production grade and meant to be used for testing.

Comment thread packages/cli/bin/commands/preview.mjs Outdated
const server = await serve(output, { port: opts.port });

logger.info(
`Serving ${output} at http://localhost:${server.address().port}/ ` +

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We should be able to also pass the host parameter so you can serve on localhost, 0.0.0.0 or whatever you want IMO

Comment thread packages/cli/bin/commands/preview.mjs Outdated

const { runGenerators } = createGenerator();

const DEFAULT_OUTPUT = './out';

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this already defined somewhere? I feel that this command can't really run without an output flag being passed... Is it correct to assume the default should be "out" and if that's the case, then our generator command also should have a default out, no?

cc @avivkeller ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be defined as a default in config

@avivkeller

Copy link
Copy Markdown
Member

Will review today!

Comment on lines +6 to +28
const MIME_TYPES = {
'.avif': 'image/avif',
'.css': 'text/css; charset=utf-8',
'.gif': 'image/gif',
'.html': 'text/html; charset=utf-8',
'.ico': 'image/x-icon',
'.jpeg': 'image/jpeg',
'.jpg': 'image/jpeg',
'.js': 'text/javascript; charset=utf-8',
'.json': 'application/json',
'.map': 'application/json',
'.md': 'text/markdown; charset=utf-8',
'.mjs': 'text/javascript; charset=utf-8',
'.png': 'image/png',
'.svg': 'image/svg+xml',
'.txt': 'text/plain; charset=utf-8',
'.wasm': 'application/wasm',
'.webmanifest': 'application/manifest+json',
'.webp': 'image/webp',
'.woff': 'font/woff',
'.woff2': 'font/woff2',
'.xml': 'application/xml',
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use a dependancy for this? Fine if not, just makes our life easier (sorry if I'm missing context on this)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should we add a dependency for a simple list of mime types? That said, what is this list of mime types even for? what we serve in the server? I think 2/3rd of this aren't even served by doc-kit and can be removed from this list.

Comment on lines +82 to +88
// Requests must not escape the served directory
if (filePath !== root && !filePath.startsWith(root + sep)) {
response.writeHead(403);
response.end('Forbidden');

return;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Requests must not escape the served directory
if (filePath !== root && !filePath.startsWith(root + sep)) {
response.writeHead(403);
response.end('Forbidden');
return;
}
// Requests must not escape the served directory
// Note: This is not intended to be a secure server, and
// this is a best-effort implementation of a secure file-
// serving.
if (filePath !== root && !filePath.startsWith(root + sep)) {
response.writeHead(403);
response.end('Forbidden');
return;
}

@avivkeller avivkeller left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comments, then LGTM

This branch was successfully deployed

1 active deployment
Preview – api-docs-tooling — 6fdc7768 Deployed Oct 28, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants