Add a browsable mdBook developer guide under docs/dev-guide/ covering the full PiCloud v1.1.9 surface for developers building on the platform: - Guide: introduction, 10-minute quickstart, core concepts, writing scripts - Tutorials: 5 end-to-end example apps (URL shortener, webhook receiver, TODO API with auth, scheduled report, file-upload service) + feature matrix - SDK reference: kv/docs/files, pubsub/queue, http, email, users, secrets, invoke/retry/dead_letters, stdlib, ctx & events - HTTP API reference: every /api/v1 endpoint, auth, and capability - CLI reference: the `pic` client + the server admin recovery command - Config: every PICLOUD_* env var, capabilities & roles - Deployment: Docker Compose, bare binary, Caddy/TLS, production checklist - Operations: security, best practices, troubleshooting Every example was built and run against a live instance; SDK signatures, endpoint paths, and env vars were verified against source. Build the site with `mdbook serve docs/dev-guide`. A pointer is added to README. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2.6 KiB
Apps & domains
Apps are tenants; domains route hosts to apps. See Core concepts.
Apps
| Method & path | Capability | Notes |
|---|---|---|
GET /api/v1/admin/apps |
authenticated | lists apps the caller can see (members: only theirs) |
POST /api/v1/admin/apps |
InstanceCreateApp (owner/admin) |
create |
GET /api/v1/admin/apps/{id_or_slug} |
AppRead |
one app |
PATCH /api/v1/admin/apps/{id_or_slug} |
AppAdmin |
update name/description/slug |
DELETE /api/v1/admin/apps/{id_or_slug} |
AppAdmin |
delete (cascades scripts, routes, data) |
POST /api/v1/admin/apps/{id_or_slug}/slug:check |
AppAdmin |
{"new_slug":"…"} → {ok, conflict_kind?, current_app?, reason?} |
Create:
curl -X POST $PICLOUD/api/v1/admin/apps -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-d '{"slug":"demo","name":"Demo App","description":"…"}'
{"id":"41f42060-…","slug":"demo","name":"Demo App","description":null,
"created_at":"2026-…Z","updated_at":"2026-…Z"}
Slug rules: ^[a-z0-9][a-z0-9-]{0,62}$, and not one of the reserved words (new, api, admin,
apps, login, healthz, version, …). Renaming a slug records the old one for redirects; reclaim a
released slug with "force_takeover": true in the create/patch body.
Domains
A non-default app's routes only match once the app claims the request Host.
| Method & path | Capability |
|---|---|
GET /api/v1/admin/apps/{id_or_slug}/domains |
AppRead |
POST /api/v1/admin/apps/{id_or_slug}/domains |
AppManageDomains |
DELETE /api/v1/admin/apps/{id_or_slug}/domains/{domain_id} |
AppManageDomains |
curl -X POST $PICLOUD/api/v1/admin/apps/demo/domains -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"pattern":"demo.localhost"}'
{"id":"6ff04d56-…","app_id":"41f42060-…","pattern":"demo.localhost",
"shape":"exact","shape_key":"exact:demo.localhost","created_at":"2026-…Z"}
Pattern shapes (use {name}, never :name, in domains):
- exact —
app.example.com - wildcard —
*.example.com - parameterized —
{tenant}.example.com(the segment is captured into a route param)
The most specific claim wins. Claiming a host another app already holds (in the same shape) returns
409. The default app ships claiming localhost. Locally, claim something.localhost and test with
curl -H 'Host: something.localhost' $PICLOUD/....
CLI: pic apps create demo --name "Demo App", pic apps domains add demo demo.localhost,
pic apps ls, pic apps show demo.