htmlship 0.3.0__tar.gz → 0.3.1__tar.gz

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 (34) hide show
  1. {htmlship-0.3.0 → htmlship-0.3.1}/PKG-INFO +25 -14
  2. {htmlship-0.3.0 → htmlship-0.3.1}/README.md +24 -13
  3. {htmlship-0.3.0 → htmlship-0.3.1}/pyproject.toml +1 -1
  4. htmlship-0.3.1/src/htmlship/_version.py +1 -0
  5. htmlship-0.3.1/src/htmlship_mcp/__init__.py +1 -0
  6. htmlship-0.3.1/src/htmlship_server/__init__.py +1 -0
  7. htmlship-0.3.0/src/htmlship/_version.py +0 -1
  8. htmlship-0.3.0/src/htmlship_mcp/__init__.py +0 -1
  9. htmlship-0.3.0/src/htmlship_server/__init__.py +0 -1
  10. {htmlship-0.3.0 → htmlship-0.3.1}/.gitignore +0 -0
  11. {htmlship-0.3.0 → htmlship-0.3.1}/LICENSE +0 -0
  12. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/__init__.py +0 -0
  13. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/build.py +0 -0
  14. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/cli.py +0 -0
  15. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/client.py +0 -0
  16. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/exceptions.py +0 -0
  17. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/models.py +0 -0
  18. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_mcp/server.py +0 -0
  19. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/config.py +0 -0
  20. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/database.py +0 -0
  21. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/db_models/__init__.py +0 -0
  22. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/db_models/page.py +0 -0
  23. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/exceptions.py +0 -0
  24. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/main.py +0 -0
  25. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/middleware.py +0 -0
  26. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/routers/__init__.py +0 -0
  27. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/routers/meta.py +0 -0
  28. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/routers/pages.py +0 -0
  29. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/routers/view.py +0 -0
  30. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/schemas/__init__.py +0 -0
  31. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/schemas/pages.py +0 -0
  32. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/security.py +0 -0
  33. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/slugs.py +0 -0
  34. {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/storage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: htmlship
3
- Version: 0.3.0
3
+ Version: 0.3.1
4
4
  Summary: Host and share HTML pages from LLMs and coding agents in one line.
5
5
  Project-URL: Homepage, https://htmlship.com
6
6
  Project-URL: Repository, https://github.com/htmlship/htmlship
@@ -136,36 +136,44 @@ The CLI stores owner keys in `~/.htmlship/keys.json` so `update`, `delete`, and
136
136
 
137
137
  ## Deploy built apps
138
138
 
139
- `deploy` builds a modern frontend project (React, Vite, Svelte, etc.) and publishes the **compiled** app as a single self-contained page — no separate asset hosting required.
139
+ `deploy` builds a modern frontend project (React, Vite, Svelte, Next.js, …) **locally** and publishes the compiled output. Single-page apps are inlined into one self-contained page; multi-file sites (Next.js static export auto-detected — Astro, Docusaurus, VitePress, …) are hosted as a file tree at `view.htmlship.com/{slug}/`. No separate asset hosting required either way.
140
140
 
141
141
  ```bash
142
- htmlship deploy ./my-app # detect build script, build, inline, publish
143
- htmlship deploy --dry-run # build + inline, but don't publish (inspect first)
142
+ htmlship deploy ./my-app # SPA -> one inlined page
143
+ htmlship deploy ./my-next-app # Next.js -> multi-file site (auto-detected)
144
+ htmlship deploy ./my-app --site --out dist # force multi-file hosting (Astro, etc.)
145
+ htmlship deploy ./my-app --single-file # force single-file inlining
146
+ htmlship deploy ./my-app --password "demo-pass" # password-protect the deploy
147
+ htmlship deploy --dry-run # build, but don't publish (inspect first)
144
148
  htmlship deploy --build-cmd "vite build" --out dist
145
- npx htmlship deploy ./my-app # same, no install
149
+ npx htmlship deploy ./my-app # same, no install
146
150
  ```
147
151
 
148
152
  How it works:
149
153
 
150
154
  1. **The build runs locally, on your machine — never on the server.** `deploy` detects your package manager (npm/pnpm/yarn/bun) and runs the `build` script (falling back to `build:prod`, or `--build-cmd` to override). This is what keeps the service from ever executing untrusted build steps.
151
- 2. The build output (`dist/` or `build/`, or `--out`) is **inlined into one HTML file**: scripts and stylesheets are embedded, and referenced images/icons/fonts become data URIs. The result must be 10 MB.
152
- 3. It's published with `sandbox_mode: "relaxed"` so the app's JavaScript can run (see [Rendering](#rendering)).
155
+ 2. **Single-file** (default for SPAs): the output (`dist/`, `build/`, or `--out`) is inlined into one HTML file scripts and stylesheets embedded, images/icons/fonts as data URIs and published with `sandbox_mode: "relaxed"`.
156
+ 3. **Multi-file** (Next.js auto-detected, or `--site`): the whole output tree is uploaded as a base64 file manifest to `POST /api/v1/sites` and served at `view.htmlship.com/{slug}/`, each response carrying a path-scoped per-slug sandbox CSP.
157
+
158
+ Both kinds run with relaxed sandboxing (see [Rendering](#rendering)) and are capped at 10 MB. `--single-file` and `--site` force a mode when you don't want the auto-detected one.
153
159
 
154
160
  The same flow is available programmatically (Python library) and via the `deploy_project` MCP tool:
155
161
 
156
162
  ```python
157
163
  import htmlship
158
164
 
159
- # Library: build ./my-app locally and publish the compiled app
160
- page = htmlship.HTMLShipClient().deploy("./my-app", expires_in=1440)
165
+ # build ./my-app locally and publish (auto-detects single-file vs. multi-file site)
166
+ page = htmlship.HTMLShipClient().deploy_project("./my-app", password="demo-pass", expires_in=1440)
161
167
  print(page.url)
162
168
  ```
163
169
 
164
- **Relaxed-mode limits (by design):** a deployed app runs in an isolated, opaque origin and **cannot** make network requests (`connect-src 'none'`), read cookies, access other pages, or use `eval`. It's intended for self-contained client-side apps and demos — not for apps that call external APIs at runtime.
170
+ **Relaxed-mode limits (by design):** a deployed app runs in an isolated, opaque origin and **cannot** make network requests (`connect-src 'none'`), read cookies, access other pages, or use `eval`. For a multi-file Next.js site that means client-side data fetches fail closed and Next falls back to full-page navigation — links still work, runtime API calls don't. It's intended for self-contained client-side apps, demos, and static content — not for apps that call external APIs at runtime.
165
171
 
166
- **What `deploy` supports:** single-page static apps that build to one `index.html` plus assets — Vite, Create React App, Astro (static), SvelteKit (`adapter-static`), Vue CLI, plain static-site generators. `deploy` auto-detects `dist/`, `build/`, and `out/` with no flags.
172
+ **What `deploy` supports:**
167
173
 
168
- **Next.js note:** a default `next build` produces a *server* build in `.next/`, which is not statically hostable anywhere — and renaming it via `distDir` doesn't change that. To deploy a Next.js app you must add `output: "export"` to `next.config` (it emits a static `out/` folder, which `deploy` picks up automatically). Apps that rely on middleware, SSR, or multi-route i18n can't be statically exported and aren't a fit for single-file hosting.
174
+ - **Single-page apps** that build to one `index.html` plus assets Vite, Create React App, SvelteKit (`adapter-static`), Vue CLI, plain static-site generators. Auto-detects `dist/`, `build/`, and `out/` with no flags.
175
+ - **Next.js** (auto-detected): the CLI transparently builds a **static export based at the slug path** — you don't edit `next.config`. The app must be statically exportable (no middleware, SSR, or server features). One exception: a `next.config.ts` can't be rewritten automatically yet, so `deploy` asks you to set `output: "export"` plus `basePath`/`assetPrefix = "/__htmlship_base__"` yourself, or convert the config to `next.config.mjs`.
176
+ - **Other multi-file frameworks** via `--site` (Astro, Docusaurus, VitePress, multi-page builds): build with your framework's base path set to `/__htmlship_base__` (e.g. Astro's `base`, or `vite build --base=/__htmlship_base__/`) so root-absolute asset URLs resolve under `/{slug}/`; the server rewrites that placeholder to the real slug at upload. Automatic base injection is currently Next.js-only.
169
177
 
170
178
  ## API
171
179
 
@@ -176,6 +184,7 @@ Base URL: `https://api.htmlship.com`.
176
184
  | `GET` | `/health` | Health check with service version. |
177
185
  | `GET` | `/version` | Service version. |
178
186
  | `POST` | `/api/v1/pages` | Create a page. |
187
+ | `POST` | `/api/v1/sites` | Upload a multi-file static site (base64 file manifest); served at `view.htmlship.com/{slug}/`. |
179
188
  | `GET` | `/api/v1/pages/{slug}` | Fetch page metadata. |
180
189
  | `PATCH` | `/api/v1/pages/{slug}` | Replace HTML or title. Requires `X-Owner-Key`. |
181
190
  | `DELETE` | `/api/v1/pages/{slug}` | Soft-delete a page. Requires `X-Owner-Key`. |
@@ -202,7 +211,7 @@ Notes:
202
211
  - `sandbox_mode` accepts `strict` (default) or `relaxed`. `strict` blocks all scripts; `relaxed` lets the page's own inline scripts run inside an isolated, opaque origin (used by `deploy` for compiled apps). See [Rendering](#rendering).
203
212
  - Password-protected views set a signed, HTTP-only session cookie after the correct password is submitted.
204
213
 
205
- There is no server-side build endpoint, by design: builds always run on the client (see [Deploy built apps](#deploy-built-apps)). The API only ever receives already-inlined HTML, so deploying via the API is simply a `POST /api/v1/pages` with `"sandbox_mode": "relaxed"`.
214
+ There is no server-side build endpoint, by design: builds always run on the client (see [Deploy built apps](#deploy-built-apps)). The API only ever receives already-built output single-file deploys are a `POST /api/v1/pages` with `"sandbox_mode": "relaxed"`; multi-file sites are a `POST /api/v1/sites` with a base64 file manifest, served per-slug at `view.htmlship.com/{slug}/`.
206
215
 
207
216
  ## Rendering
208
217
 
@@ -218,11 +227,13 @@ Rendered HTML is served from `view.htmlship.com/{slug}`. **Strict** pages (the d
218
227
 
219
228
  **Relaxed** pages (`sandbox_mode: "relaxed"`, used by `deploy`) let the page's own inline scripts run but isolate them with `Content-Security-Policy: sandbox allow-scripts` — deliberately *without* `allow-same-origin`. That forces an opaque origin, so a deployed app cannot read cookies, touch `localStorage`, or fetch other pages same-origin. `connect-src 'none'` additionally blocks network egress. The body is still served verbatim; isolation is enforced entirely by response headers, with no change to the single-file storage model.
220
229
 
230
+ **Multi-file sites** (`deploy` of a Next.js export or `--site`) are served at `view.htmlship.com/{slug}/` from a per-slug file tree. Each response carries the same opaque-origin `sandbox` CSP, additionally path-scoped to `/{slug}/` (`script-src`/`style-src`/`img-src`/`font-src` are pinned to that prefix). Per-slug isolation therefore comes from the CSP, not from the URL path — one slug's scripts can't read another's, and `connect-src 'none'` blocks egress just as for single-file pages.
231
+
221
232
  The app routes by `Host` header:
222
233
 
223
234
  - `htmlship.com` serves the landing page
224
235
  - `api.htmlship.com` serves the API and landing assets
225
- - `view.htmlship.com/{slug}` serves sandboxed HTML
236
+ - `view.htmlship.com/{slug}` serves a sandboxed single page; `view.htmlship.com/{slug}/…` serves a multi-file site's tree
226
237
 
227
238
  For local development without DNS, append `?_host=view.htmlship.com` (or your configured view host) to spoof the host header, for example:
228
239
 
@@ -91,36 +91,44 @@ The CLI stores owner keys in `~/.htmlship/keys.json` so `update`, `delete`, and
91
91
 
92
92
  ## Deploy built apps
93
93
 
94
- `deploy` builds a modern frontend project (React, Vite, Svelte, etc.) and publishes the **compiled** app as a single self-contained page — no separate asset hosting required.
94
+ `deploy` builds a modern frontend project (React, Vite, Svelte, Next.js, …) **locally** and publishes the compiled output. Single-page apps are inlined into one self-contained page; multi-file sites (Next.js static export auto-detected — Astro, Docusaurus, VitePress, …) are hosted as a file tree at `view.htmlship.com/{slug}/`. No separate asset hosting required either way.
95
95
 
96
96
  ```bash
97
- htmlship deploy ./my-app # detect build script, build, inline, publish
98
- htmlship deploy --dry-run # build + inline, but don't publish (inspect first)
97
+ htmlship deploy ./my-app # SPA -> one inlined page
98
+ htmlship deploy ./my-next-app # Next.js -> multi-file site (auto-detected)
99
+ htmlship deploy ./my-app --site --out dist # force multi-file hosting (Astro, etc.)
100
+ htmlship deploy ./my-app --single-file # force single-file inlining
101
+ htmlship deploy ./my-app --password "demo-pass" # password-protect the deploy
102
+ htmlship deploy --dry-run # build, but don't publish (inspect first)
99
103
  htmlship deploy --build-cmd "vite build" --out dist
100
- npx htmlship deploy ./my-app # same, no install
104
+ npx htmlship deploy ./my-app # same, no install
101
105
  ```
102
106
 
103
107
  How it works:
104
108
 
105
109
  1. **The build runs locally, on your machine — never on the server.** `deploy` detects your package manager (npm/pnpm/yarn/bun) and runs the `build` script (falling back to `build:prod`, or `--build-cmd` to override). This is what keeps the service from ever executing untrusted build steps.
106
- 2. The build output (`dist/` or `build/`, or `--out`) is **inlined into one HTML file**: scripts and stylesheets are embedded, and referenced images/icons/fonts become data URIs. The result must be 10 MB.
107
- 3. It's published with `sandbox_mode: "relaxed"` so the app's JavaScript can run (see [Rendering](#rendering)).
110
+ 2. **Single-file** (default for SPAs): the output (`dist/`, `build/`, or `--out`) is inlined into one HTML file scripts and stylesheets embedded, images/icons/fonts as data URIs and published with `sandbox_mode: "relaxed"`.
111
+ 3. **Multi-file** (Next.js auto-detected, or `--site`): the whole output tree is uploaded as a base64 file manifest to `POST /api/v1/sites` and served at `view.htmlship.com/{slug}/`, each response carrying a path-scoped per-slug sandbox CSP.
112
+
113
+ Both kinds run with relaxed sandboxing (see [Rendering](#rendering)) and are capped at 10 MB. `--single-file` and `--site` force a mode when you don't want the auto-detected one.
108
114
 
109
115
  The same flow is available programmatically (Python library) and via the `deploy_project` MCP tool:
110
116
 
111
117
  ```python
112
118
  import htmlship
113
119
 
114
- # Library: build ./my-app locally and publish the compiled app
115
- page = htmlship.HTMLShipClient().deploy("./my-app", expires_in=1440)
120
+ # build ./my-app locally and publish (auto-detects single-file vs. multi-file site)
121
+ page = htmlship.HTMLShipClient().deploy_project("./my-app", password="demo-pass", expires_in=1440)
116
122
  print(page.url)
117
123
  ```
118
124
 
119
- **Relaxed-mode limits (by design):** a deployed app runs in an isolated, opaque origin and **cannot** make network requests (`connect-src 'none'`), read cookies, access other pages, or use `eval`. It's intended for self-contained client-side apps and demos — not for apps that call external APIs at runtime.
125
+ **Relaxed-mode limits (by design):** a deployed app runs in an isolated, opaque origin and **cannot** make network requests (`connect-src 'none'`), read cookies, access other pages, or use `eval`. For a multi-file Next.js site that means client-side data fetches fail closed and Next falls back to full-page navigation — links still work, runtime API calls don't. It's intended for self-contained client-side apps, demos, and static content — not for apps that call external APIs at runtime.
120
126
 
121
- **What `deploy` supports:** single-page static apps that build to one `index.html` plus assets — Vite, Create React App, Astro (static), SvelteKit (`adapter-static`), Vue CLI, plain static-site generators. `deploy` auto-detects `dist/`, `build/`, and `out/` with no flags.
127
+ **What `deploy` supports:**
122
128
 
123
- **Next.js note:** a default `next build` produces a *server* build in `.next/`, which is not statically hostable anywhere — and renaming it via `distDir` doesn't change that. To deploy a Next.js app you must add `output: "export"` to `next.config` (it emits a static `out/` folder, which `deploy` picks up automatically). Apps that rely on middleware, SSR, or multi-route i18n can't be statically exported and aren't a fit for single-file hosting.
129
+ - **Single-page apps** that build to one `index.html` plus assets Vite, Create React App, SvelteKit (`adapter-static`), Vue CLI, plain static-site generators. Auto-detects `dist/`, `build/`, and `out/` with no flags.
130
+ - **Next.js** (auto-detected): the CLI transparently builds a **static export based at the slug path** — you don't edit `next.config`. The app must be statically exportable (no middleware, SSR, or server features). One exception: a `next.config.ts` can't be rewritten automatically yet, so `deploy` asks you to set `output: "export"` plus `basePath`/`assetPrefix = "/__htmlship_base__"` yourself, or convert the config to `next.config.mjs`.
131
+ - **Other multi-file frameworks** via `--site` (Astro, Docusaurus, VitePress, multi-page builds): build with your framework's base path set to `/__htmlship_base__` (e.g. Astro's `base`, or `vite build --base=/__htmlship_base__/`) so root-absolute asset URLs resolve under `/{slug}/`; the server rewrites that placeholder to the real slug at upload. Automatic base injection is currently Next.js-only.
124
132
 
125
133
  ## API
126
134
 
@@ -131,6 +139,7 @@ Base URL: `https://api.htmlship.com`.
131
139
  | `GET` | `/health` | Health check with service version. |
132
140
  | `GET` | `/version` | Service version. |
133
141
  | `POST` | `/api/v1/pages` | Create a page. |
142
+ | `POST` | `/api/v1/sites` | Upload a multi-file static site (base64 file manifest); served at `view.htmlship.com/{slug}/`. |
134
143
  | `GET` | `/api/v1/pages/{slug}` | Fetch page metadata. |
135
144
  | `PATCH` | `/api/v1/pages/{slug}` | Replace HTML or title. Requires `X-Owner-Key`. |
136
145
  | `DELETE` | `/api/v1/pages/{slug}` | Soft-delete a page. Requires `X-Owner-Key`. |
@@ -157,7 +166,7 @@ Notes:
157
166
  - `sandbox_mode` accepts `strict` (default) or `relaxed`. `strict` blocks all scripts; `relaxed` lets the page's own inline scripts run inside an isolated, opaque origin (used by `deploy` for compiled apps). See [Rendering](#rendering).
158
167
  - Password-protected views set a signed, HTTP-only session cookie after the correct password is submitted.
159
168
 
160
- There is no server-side build endpoint, by design: builds always run on the client (see [Deploy built apps](#deploy-built-apps)). The API only ever receives already-inlined HTML, so deploying via the API is simply a `POST /api/v1/pages` with `"sandbox_mode": "relaxed"`.
169
+ There is no server-side build endpoint, by design: builds always run on the client (see [Deploy built apps](#deploy-built-apps)). The API only ever receives already-built output single-file deploys are a `POST /api/v1/pages` with `"sandbox_mode": "relaxed"`; multi-file sites are a `POST /api/v1/sites` with a base64 file manifest, served per-slug at `view.htmlship.com/{slug}/`.
161
170
 
162
171
  ## Rendering
163
172
 
@@ -173,11 +182,13 @@ Rendered HTML is served from `view.htmlship.com/{slug}`. **Strict** pages (the d
173
182
 
174
183
  **Relaxed** pages (`sandbox_mode: "relaxed"`, used by `deploy`) let the page's own inline scripts run but isolate them with `Content-Security-Policy: sandbox allow-scripts` — deliberately *without* `allow-same-origin`. That forces an opaque origin, so a deployed app cannot read cookies, touch `localStorage`, or fetch other pages same-origin. `connect-src 'none'` additionally blocks network egress. The body is still served verbatim; isolation is enforced entirely by response headers, with no change to the single-file storage model.
175
184
 
185
+ **Multi-file sites** (`deploy` of a Next.js export or `--site`) are served at `view.htmlship.com/{slug}/` from a per-slug file tree. Each response carries the same opaque-origin `sandbox` CSP, additionally path-scoped to `/{slug}/` (`script-src`/`style-src`/`img-src`/`font-src` are pinned to that prefix). Per-slug isolation therefore comes from the CSP, not from the URL path — one slug's scripts can't read another's, and `connect-src 'none'` blocks egress just as for single-file pages.
186
+
176
187
  The app routes by `Host` header:
177
188
 
178
189
  - `htmlship.com` serves the landing page
179
190
  - `api.htmlship.com` serves the API and landing assets
180
- - `view.htmlship.com/{slug}` serves sandboxed HTML
191
+ - `view.htmlship.com/{slug}` serves a sandboxed single page; `view.htmlship.com/{slug}/…` serves a multi-file site's tree
181
192
 
182
193
  For local development without DNS, append `?_host=view.htmlship.com` (or your configured view host) to spoof the host header, for example:
183
194
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "htmlship"
3
- version = "0.3.0"
3
+ version = "0.3.1"
4
4
  description = "Host and share HTML pages from LLMs and coding agents in one line."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -0,0 +1 @@
1
+ __version__ = "0.3.1"
@@ -0,0 +1 @@
1
+ __version__ = "0.3.1"
@@ -0,0 +1 @@
1
+ __version__ = "0.3.1"
@@ -1 +0,0 @@
1
- __version__ = "0.3.0"
@@ -1 +0,0 @@
1
- __version__ = "0.3.0"
@@ -1 +0,0 @@
1
- __version__ = "0.3.0"
File without changes
File without changes
File without changes
File without changes