Building a guide¶
Guides are interactive, step-based learning content built from a ZIP package of Markdown and assets. PlusPlus renders the package into a step-by-step codelab asynchronously. The upload mirrors native videos: request a URL, PUT the ZIP, poll until ready.
Flow at a glance¶
sequenceDiagram
participant Your app
participant PlusPlus API
participant Storage
Your app->>PlusPlus API: POST /guides/uploads/ { name }
PlusPlus API-->>Your app: 201 { upload_id, upload_url, guide_id }
Your app->>Storage: PUT (application/zip)
loop until ready or errored
Your app->>PlusPlus API: GET /guides/uploads/{upload_id}/status/
PlusPlus API-->>Your app: 200 { status, launch_url }
end
1. Request an upload URL¶
Two modes:
- Create-and-upload — pass
name. PlusPlus creates a hidden guide and binds an upload URL to it. It auto-unhides once processing succeeds. - Attach to existing — pass
guide_id. The new package replaces the active version; the guide's existingis_hiddenis preserved.
curl -X POST https://acme.plusplus.app/api/v2/guides/uploads/ \
-H "Authorization: Bearer pp_your_token_here" \
-H "Content-Type: application/json" \
-d '{ "name": "Setting up your dev environment" }'
{
"upload_id": "upl_guide_abc",
"upload_url": "https://uploads.plusplus.app/guides/…",
"guide_id": "01HXYDBKW5V2H6F3M8R9N0Q2YP",
"expires_at": "2026-04-29T13:00:00Z",
"status": "awaiting_upload"
}
2. Upload the package¶
The presigned URL is scoped to application/zip — send exactly that content type:
3. Poll until ready¶
curl https://acme.plusplus.app/api/v2/guides/uploads/upl_guide_abc/status/ \
-H "Authorization: Bearer pp_your_token_here"
{
"upload_id": "upl_guide_abc",
"status": "ready",
"launch_url": "https://acme.plusplus.app/guides/dev-env-setup/"
}
status |
Meaning |
|---|---|
awaiting_upload |
URL issued; storage hasn't received the ZIP. |
processing |
Uploaded; PlusPlus is extracting and rendering (seconds to a minute). |
ready |
Done. launch_url is populated. |
errored |
Processing failed. Check error_message and upload a new package to retry. |
There's no separate confirm call — a single polling loop drives the whole flow. Poll every 3–5 seconds.
Package shape¶
A guide package is a ZIP whose root contains exactly one Markdown file (.md, not named README.md), optionally with image assets and a custom style.css. PlusPlus uses the claat tool to render it into a step-based codelab. The most common errored causes are a missing Markdown file or an invalid ZIP structure — surface error_message to your users.
Re-uploading¶
To replace a guide's contents, request a fresh upload URL with guide_id mode and upload again. Learner progress is preserved across re-uploads unless the section structure changes substantially.
Common pitfalls¶
- Wrong content type on the
PUT. The presigned URL is bound toapplication/zip. Sending anything else fails the upload. - Multiple Markdown files in the ZIP root. Exactly one is required.
- Expecting auto-publish on re-upload. Create-and-upload guides auto-unhide;
guide_idre-uploads preserve whatever visibility you'd set.