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.
- {htmlship-0.3.0 → htmlship-0.3.1}/PKG-INFO +25 -14
- {htmlship-0.3.0 → htmlship-0.3.1}/README.md +24 -13
- {htmlship-0.3.0 → htmlship-0.3.1}/pyproject.toml +1 -1
- htmlship-0.3.1/src/htmlship/_version.py +1 -0
- htmlship-0.3.1/src/htmlship_mcp/__init__.py +1 -0
- htmlship-0.3.1/src/htmlship_server/__init__.py +1 -0
- htmlship-0.3.0/src/htmlship/_version.py +0 -1
- htmlship-0.3.0/src/htmlship_mcp/__init__.py +0 -1
- htmlship-0.3.0/src/htmlship_server/__init__.py +0 -1
- {htmlship-0.3.0 → htmlship-0.3.1}/.gitignore +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/LICENSE +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/__init__.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/build.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/cli.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/client.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/exceptions.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship/models.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_mcp/server.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/config.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/database.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/db_models/__init__.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/db_models/page.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/exceptions.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/main.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/middleware.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/routers/__init__.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/routers/meta.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/routers/pages.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/routers/view.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/schemas/__init__.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/schemas/pages.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/security.py +0 -0
- {htmlship-0.3.0 → htmlship-0.3.1}/src/htmlship_server/slugs.py +0 -0
- {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.
|
|
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,
|
|
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
|
|
143
|
-
htmlship deploy
|
|
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
|
|
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.
|
|
152
|
-
3.
|
|
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
|
-
#
|
|
160
|
-
page = htmlship.HTMLShipClient().
|
|
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
|
|
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:**
|
|
172
|
+
**What `deploy` supports:**
|
|
167
173
|
|
|
168
|
-
**
|
|
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-
|
|
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
|
|
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,
|
|
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
|
|
98
|
-
htmlship deploy
|
|
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
|
|
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.
|
|
107
|
-
3.
|
|
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
|
-
#
|
|
115
|
-
page = htmlship.HTMLShipClient().
|
|
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
|
|
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:**
|
|
127
|
+
**What `deploy` supports:**
|
|
122
128
|
|
|
123
|
-
**
|
|
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-
|
|
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
|
|
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
|
|
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|