shiply-cli 0.27.2 → 0.29.0
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.
- package/dist/access.js +54 -0
- package/dist/data.js +1 -0
- package/dist/db.js +2 -0
- package/dist/domain.js +30 -0
- package/dist/drive.js +15 -4
- package/dist/index.js +151 -8
- package/dist/login.js +9 -3
- package/dist/publish.js +6 -1
- package/dist/sending-domains.js +1 -0
- package/dist/sites.js +1 -0
- package/dist/variable.js +80 -0
- package/package.json +42 -42
- package/skill/CHANGELOG.md +10 -0
- package/skill/SKILL.md +256 -253
- package/skill/references/client-work.md +93 -12
- package/skill/references/custom-domains.md +2 -0
- package/skill/references/databases.md +5 -0
- package/skill/references/drives.md +70 -0
- package/skill/references/email.md +24 -0
- package/skill/references/publishing.md +3 -1
- package/skill/references/site-features.md +26 -8
- package/skill/references/ssr-frameworks.md +57 -57
|
@@ -31,16 +31,49 @@ list_project_files — files uploaded by the customer
|
|
|
31
31
|
resend_intake_invite — re-email the customer their intake link (requires customerEmail on project)
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
REST:
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
REST:
|
|
35
|
+
|
|
36
|
+
| Endpoint | Action |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `POST/GET /api/v1/projects` | create / list |
|
|
39
|
+
| `GET/PATCH /api/v1/projects/{id}` | read / update brief or metadata |
|
|
40
|
+
| `POST /api/v1/projects/{id}/regenerate-brief` | re-run AI from current intake responses |
|
|
41
|
+
| `POST /api/v1/projects/{id}/archive` `{reason?}` | dedicated archive route — mirrors `archive_project` (`PATCH .../{id}` `{"status":"archived"}` still works too, back-compat) |
|
|
42
|
+
| `GET /api/v1/projects/{id}/files/zip` | download every customer-uploaded file as one .zip |
|
|
43
|
+
| `GET /api/v1/projects/{id}/files/{fileId}/download` | 302-redirect to a short-lived signed URL for one file |
|
|
44
|
+
| `POST /api/v1/projects/{id}/upload` | dev sends the customer a file (multipart `file` field, ≤25 MB) |
|
|
45
|
+
| `PATCH /api/v1/projects/{id}/status-note` `{note}` | short customer-facing status line shown in the portal header (`note:null` clears it) |
|
|
46
|
+
| `POST /api/v1/projects/{id}/resend-portal-link` | dev re-sends the customer's **portal** link — different from `resend_intake_invite`/`resend-invite` below, which re-sends the original **intake** invite |
|
|
38
47
|
|
|
39
48
|
CLI: `shiply project ls · shiply project create <label> [--customer-email <e>]
|
|
40
49
|
[--customer-name <n>] · shiply project get <id> · shiply project archive <id>`
|
|
41
50
|
|
|
42
51
|
Docs: https://shiply.now/docs/projects
|
|
43
52
|
|
|
53
|
+
### Intake — the customer-facing side (token auth, not Bearer)
|
|
54
|
+
|
|
55
|
+
The intake URL a customer opens is token-scoped, not account-scoped — no
|
|
56
|
+
Bearer key. These routes power the wizard, portal chat, and dev-side nudges:
|
|
57
|
+
|
|
58
|
+
| Endpoint | Action |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `GET /api/v1/intake/{token}/state` | current status + saved wizard responses + project label |
|
|
61
|
+
| `PATCH /api/v1/intake/{token}` `{stepKey, data}` | save one wizard step (auto-save as the customer types) |
|
|
62
|
+
| `POST /api/v1/intake/{token}/submit` | run AI brief generation from the saved responses |
|
|
63
|
+
| `GET /api/v1/intake/{token}/contract` | the project's contract, if one has been sent to this token |
|
|
64
|
+
| `GET/POST /api/v1/intake/{token}/files` | list / upload customer attachments |
|
|
65
|
+
| `DELETE /api/v1/intake/{token}/files/{fileId}` | remove an uploaded attachment |
|
|
66
|
+
| `GET/POST /api/v1/intake/{token}/messages` `{body}` (POST) | portal chat thread with the dev, oldest-first, `?before=` cursor |
|
|
67
|
+
| `POST /api/v1/intake/{token}/nudge` | dev-triggered reminder ping to the customer |
|
|
68
|
+
| `POST /api/v1/intake/{token}/email-link` | re-email the customer their intake link |
|
|
69
|
+
| `POST /api/v1/intake/{token}/cookie` | set the portal session cookie for this token |
|
|
70
|
+
| `GET /api/v1/intake/{token}/activity` | activity/audit log for this intake |
|
|
71
|
+
| `POST /api/v1/intake/{token}/suggest` | AI suggestion helper for a wizard field |
|
|
72
|
+
|
|
73
|
+
Dev-side equivalent for re-sending the invite email is `resend_intake_invite`
|
|
74
|
+
(MCP) / `POST /api/v1/projects/{id}/resend-invite` — different from the
|
|
75
|
+
customer-token `email-link` route above.
|
|
76
|
+
|
|
44
77
|
## Group work by client (optional, for freelancers)
|
|
45
78
|
|
|
46
79
|
Building sites for clients? Pass an optional `client` (a name or email) on any
|
|
@@ -56,7 +89,28 @@ drive/intake/contract all land under the same client. List calls take an
|
|
|
56
89
|
optional `clientId` filter (`list_sites`/`list_drives`/`list_projects`).
|
|
57
90
|
Omit `client` for personal projects; shiply works identically.
|
|
58
91
|
CLI: `--client "<name-or-email>"` on publish/drive/project, plus
|
|
59
|
-
`shiply client ls|show`.
|
|
92
|
+
`shiply client ls|show`. Re-assign (or clear) a client on an already-published
|
|
93
|
+
site directly: `PATCH /api/v1/publish/{slug}/client` `{clientId}`
|
|
94
|
+
(`clientId: null` clears it) — no MCP tool for this yet, REST only.
|
|
95
|
+
|
|
96
|
+
REST (Bearer; Studio plan — `assertStudioEntitled` gates `POST`):
|
|
97
|
+
|
|
98
|
+
| Endpoint | Action |
|
|
99
|
+
|---|---|
|
|
100
|
+
| `GET /api/v1/clients` | list your clients → `{clients}` |
|
|
101
|
+
| `POST /api/v1/clients` `{name, email?, phone?, company?, notes?}` | create a client explicitly (usually unnecessary — clients self-assemble from `client`/`customerEmail`) |
|
|
102
|
+
| `GET /api/v1/clients/{id}` | rollup view: sites, drives, projects, contracts, invoices under this client |
|
|
103
|
+
| `GET /api/v1/clients/{id}/invoices` | list invoices for this client |
|
|
104
|
+
| `POST /api/v1/clients/{id}/invoices` `{description, amountCents, currency?, dueDate?, projectId?}` | create an invoice |
|
|
105
|
+
| `POST /api/v1/invoices/{id}/send` | email the invoice to the client |
|
|
106
|
+
| `POST /api/v1/invoices/{id}/void` | void an unpaid invoice |
|
|
107
|
+
| `POST /api/v1/clients/{id}/portal` | enable the client's public portal (idempotent) → `{portalUrl}` |
|
|
108
|
+
| `DELETE /api/v1/clients/{id}/portal` | disable the portal — the link dies immediately |
|
|
109
|
+
| `POST /api/v1/clients/{id}/portal/rotate` | mint a fresh portal token (old link dies instantly) |
|
|
110
|
+
|
|
111
|
+
No `list_clients`/`get_client`/portal-management MCP tools exist yet — this
|
|
112
|
+
is REST + CLI (`shiply client ls|show`) only; an MCP agent reads client data
|
|
113
|
+
indirectly via `list_sites`/`list_drives`/`list_projects` with `clientId`.
|
|
60
114
|
|
|
61
115
|
## Contracts — draft, sign, amend (extends Projects)
|
|
62
116
|
|
|
@@ -91,7 +145,7 @@ Example agent flow (draft → tweak fee → send → poll → amend):
|
|
|
91
145
|
6. `contract_send({contractId: amendment.id})` (no PATCH needed if the amend fields are right)
|
|
92
146
|
|
|
93
147
|
REST (Bearer for dev, portal cookie for customer):
|
|
94
|
-
`POST /api/v1/projects/{id}/
|
|
148
|
+
`POST /api/v1/projects/{id}/contract` (draft — singular; the plural `/contracts` is a GET-only read bundle) ·
|
|
95
149
|
`GET/PATCH /api/v1/contracts/{id}` (read either-party / dev edit) ·
|
|
96
150
|
`POST /api/v1/contracts/{id}/send` (dev) ·
|
|
97
151
|
`POST /api/v1/contracts/{id}/view` (customer ping) ·
|
|
@@ -141,12 +195,13 @@ refund_order — issue Stripe refund (within refund window; goes back to buy
|
|
|
141
195
|
get_connect_status — Stripe Connect onboarding state + actionable URL
|
|
142
196
|
```
|
|
143
197
|
|
|
144
|
-
REST: `POST /api/v1/listings · PATCH /api/v1/listings/{id} ·
|
|
145
|
-
POST /api/v1/listings/{id}/checkout ·
|
|
146
|
-
GET /api/v1/connect/status`
|
|
147
|
-
(
|
|
148
|
-
|
|
149
|
-
|
|
198
|
+
REST: `GET/POST /api/v1/listings · PATCH /api/v1/listings/{id} ·
|
|
199
|
+
POST /api/v1/listings/{id}/checkout · GET /api/v1/orders ·
|
|
200
|
+
POST /api/v1/orders/{id}/refund · GET /api/v1/connect/status`
|
|
201
|
+
(`GET /api/v1/listings` and `GET /api/v1/orders` list your own listings/
|
|
202
|
+
orders — `?limit=` supported; MCP mirrors are `list_listings` /
|
|
203
|
+
`list_my_orders`. Sales specifically: `GET /api/v1/listings/sales` /
|
|
204
|
+
`list_my_sales`.)
|
|
150
205
|
|
|
151
206
|
CLI: `shiply listing ls · shiply listing create <site-slug> --price <cents>
|
|
152
207
|
--jurisdiction "<region>" · shiply listing rm <slug> --id <listing-id>`
|
|
@@ -157,3 +212,29 @@ isn't `'ready'` it returns an `onboardingUrl` you should hand to the
|
|
|
157
212
|
user as a clickable link.
|
|
158
213
|
|
|
159
214
|
Docs: https://shiply.now/docs/marketplace
|
|
215
|
+
|
|
216
|
+
## Inbox threads — reply, forward, archive, summarize, AI draft
|
|
217
|
+
|
|
218
|
+
The account-wide inbox (replies, unsubscribes, complaints, bounces across
|
|
219
|
+
every site) beyond the read-only MCP tools in [email.md](email.md):
|
|
220
|
+
|
|
221
|
+
MCP tools: `list_inbox` (filtered list + counts in one call — filters
|
|
222
|
+
`all|unread|replies|unsubscribes|complaints|bounces|archived`), `read_thread`
|
|
223
|
+
(marks read implicitly), `mark_thread_read`, `summarize_thread`,
|
|
224
|
+
`reply_to_thread`, `forward_thread`, `archive_thread`, `unarchive_thread`.
|
|
225
|
+
|
|
226
|
+
REST (Bearer):
|
|
227
|
+
|
|
228
|
+
| Endpoint | Action |
|
|
229
|
+
|---|---|
|
|
230
|
+
| `GET /api/v1/inbox/threads?filter=&limit=&offset=` | atomic snapshot: `{threads, counts}` |
|
|
231
|
+
| `GET /api/v1/inbox/threads/{id}` | one thread (also marks read) |
|
|
232
|
+
| `PATCH /api/v1/inbox/threads/{id}` `{action:"mark_read"\|"archive"\|"unarchive"}` | thread lifecycle |
|
|
233
|
+
| `POST /api/v1/inbox/threads/{id}/reply` `{body, subject?}` | reply from the original recipient alias, threaded via In-Reply-To |
|
|
234
|
+
| `POST /api/v1/inbox/threads/{id}/forward` `{to, messageId?, subject?, note?}` | forward one message to a new address |
|
|
235
|
+
| `POST /api/v1/inbox/threads/{id}/summarize` | AI summary of the thread |
|
|
236
|
+
| `POST /api/v1/inbox/threads/{id}/ai-reply` | AI-drafted reply body (review before sending — no matching MCP tool yet) |
|
|
237
|
+
|
|
238
|
+
**Gap (intentional, tracked):** the CLI has no `shiply inbox` thread-action
|
|
239
|
+
subcommands (reply/forward/archive/summarize) — use MCP or REST for those;
|
|
240
|
+
`shiply email inbox` only reads.
|
|
@@ -40,6 +40,8 @@ shiply domain sub add www.example.com --site my-site # map a subdomain → sit
|
|
|
40
40
|
shiply domain ls # list all domains + subdomains + status
|
|
41
41
|
shiply domain sync example.com # re-sync DNS records with a connected provider
|
|
42
42
|
shiply domain primary <hostname> # mark hostname canonical (siblings 301)
|
|
43
|
+
shiply domain check example.com # re-poll cert/DNS/HTTPS readiness per subdomain
|
|
44
|
+
shiply domain rm example.com --yes # remove a domain (its subdomains stop resolving)
|
|
43
45
|
```
|
|
44
46
|
|
|
45
47
|
For one-click connect (`shiply domain connect`), the CLI prints an
|
|
@@ -95,6 +95,11 @@ for D1 and Neon), `POST .../attach` to bind, `DELETE` to drop. Neon-only:
|
|
|
95
95
|
`POST/GET/DELETE /api/v1/databases/{id}/branches[/{branchId}]` (400 on
|
|
96
96
|
D1 rows).
|
|
97
97
|
|
|
98
|
+
Main MCP server (account-wide lifecycle — start here to discover a
|
|
99
|
+
databaseId): `list_databases`, `create_database`, `delete_database`,
|
|
100
|
+
`attach_database`. Then, to query/introspect one database, connect the
|
|
101
|
+
per-DB MCP server below with that id.
|
|
102
|
+
|
|
98
103
|
Per-DB MCP server (so an agent can be scoped to one DB):
|
|
99
104
|
`https://shiply.now/api/mcp/db/<id>/sse` (or `/mcp` for streamable-http),
|
|
100
105
|
Bearer `shp_…` — tools: `db_query`, `db_list_tables`, `db_schema`. The same
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
title: Drives (private storage — REST, CLI, MCP)
|
|
4
|
+
description: Full reference for Drives — private cloud storage for agent memory, notes, and assets. Staged uploads, sharing links, client assignment, and publish-from-drive.
|
|
5
|
+
timestamp: 2026-07-14
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Drives — private cloud storage
|
|
9
|
+
|
|
10
|
+
Part of the shiply skill (see SKILL.md for publish basics). A Drive is
|
|
11
|
+
private storage — files, notes, context — that is **not** served publicly
|
|
12
|
+
like a published site. Every account gets a `default` drive on first use;
|
|
13
|
+
you can also create named drives (e.g. one per client).
|
|
14
|
+
|
|
15
|
+
## REST (Bearer `shp_...`)
|
|
16
|
+
|
|
17
|
+
| Endpoint | Action |
|
|
18
|
+
|---|---|
|
|
19
|
+
| `GET /api/v1/drives?clientId=` | list your drives (optional client filter) → `{drives}` |
|
|
20
|
+
| `POST /api/v1/drives` `{name, client?}` | create a named drive. `client` is the same optional `{clientId?, clientEmail?, clientName?, clientCompany?}` shape used on publish/create_project |
|
|
21
|
+
| `GET /api/v1/drives/default` | the account's auto-provisioned default drive (creates it on first call) |
|
|
22
|
+
| `GET /api/v1/drives/{id}` | drive detail |
|
|
23
|
+
| `DELETE /api/v1/drives/{id}` | delete a drive and its files |
|
|
24
|
+
| `GET /api/v1/drives/{id}/files?prefix=&cursor=` | list files (optional path-prefix filter, pagination cursor) |
|
|
25
|
+
| `POST /api/v1/drives/{id}/files/uploads` `{files:[{path,size,contentType?,hash}]}` | stage up to 1000 files → presigned PUT URLs (same 3-step flow as site publish) |
|
|
26
|
+
| `POST /api/v1/drives/{id}/files/finalize` `{files:[{path,size,contentType?,hash}]}` | confirm uploads landed — same `files` array as the uploads call |
|
|
27
|
+
| `GET /api/v1/drives/{id}/files/{...path}` | `{url}` — a presigned, time-limited download URL for one file |
|
|
28
|
+
| `DELETE /api/v1/drives/{id}/files/{...path}` | delete one file (optional `If-Match` header for optimistic concurrency) |
|
|
29
|
+
| `POST /api/v1/drives/{id}/assign-client` `{clientId}` | file this drive under a client (`clientId: null` clears it) |
|
|
30
|
+
| `POST /api/v1/drives/{id}/share` `{instructions?}` | enable a public share link for the drive |
|
|
31
|
+
| `DELETE /api/v1/drives/{id}/share` | disable the share link |
|
|
32
|
+
| `POST /api/v1/drives/{id}/share/rotate` | mint a fresh share token — the old link dies instantly |
|
|
33
|
+
| `POST /api/v1/drives/{id}/share/invite` `{emails:[...max 50], message?}` | email the share link to a list of addresses |
|
|
34
|
+
|
|
35
|
+
`{id}` is the drive's public id (`drv_...`), or the literal string
|
|
36
|
+
`default` where the endpoint supports it (only `GET /api/v1/drives/default`
|
|
37
|
+
resolves the alias itself — everywhere else, resolve `default` to a real
|
|
38
|
+
`drv_...` id first via that call).
|
|
39
|
+
|
|
40
|
+
## CLI
|
|
41
|
+
|
|
42
|
+
The CLI only operates on the account's **default** drive — for named/
|
|
43
|
+
per-client drives, use REST or MCP.
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
shiply drive ls [prefix] # list files (optionally under a prefix)
|
|
47
|
+
shiply drive put <file> [as-path] # stage + finalize a file into the default drive
|
|
48
|
+
shiply drive get <path> [out-file] # download; omit out-file to print to stdout
|
|
49
|
+
shiply drive rm <path> # delete a file
|
|
50
|
+
shiply drive publish [prefix] # snapshot the default drive (or a prefix) as a new live site
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## MCP tools
|
|
54
|
+
|
|
55
|
+
| Tool | Purpose |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `list_drives` | your drives (optional `clientId` filter) |
|
|
58
|
+
| `create_drive` | create a named drive (`name`, optional `client`) |
|
|
59
|
+
| `drive_list_files` | list files in a drive (`driveId` = `drv_...` or `"default"`, optional `prefix`) |
|
|
60
|
+
| `drive_put_file` | write a file inline (utf8 or base64, ≤2 MB — use the REST staged-upload flow above for bigger files) |
|
|
61
|
+
| `drive_delete_file` | delete a file from a drive |
|
|
62
|
+
| `publish_from_drive` | snapshot a drive (or a path prefix within it) into a new live site |
|
|
63
|
+
|
|
64
|
+
**Gap (intentional, tracked):** file download, drive delete, and the
|
|
65
|
+
share/assign-client family (`share`, `share/rotate`, `share/invite`,
|
|
66
|
+
`assign-client`) are REST-only today — there is no `drive_download`,
|
|
67
|
+
`delete_drive`, or share-management MCP tool yet. Use the REST endpoints
|
|
68
|
+
above from an MCP-only agent until parity lands.
|
|
69
|
+
|
|
70
|
+
Docs: https://shiply.now/docs/drives
|
|
@@ -127,6 +127,22 @@ the confirmed audience (unsubscribe link auto-added). `list_tests()` — all
|
|
|
127
127
|
tests for this key. `resend_confirmation({ testId, email })` — re-send the
|
|
128
128
|
opt-in to one address.
|
|
129
129
|
|
|
130
|
+
REST (Bearer, mirrors the MCP tools above):
|
|
131
|
+
|
|
132
|
+
| Endpoint | Action |
|
|
133
|
+
|---|---|
|
|
134
|
+
| `GET /api/v1/tests` | list your demand tests → `{tests}` |
|
|
135
|
+
| `POST /api/v1/tests` `{idea, copy:{headline, sub?, cta?}, price?, captureFields?, sendingDomainId?}` | create a test — deploys the capture page + provisions the confirmed-subscriber segment |
|
|
136
|
+
| `GET /api/v1/tests/{id}` | merged status object — same shape as `get_test_status` |
|
|
137
|
+
| `PATCH /api/v1/tests/{id}/branding` `{brandName?, logoUrl?, brandColor?, accentColor?, footerText?, replyTo?}` | customize the capture page's branding |
|
|
138
|
+
| `POST /api/v1/tests/{id}/broadcasts` `{subject, html, text?}` | email the confirmed audience — same as `send_broadcast` |
|
|
139
|
+
| `POST /api/v1/tests/suggest-copy` `{idea}` | AI-drafted `{headline, sub, cta}` from a one-line idea (MiniMax; 503 `service_unavailable` if no AI provider is configured) |
|
|
140
|
+
|
|
141
|
+
`list_tests` maps to `GET /api/v1/tests` above. `resend_confirmation` (re-send
|
|
142
|
+
the opt-in email to one address) is **MCP-only today** — no REST route exists
|
|
143
|
+
yet; use the MCP tool from a REST-only agent by proxying through an MCP
|
|
144
|
+
client, or ask for the confirmation link to be resent from the dashboard.
|
|
145
|
+
|
|
130
146
|
## Sending domains — outbound email on your domain
|
|
131
147
|
|
|
132
148
|
For agents that want shiply to send emails (demand-test broadcasts, project
|
|
@@ -140,6 +156,14 @@ to add), `verify_sending_domain`, `remove_sending_domain`.
|
|
|
140
156
|
REST: `GET/POST /api/v1/sending-domains ·
|
|
141
157
|
POST /api/v1/sending-domains/{id}/verify · DELETE /api/v1/sending-domains/{id}`
|
|
142
158
|
|
|
159
|
+
Auto-DNS shortcuts (skip the "copy these records to your registrar" step —
|
|
160
|
+
user supplies a scoped, never-stored Cloudflare API token for the domain's
|
|
161
|
+
zone): `POST /api/v1/sending-domains/{id}/auto-dns` `{provider:"cloudflare",
|
|
162
|
+
token}` adds the SPF/DKIM records automatically; `POST
|
|
163
|
+
/api/v1/sending-domains/{id}/email-routing` `{provider:"cloudflare", token}`
|
|
164
|
+
additionally turns on inbound Email Routing and binds the catch-all to
|
|
165
|
+
shiply's inbound worker. No MCP tools for either yet — REST only.
|
|
166
|
+
|
|
143
167
|
CLI: `shiply sending-domain ls · shiply sending-domain add <domain> ·
|
|
144
168
|
shiply sending-domain verify <id> · shiply sending-domain rm <id> --yes`
|
|
145
169
|
|
|
@@ -70,7 +70,9 @@ shiply publish <dir> --json # one machine-readable JSON line, no
|
|
|
70
70
|
- **`shiply verify <slug>`** prints a human report PLUS a stable machine marker
|
|
71
71
|
line `VERIFY status=LIVE http=200 ssl=valid thumb=…` (or `status=PENDING`).
|
|
72
72
|
Headless agents should parse that `VERIFY status=…` line — it's the
|
|
73
|
-
contract, like `SITE_READY` in `status`.
|
|
73
|
+
contract, like `SITE_READY` in `status`. REST: `GET /api/v1/sites/{slug}/verify`
|
|
74
|
+
(public, no auth — mirrors `site_status`) → `{status, ssl, http, thumbnailUrl,
|
|
75
|
+
consoleErrorsDeepLink}`. MCP: `verify_site`.
|
|
74
76
|
- **`shiply publish <dir> --as <name>`** gives a stable preview URL that the
|
|
75
77
|
next publish with the same `--as <name>` reuses — no more changing URLs or
|
|
76
78
|
orphaned scratch sites across iterations, independent of the source dir.
|
|
@@ -44,21 +44,36 @@ see [email.md](email.md).
|
|
|
44
44
|
|
|
45
45
|
## Access control — password or invite-only sites (paid)
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
CLI (preferred): `shiply access <slug>` prints the current policy (plus a
|
|
48
|
+
stable `ACCESS slug=… mode=…` marker line); set it with
|
|
49
|
+
`shiply access <slug> --password "..."`, `--restricted --email a@b.com
|
|
50
|
+
--domain example.com` (both flags repeatable — each set REPLACES the previous
|
|
51
|
+
lists), or `--public` to open it up.
|
|
52
|
+
REST: PATCH /api/v1/publishes/<slug>/access
|
|
48
53
|
with {"mode":"password","password":"..."} or {"mode":"restricted",
|
|
49
54
|
"allowedEmails":[...],"allowedDomains":[...]}, or set mode "public" to open it.
|
|
50
|
-
GET returns the policy (never the hash). MCP
|
|
55
|
+
GET returns the policy (never the hash). MCP tools: `get_site_access` (read),
|
|
56
|
+
`set_site_access` (write). Enforced
|
|
51
57
|
at the edge before any content/proxy/data is served; visitors get a 7-day
|
|
52
58
|
signed cookie; changing any setting signs current visitors out.
|
|
53
59
|
Docs: /docs/access-control
|
|
54
60
|
|
|
55
61
|
## Variables — encrypted per-user KV
|
|
56
62
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
CLI (preferred): `shiply variable ls [--reveal]`, `shiply variable set <NAME>
|
|
64
|
+
<value>` (or `--stdin`), `shiply variable rm <NAME> --yes`.
|
|
65
|
+
REST: GET/PUT /api/v1/variables {"name","value"}, DELETE
|
|
66
|
+
/api/v1/variables/{NAME}; GET ?reveal=1 returns plaintext values.
|
|
67
|
+
MCP: `list_variables`, `set_variable`, `delete_variable`. Referenced by proxy
|
|
68
|
+
routes (`${VAR}`) and injected into Workers as `env.<NAME>`. Supabase can be
|
|
69
|
+
connected from the dashboard and lands here as SUPABASE_URL + SUPABASE_ANON_KEY.
|
|
70
|
+
|
|
71
|
+
Expose (or stop exposing) a saved account variable to one specific site's
|
|
72
|
+
Worker env, independent of proxy routes: CLI `shiply variable attach <NAME>
|
|
73
|
+
--site <slug>` / `shiply variable detach <NAME> --site <slug>` (both
|
|
74
|
+
idempotent). REST: `POST /api/v1/variables/{name}/attach` `{slug}` / `POST
|
|
75
|
+
/api/v1/variables/{name}/detach` `{slug}`. MCP: `attach_variable`,
|
|
76
|
+
`detach_variable`, `list_site_variables`.
|
|
62
77
|
|
|
63
78
|
## Drives — private cloud storage (agent memory + assets)
|
|
64
79
|
|
|
@@ -66,6 +81,8 @@ Private storage for files/notes/context you don't want on a public site.
|
|
|
66
81
|
MCP tools: `list_drives`, `create_drive`, `drive_put_file` (driveId
|
|
67
82
|
"default", utf8/base64, ≤2 MB), `drive_list_files`, `drive_delete_file`,
|
|
68
83
|
`publish_from_drive` (snapshot a drive into a live site).
|
|
84
|
+
Full reference (REST staged uploads, sharing, client assignment, CLI):
|
|
85
|
+
[drives.md](drives.md).
|
|
69
86
|
|
|
70
87
|
## Path-mounting + public profile
|
|
71
88
|
|
|
@@ -73,7 +90,8 @@ MCP tools: `list_drives`, `create_drive`, `drive_put_file` (driveId
|
|
|
73
90
|
(host/docs → target).
|
|
74
91
|
- `set_profile` / `feature_site` (MCP) — stand up the user's public portfolio
|
|
75
92
|
at <handle>.shiply.now and feature a public site on shiply.now/explore.
|
|
76
|
-
- `export_account` (MCP)
|
|
93
|
+
- `export_account` (MCP) / `GET /api/v1/account/export` (REST) — JSON bundle
|
|
94
|
+
of the user's data (no secrets).
|
|
77
95
|
- Site metadata: `PATCH /api/v1/publish/<slug>/metadata`
|
|
78
96
|
{"title?","spaMode?","addedToProfile?"}.
|
|
79
97
|
|
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
---
|
|
2
|
-
type: reference
|
|
3
|
-
title: SSR frameworks
|
|
4
|
-
description: Deploy full server-side-rendered apps — SvelteKit, Astro, Qwik, the Nitro family (Nuxt, SolidStart, Analog, TanStack Start), React Router v7, Next.js via OpenNext, and Hono/raw Workers.
|
|
5
|
-
timestamp: 2026-07-04
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# SSR / server frameworks (live: every major JS framework)
|
|
9
|
-
|
|
10
|
-
Part of the shiply skill (see SKILL.md for publish basics). Requires sign-in +
|
|
11
|
-
Developer plan.
|
|
12
|
-
|
|
13
|
-
`shiply publish` auto-detects an SSR build and deploys the worker bundle with
|
|
14
|
-
`nodejs_compat`, serving static assets from the edge. Live and verified on prod:
|
|
15
|
-
SvelteKit (`@sveltejs/adapter-cloudflare`), Astro (`@astrojs/cloudflare`), Qwik
|
|
16
|
-
City, the Nitro family (Nuxt, SolidStart, Analog, TanStack Start), React Router
|
|
17
|
-
v7, and Next.js (via OpenNext) — plus wrangler workers (`wrangler.toml` with
|
|
18
|
-
`main` — Hono, itty-router, raw `fetch`). **Build first** (`npm run build`),
|
|
19
|
-
then `shiply publish .`. Force the static path with `--framework=<name>`, or
|
|
20
|
-
skip SSR detection entirely with `--no-ssr`.
|
|
21
|
-
|
|
22
|
-
Per-framework build setup:
|
|
23
|
-
|
|
24
|
-
- **SvelteKit** — `@sveltejs/adapter-cloudflare`, then `npm run build`,
|
|
25
|
-
`shiply publish .`
|
|
26
|
-
- **Astro** — `@astrojs/cloudflare` adapter, `npm run build`, `shiply publish .`
|
|
27
|
-
- **Qwik City** — `@builder.io/qwik-city` cloudflare-pages adapter,
|
|
28
|
-
`npm run build`, `shiply publish .`
|
|
29
|
-
- **Nitro family (Nuxt, SolidStart, Analog, TanStack Start)** — build with the
|
|
30
|
-
`cloudflare`(-module) Nitro preset, then `shiply publish .`
|
|
31
|
-
- **React Router v7** — framework mode (`@react-router/dev`), `react-router
|
|
32
|
-
build`, then `shiply publish .`
|
|
33
|
-
- **Next.js** — build via `@opennextjs/cloudflare` (OpenNext), then
|
|
34
|
-
`shiply publish .`. Plain SSR works today; **ISR / on-demand revalidate is
|
|
35
|
-
not live yet**, and Next 16 must build with `next build --webpack` (not
|
|
36
|
-
Turbopack). `shiply publish` runs a **PREFLIGHT** on Next source dirs: it
|
|
37
|
-
auto-fixes Turbopack build scripts, translates `vercel.json` crons to
|
|
38
|
-
`.shiply/crons.json`, and refuses to publish raw source with no worker
|
|
39
|
-
build — read its `FIX`/`WARN` lines, do what they say, re-run.
|
|
40
|
-
|
|
41
|
-
Publish output is self-describing — trust it over memory: finalize streams
|
|
42
|
-
per-phase progress lines, a failed worker deploy prints a structured `fix:`
|
|
43
|
-
line to execute verbatim, and after every worker deploy the server probes
|
|
44
|
-
the live site — a non-zero exit with a `runtime error:` line means
|
|
45
|
-
DEPLOYED BUT BROKEN (the actual worker exception + likely fix are printed,
|
|
46
|
-
e.g. a missing `shiply secret set`); fix the printed cause and republish.
|
|
47
|
-
- **Wrangler workers** — any repo with `wrangler.toml` declaring `main`
|
|
48
|
-
(Hono, itty-router, raw `fetch` handler) deploys as-is.
|
|
49
|
-
|
|
50
|
-
How serving works: the deployed worker receives every request; static assets
|
|
51
|
-
are tried first (the worker calls `env.ASSETS`, 200 = asset served from the
|
|
52
|
-
edge / 404 = your SSR handler runs). The worker gets the same bindings,
|
|
53
|
-
secrets, and crons as Functions — see [functions.md](functions.md). Bundle
|
|
54
|
-
cap 8 MB.
|
|
55
|
-
|
|
56
|
-
Plan gate: Free/Hobby get `402 payment_required` — upgrade at
|
|
57
|
-
https://shiply.now/dashboard/plan.
|
|
1
|
+
---
|
|
2
|
+
type: reference
|
|
3
|
+
title: SSR frameworks
|
|
4
|
+
description: Deploy full server-side-rendered apps — SvelteKit, Astro, Qwik, the Nitro family (Nuxt, SolidStart, Analog, TanStack Start), React Router v7, Next.js via OpenNext, and Hono/raw Workers.
|
|
5
|
+
timestamp: 2026-07-04
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# SSR / server frameworks (live: every major JS framework)
|
|
9
|
+
|
|
10
|
+
Part of the shiply skill (see SKILL.md for publish basics). Requires sign-in +
|
|
11
|
+
Developer plan.
|
|
12
|
+
|
|
13
|
+
`shiply publish` auto-detects an SSR build and deploys the worker bundle with
|
|
14
|
+
`nodejs_compat`, serving static assets from the edge. Live and verified on prod:
|
|
15
|
+
SvelteKit (`@sveltejs/adapter-cloudflare`), Astro (`@astrojs/cloudflare`), Qwik
|
|
16
|
+
City, the Nitro family (Nuxt, SolidStart, Analog, TanStack Start), React Router
|
|
17
|
+
v7, and Next.js (via OpenNext) — plus wrangler workers (`wrangler.toml` with
|
|
18
|
+
`main` — Hono, itty-router, raw `fetch`). **Build first** (`npm run build`),
|
|
19
|
+
then `shiply publish .`. Force the static path with `--framework=<name>`, or
|
|
20
|
+
skip SSR detection entirely with `--no-ssr`.
|
|
21
|
+
|
|
22
|
+
Per-framework build setup:
|
|
23
|
+
|
|
24
|
+
- **SvelteKit** — `@sveltejs/adapter-cloudflare`, then `npm run build`,
|
|
25
|
+
`shiply publish .`
|
|
26
|
+
- **Astro** — `@astrojs/cloudflare` adapter, `npm run build`, `shiply publish .`
|
|
27
|
+
- **Qwik City** — `@builder.io/qwik-city` cloudflare-pages adapter,
|
|
28
|
+
`npm run build`, `shiply publish .`
|
|
29
|
+
- **Nitro family (Nuxt, SolidStart, Analog, TanStack Start)** — build with the
|
|
30
|
+
`cloudflare`(-module) Nitro preset, then `shiply publish .`
|
|
31
|
+
- **React Router v7** — framework mode (`@react-router/dev`), `react-router
|
|
32
|
+
build`, then `shiply publish .`
|
|
33
|
+
- **Next.js** — build via `@opennextjs/cloudflare` (OpenNext), then
|
|
34
|
+
`shiply publish .`. Plain SSR works today; **ISR / on-demand revalidate is
|
|
35
|
+
not live yet**, and Next 16 must build with `next build --webpack` (not
|
|
36
|
+
Turbopack). `shiply publish` runs a **PREFLIGHT** on Next source dirs: it
|
|
37
|
+
auto-fixes Turbopack build scripts, translates `vercel.json` crons to
|
|
38
|
+
`.shiply/crons.json`, and refuses to publish raw source with no worker
|
|
39
|
+
build — read its `FIX`/`WARN` lines, do what they say, re-run.
|
|
40
|
+
|
|
41
|
+
Publish output is self-describing — trust it over memory: finalize streams
|
|
42
|
+
per-phase progress lines, a failed worker deploy prints a structured `fix:`
|
|
43
|
+
line to execute verbatim, and after every worker deploy the server probes
|
|
44
|
+
the live site — a non-zero exit with a `runtime error:` line means
|
|
45
|
+
DEPLOYED BUT BROKEN (the actual worker exception + likely fix are printed,
|
|
46
|
+
e.g. a missing `shiply secret set`); fix the printed cause and republish.
|
|
47
|
+
- **Wrangler workers** — any repo with `wrangler.toml` declaring `main`
|
|
48
|
+
(Hono, itty-router, raw `fetch` handler) deploys as-is.
|
|
49
|
+
|
|
50
|
+
How serving works: the deployed worker receives every request; static assets
|
|
51
|
+
are tried first (the worker calls `env.ASSETS`, 200 = asset served from the
|
|
52
|
+
edge / 404 = your SSR handler runs). The worker gets the same bindings,
|
|
53
|
+
secrets, and crons as Functions — see [functions.md](functions.md). Bundle
|
|
54
|
+
cap 8 MB.
|
|
55
|
+
|
|
56
|
+
Plan gate: Free/Hobby get `402 payment_required` — upgrade at
|
|
57
|
+
https://shiply.now/dashboard/plan.
|