htmlship 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +10 -4
  2. package/dist/cli.js +20 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -18,15 +18,21 @@ npx htmlship list-mine
18
18
 
19
19
  ## Deploy built apps
20
20
 
21
- Build a modern frontend project (React/Vite/etc.) and publish the compiled app as one self-contained page:
21
+ `deploy` builds a frontend project **locally** and ships the compiled output. Single-page apps (Vite, CRA, …) are inlined into one self-contained page; multi-file sites (Next.js — auto-detected — Astro, Docusaurus, …) are hosted as a file tree at `view.htmlship.com/{slug}/`.
22
22
 
23
23
  ```bash
24
- npx htmlship deploy ./my-app # detect build script, build, inline, publish
25
- npx htmlship deploy --dry-run # build + inline without publishing
24
+ npx htmlship deploy ./my-app # SPA -> one inlined page
25
+ npx htmlship deploy ./my-next-app # Next.js -> multi-file site (auto-detected)
26
+ npx htmlship deploy ./my-app --site --out dist # force multi-file hosting (Astro, etc.)
27
+ npx htmlship deploy ./my-app --single-file # force single-file inlining
28
+ npx htmlship deploy ./my-app --password "demo-pass" # password-protect the deploy
29
+ npx htmlship deploy --dry-run # build, but don't publish
26
30
  npx htmlship deploy --build-cmd "vite build" --out dist
27
31
  ```
28
32
 
29
- The build runs **locally on your machine** (npm/pnpm/yarn/bun, auto-detected) — never on the server. The output is inlined into a single HTML file (≤ 10 MB) and published with relaxed sandboxing, so the app's JavaScript runs in an isolated, opaque origin (no cookies, no same-origin access, no network egress, no `eval`). The same flow is available to agents through the `deploy_project` MCP tool.
33
+ The build always runs **locally on your machine** (npm/pnpm/yarn/bun, auto-detected) — never on the server. Either way the result renders in its own isolated, opaque origin (no cookies, no same-origin access, no network egress, no `eval`) via a sandboxed CSP; single-file pages and site trees are both capped at 10 MB.
34
+
35
+ For Next.js the CLI builds a static export based at the slug path automatically (no `next.config` edits — JS, `.mjs`, and `.ts` configs are all handled) as long as the app is statically exportable (no middleware/SSR). For other frameworks, `--site` ships any static build; set your framework's base path to `/__htmlship_base__` so assets resolve under `/{slug}/`. The same flow is available to agents through the `deploy_project` MCP tool.
30
36
 
31
37
  ## MCP server
32
38
 
package/dist/cli.js CHANGED
@@ -296,22 +296,17 @@ function isNextProject(dir) {
296
296
  }
297
297
  function injectNextBase(dir) {
298
298
  const existing = NEXT_CONFIGS.find((f) => existsSync(join(dir, f)));
299
- if (existing && existing.endsWith(".ts")) {
300
- throw new HTMLShipError(
301
- `Next .ts config isn't auto-configured yet. Temporarily set basePath and assetPrefix to "${SITE_BASE_PLACEHOLDER}" and output: "export" in next.config.ts, or convert it to next.config.mjs, then re-run.`
302
- );
303
- }
304
- const wrapper = join(dir, "next.config.mjs");
305
299
  const base = SITE_BASE_PLACEHOLDER;
306
300
  if (!existing) {
301
+ const wrapper2 = join(dir, "next.config.mjs");
307
302
  writeFileSync(
308
- wrapper,
303
+ wrapper2,
309
304
  `export default { output: 'export', basePath: '${base}', assetPrefix: '${base}', images: { unoptimized: true }, trailingSlash: true };
310
305
  `
311
306
  );
312
307
  return () => {
313
308
  try {
314
- unlinkSync(wrapper);
309
+ unlinkSync(wrapper2);
315
310
  } catch {
316
311
  }
317
312
  };
@@ -319,14 +314,25 @@ function injectNextBase(dir) {
319
314
  const ext = extname(existing);
320
315
  const backupName = `next.config.__hsorig__${ext}`;
321
316
  renameSync(join(dir, existing), join(dir, backupName));
322
- writeFileSync(
323
- wrapper,
324
- `import orig from './${backupName}';
317
+ let wrapper;
318
+ let body;
319
+ if (ext === ".ts") {
320
+ wrapper = join(dir, "next.config.ts");
321
+ body = `import orig from './next.config.__hsorig__';
322
+ const base = '${base}';
323
+ const o = orig as any;
324
+ const merge = (c: any) => ({ ...c, output: 'export', basePath: base, assetPrefix: base, images: { ...(c && c.images), unoptimized: true }, trailingSlash: true });
325
+ export default typeof o === 'function' ? ((...a: any[]) => merge(o(...a))) : merge(o);
326
+ `;
327
+ } else {
328
+ wrapper = join(dir, "next.config.mjs");
329
+ body = `import orig from './${backupName}';
325
330
  const base = '${base}';
326
331
  const over = { output: 'export', basePath: base, assetPrefix: base, images: { ...(typeof orig === 'object' && orig ? orig.images : {}), unoptimized: true }, trailingSlash: true };
327
332
  export default typeof orig === 'function' ? ((...a) => ({ ...orig(...a), ...over })) : { ...orig, ...over };
328
- `
329
- );
333
+ `;
334
+ }
335
+ writeFileSync(wrapper, body);
330
336
  return () => {
331
337
  try {
332
338
  unlinkSync(wrapper);
@@ -450,7 +456,7 @@ var VERSION;
450
456
  var init_version = __esm({
451
457
  "src/version.ts"() {
452
458
  "use strict";
453
- VERSION = "0.3.0";
459
+ VERSION = "0.3.2";
454
460
  }
455
461
  });
456
462
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "htmlship",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Host and share HTML pages from LLMs and coding agents in one line. CLI + MCP server.",
5
5
  "keywords": [
6
6
  "html",