Agent-skill-layerproof themes
Public API theme management (X-API-KEY). List, get, save, update, delete, generate, regenerate, apply, unapply. PublicThemeController (/api/v2/themes).
git clone https://github.com/compilet-dev/agent-skill-layerproof
T=$(mktemp -d) && git clone --depth=1 https://github.com/compilet-dev/agent-skill-layerproof "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/themes" ~/.claude/skills/compilet-dev-agent-skill-layerproof-themes && rm -rf "$T"
skills/themes/SKILL.mdSkill: Theme Management
Description
Themes define visual styling for slides. This skill documents the public API at
/api/v2/themes (PublicThemeController). Authenticate with X-API-KEY header.
TypeScript types (request / response)
Mirrors
PublicThemeController (/api/v2/themes) data classes.
// --- List Themes (GET) --- // Query: offset (default 0), limit (default 20), search (optional) type PublicThemeListResponse = { data: PublicThemeResponse[]; total: number; offset: number; limit: number; }; // --- Get Theme By ID (GET) --- type PublicThemeResponse = { id: string; name: string; description: string | null; visibility: string; // "PRIVATE" | "SYSTEM" | "SHARED" preview_url: string; created_at: string; // ISO 8601 updated_at: string; // ISO 8601 }; // --- Generate Theme (POST) — async --- type PublicGenerateThemeRequest = { prompt: string; // required, max 5000 chars project_id?: string | null; // optional THEME project UUID; if omitted, a project is created automatically }; type PublicGenerateThemeResponse = { activity_id: string; // UUID – poll GET /api/v2/jobs/{activity_id} theme_id: string; // UUID }; // --- Apply Theme (POST) --- type PublicApplyThemeRequest = { slide_deck_id: string; // UUID, required theme_id: string; // UUID, required regenerate_slides?: boolean; // default false; if true, triggers batch image regeneration – poll activity_id }; type PublicApplyThemeResponse = { theme_id: string; theme_name: string; slide_deck_id: string; applied: boolean; // true when applied successfully activity_id: string | null; // set when regenerate_slides is true – poll GET /api/v2/jobs/{activity_id} }; // --- Save theme (POST /api/v2/themes) — 201 --- type PublicSaveThemeRequest = { name: string; // required, max 256 visual_style_description: string; // required, max 5000 preview_s3_key: string; // required — S3 key of preview image description?: string | null; // max 1000 source_prompt?: string | null; source_project_id?: string | null; tags?: string[] | null; }; // --- Update theme (PUT /{theme_id}) --- type PublicUpdateThemeRequest = { name?: string | null; description?: string | null; tags?: string[] | null; visual_style_description?: string | null; }; // --- Regenerate theme (POST /{theme_id}/regenerate) — 202 --- type PublicRegenerateThemeRequest = { project_id: string; // UUID — project whose working dir is used adjustment_prompt: string; reference_image_paths?: string[] | null; preview_only?: boolean; }; type PublicRegenerateThemeResponse = { activity_id: string; theme_id: string; live_object_id: string; }; // --- Unapply (POST /unapply) --- type PublicUnapplyThemeRequest = { project_id: string; slide_deck_id: string; };
List Themes
Query:
offset (default 0), limit (default 20), search (optional). Response: PublicThemeListResponse.
curl "$LAYERPROOF_BASE_URL/api/v2/themes?offset=0&limit=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY"
Get Theme By ID
Response:
PublicThemeResponse.
curl "$LAYERPROOF_BASE_URL/api/v2/themes/<theme_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY"
Generate Theme
Request body:
PublicGenerateThemeRequest. Response (202): PublicGenerateThemeResponse.
Only
prompt is required. Optional project_id uses an existing THEME project; if omitted, one is created automatically. Poll GET /api/v2/jobs/{activityId} for status.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/generate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"prompt":"Clean, minimal style with SF Pro"}'
With optional
project_id:
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/generate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"prompt":"Clean, minimal style","project_id":"<theme_project_uuid>"}'
Apply Theme
Request body:
PublicApplyThemeRequest. Response: PublicApplyThemeResponse.
Theme and slide deck are specified in the body. When
regenerate_slides is true, poll GET /api/v2/jobs/{activityId} for batch image regeneration status.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/apply" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"slide_deck_id":"<slide_deck_uuid>","theme_id":"<theme_uuid>"}'
With slide regeneration:
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/apply" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"slide_deck_id":"<slide_deck_uuid>","theme_id":"<theme_uuid>","regenerate_slides":true}'
Save Theme (manual)
Creates a saved private theme. Requires
visual_style_description and preview_s3_key (upload preview via project/public files first). Response (201): PublicThemeResponse.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"My brand","visual_style_description":"Minimal dark UI, rounded cards","preview_s3_key":"<s3_key>"}'
Update Theme
Request body:
PublicUpdateThemeRequest. Response: PublicThemeResponse.
curl -X PUT "$LAYERPROOF_BASE_URL/api/v2/themes/<theme_id>" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"name":"Renamed theme"}'
Delete Theme
Soft-deletes a user-owned theme. Response: 204 No Content.
curl -X DELETE "$LAYERPROOF_BASE_URL/api/v2/themes/<theme_id>" \ -H "X-API-KEY: $LAYERPROOF_API_KEY"
Regenerate Theme (async)
Request body:
PublicRegenerateThemeRequest. Response (202): PublicRegenerateThemeResponse. Poll GET /api/v2/jobs/{activity_id}.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/<theme_id>/regenerate" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"project_id":"<project_uuid>","adjustment_prompt":"More contrast, warmer palette"}'
Unapply Theme from Slide Deck
Removes applied theme from a deck. Request body:
PublicUnapplyThemeRequest. Response: 204 No Content.
curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/unapply" \ -H "Content-Type: application/json" \ -H "X-API-KEY: $LAYERPROOF_API_KEY" \ -d '{"project_id":"<project_uuid>","slide_deck_id":"<slide_deck_uuid>"}'
List My Themes (by user)
Query:
offset, limit, optional visibility (PRIVATE | SYSTEM | SHARED), optional search. Response: PublicThemeListResponse.
curl "$LAYERPROOF_BASE_URL/api/v2/themes/by-user-id?offset=0&limit=20" \ -H "X-API-KEY: $LAYERPROOF_API_KEY"
Agent behavior
When the user asks to work with themes (list, get, generate, apply), do the following.
1. Choose the right endpoint
| User intent | Endpoint | Method |
|---|---|---|
| List/browse themes, search themes | | GET |
| Get one theme by ID | | GET |
| Save a theme manually | | POST |
| Update theme metadata | | PUT |
| Delete theme | | DELETE |
| Generate theme from prompt (async) | | POST |
| Regenerate / adjust theme (async) | | POST |
| Apply a theme to a slide deck | | POST |
| Unapply theme from deck | | POST |
| List current user’s themes | | GET |
2. Build and run the request
Step 1 — Check environment variables first. Before running any curl command, verify both
LAYERPROOF_BASE_URL and LAYERPROOF_API_KEY are set on the user's machine:
if [[ -z "${LAYERPROOF_BASE_URL}" ]]; then echo "ERROR: LAYERPROOF_BASE_URL is not set." return 1 fi if [[ -z "${LAYERPROOF_API_KEY}" ]]; then echo "ERROR: LAYERPROOF_API_KEY is not set." return 1 fi
If running from a project directory with a
.env.local file, load it first:
if [[ -f .env.local ]]; then set -a source .env.local set +a fi
Step 2 — Auth: Every request must include
X-API-KEY: $LAYERPROOF_API_KEY. Read LAYERPROOF_BASE_URL and LAYERPROOF_API_KEY from the environment; if missing, tell the user to set them.
Step 3 — GET: Build curl with the chosen path and query params (offset, limit, search for list). Run the curl and show the result.
Step 4 — POST: Build a JSON body from the user's input (prompt, theme ID, slide deck ID, etc.). Use -X POST, -H "Content-Type: application/json", and -d '...'. Run the curl and show the result.
3. After generate or apply (with regeneration)
- Generate theme: Response includes
andactivity_id
. Tell the user the theme was started and givetheme_id
. Optionally polltheme_id
untilGET $LAYERPROOF_BASE_URL/api/v2/jobs/<activity_id>
isstatus
orDONE
, then report outcome.CANCELED - Apply theme with
: Response may includeregenerate_slides: true
. If present, tell the user regeneration was started and optionally pollactivity_id
for status.GET .../api/v2/jobs/<activity_id>
4. Response handling
- Always show the raw JSON response in a JSON code block; do not convert to a table.
- If the response contains a URL for an image (e.g.
), show the image and the JSON.preview_url - On error (4xx/5xx), show the response body and status code; suggest fixing missing/invalid API key, IDs, or request body.
5. Example workflows
Workflow A — User: "Generate a theme with prompt: minimal dark mode."
- Choose
.POST /api/v2/themes/generate - Build body:
.{"prompt":"minimal dark mode"} - Run:
.curl -X POST "$LAYERPROOF_BASE_URL/api/v2/themes/generate" -H "Content-Type: application/json" -H "X-API-KEY: $LAYERPROOF_API_KEY" -d '{"prompt":"minimal dark mode"}' - Show the JSON response; if it contains
, mention they can pollactivity_id
for status and use/api/v2/jobs/{activityId}
once done.theme_id
Workflow B — User: "List themes, generate a new 'corporate blue' theme, wait for it to finish, then apply it to my slide deck and regenerate slides."
- GET
with optional/api/v2/themes
,limit
,offset
; show list. User may pick existing or request new.search - POST
with/api/v2/themes/generate
; capture{"prompt":"corporate blue"}
andactivity_id
.theme_id - Poll
until status is DONE (or CANCELED). If DONE, theme is ready; if failed, reportGET /api/v2/jobs/{activity_id}
.failure_reason - Resolve projectId and slideDeckId (projects + slide-deck). POST or PUT the slide-deck theme/settings endpoint with
(e.g. PUTtheme_id
with.../slide-deck/.../settings
).{"theme_id":"<theme_id>"} - Use POST
with/api/v2/themes/apply
if you want slide images regenerated; captureregenerate_slides: true
and poll jobs until DONE. Otherwise apply withactivity_id
or omit.regenerate_slides: false
Workflow C — User: "I have a theme ID; apply it to deck X and only update the look (no slide regeneration)."
- POST
with/api/v2/themes/apply
(omit{"slide_deck_id":"<slide_deck_uuid>","theme_id":"<theme_uuid>"}
or setregenerate_slides
).false - Confirm with GET deck; no job polling needed unless
was true.regenerate_slides
Response format (required)
- (if response contains url to show image) please show image and show json response instead of table
- Always show the raw JSON response (verbatim) in a JSON code block.
- If the response contains a URL for an image, render/show the image and also show the JSON response (do not convert to a table).