sleek-design-mobile-apps

AI-powered mobile app design tool with REST API for creating projects, describing designs in plain language, and rendering screens. Supports high-level requests ("design a fitness app") and specific edits ("add a pricing section to this screen"); send natural language descriptions via chat messages and let the AI decide what to create or modify Requires Pro+ plan and API key with scoped permissions ( projects:read/write , chats:read/write , screenshots , components:read ) Async and sync modes available; async returns immediately with a run ID for polling, sync blocks up to 300 seconds Always screenshot newly created or updated screens after each chat run and deliver them to the user; combine all project screens into one screenshot when screens are created for the first time One active run per project at a time; retry failed requests safely using idempotency keys

INSTALLATION
npx skills add https://github.com/sleekdotdesign/agent-skills --skill sleek-design-mobile-apps
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

Designing with Sleek

[](https://sleek.design)

Overview

sleek.design is an AI-powered mobile app design tool. You interact with it via a REST API at /api/v1/* to create projects, describe what you want built in plain language, and get back rendered screens. All communication is standard HTTP with bearer token auth.

Base URL: https://sleek.design

Auth: Authorization: Bearer $SLEEK_API_KEY on every /api/v1/* request

Content-Type: application/json (requests and responses)

CORS: Enabled on all /api/v1/* endpoints

API docs: OpenAPI spec at https://sleek.design/api/v1/spec.json; browsable docs at https://sleek.design/api/v1/docs. Fetch the spec for any contract detail not covered here.

Prerequisites: API Key

Create API keys at https://sleek.design/dashboard/api-keys. The full key value is shown only once at creation. Store it in the SLEEK_API_KEY environment variable.

Required plan: Pro or higher (API access is gated)

Key scopes

ScopeWhat it unlocks
projects:readList / get projects
projects:writeCreate / delete projects
components:readList components in a project
chats:readGet chat run status
chats:writeSend chat messages
screenshotsRender component screenshots

Create a key with only the scopes needed for the task.

Security & Privacy

  • Single host: All requests go exclusively to https://sleek.design. No data is sent to third parties.
  • HTTPS only: All communication uses HTTPS. The API key is transmitted only in the Authorization header to Sleek endpoints.
  • Minimal scopes: Create API keys with only the scopes required for the task. Prefer short-lived or revocable keys.
  • Image URLs: When using imageUrls in chat messages, those URLs are fetched by Sleek's servers. Avoid passing URLs that contain sensitive content.

Designing

The full request/response shapes for every endpoint used below are in the [API reference](#quick-reference-all-endpoints).

1. Create a project

Create a project with POST /api/v1/projects if one doesn't exist yet. Derive a name from the request.

Each project has its own theme, style, and design system. If the user wants multiple design variations, create a separate project for each variation.

2. Send a chat message

Send the request with POST /api/v1/projects/:id/chat/messages. Sleek has its own AI that plans screen content, visual style, and layout: pass the user's request as-is and let it plan. Don't add details the user didn't ask for, and don't decompose the request into screens; send the full intent as a single message. If the user described specific screens and styling, include those. Sleek produces richer designs when given room to plan.

Seed a style with a reference: Sleek curates a catalog of design references. When the user wants a specific look or asks for style options, list them with GET /api/v1/references (each has a name and previewImageUrls you can show) and pass the chosen id as referenceId on the first message to a project, so its style guide seeds the whole design.

Identify your tool: always send source, the slug of the tool making the request. The Sleek editor uses it to show the user who is designing while the run streams. Recognized values: claude-code, claude, codex, chatgpt, cursor, openclaw. If your tool isn't listed, send a short kebab-case slug for it anyway (max 64 chars). Unrecognized values are fine and get a generic label.

Watch it live: runs render in the Sleek editor in real time. After sending the first message to a project, tell the user they can watch their screens being designed live in Sleek, and share the editor link: https://sleek.design/project/:projectId. Don't open a browser yourself unless the user asks.

Polling: chat messages are async by default: you get a runId and poll GET /api/v1/projects/:id/chat/runs/:runId. Start at 2s interval, back off to 5s after 10s, give up after 5 minutes. You can also use ?wait=true for a blocking call (up to 300s; falls back to polling if it times out with 202).

Editing a specific screen: use target.screenId to direct changes to the right screen (uses the screen ID from operations, not the component ID).

One run at a time: only one active run is allowed per project. If you get 409 CONFLICT, wait for the current run to complete before sending the next message. If the user changed their mind or a stale run is blocking the project, cancel it (see [Cancel Run](#chat-cancel-run)). Messages to different projects can run in parallel; use async polling (not ?wait=true) when running multiple projects concurrently.

Safe retries: add an idempotency-key header (≤255 chars) to replay-safe re-sends. The server returns the existing run rather than creating a duplicate.

3. Show the results

After every chat run that produces screen_created or screen_updated operations, take screenshots and show them to the user using POST /api/v1/screenshots. The step is done only when the user has seen a screenshot of every screen the run created or updated; never complete a run silently.

  • New screens: one screenshot per screen + one combined screenshot of all screens in the project.
  • Updated screens: one screenshot per affected screen.

Use background: "transparent" unless the user explicitly requests a specific background color.

Save screenshots in the project directory (not a temporary folder) so the user can easily view them.

Implementing Designs

When the user wants to implement the designs in code (not just preview them), always fetch the component HTML code. Do not rely on screenshots alone.

Use GET /api/v1/projects/:id/components/:componentId to fetch each screen's code. The componentId comes from the chat run's result.operations.

Component code can be large. When saving it to files, avoid writing the content through your text output: it's slow and wastes tokens. Instead, use shell commands to fetch the API response and write it directly to disk (e.g., pipe the response body into a file).

Which version to use

Each component carries a versions[] array and an activeVersion: number. **By default, use the entry where versions[i].version === activeVersion**: that's the code currently shown in Sleek.

If the user's prompt pins specific versions, follow those instead (see [Pinned versions](#pinned-versions) below).

Pinned versions

The user's prompt may include a pin block telling you to implement specific historical versions instead of the current ones, like this:

... at this exact state instead of the project's current version:

- component cmp_abc: version ver_001

- component cmp_def: version ver_002

- theme thm_ghi: version ver_003

When you see a pin block, implement those exact versions instead of activeVersion. Components not named in the pin block continue to use their active version. Theme IDs surface only inside pin blocks; this skill exposes no separate endpoint to enumerate them.

#### Fetching the right code

For each pinned component, find the entry in versions[] where versions[i].id matches the given version id (e.g. ver_001) and use its code. Do not fall back to activeVersion for pinned components.

#### Screenshots of pinned versions

Pass componentVersionOverrides and themeVersionOverrides to POST /api/v1/screenshots:

{

  "componentIds": ["cmp_abc"],

  "projectId": "proj_xyz",

  "componentVersionOverrides": { "cmp_abc": "ver_001" },

  "themeVersionOverrides": { "thm_ghi": "ver_003" }

}

Keys are component / theme public ids; values are the corresponding versions[i].id. Entities missing from a map fall back to their active version. Include the override maps whenever the prompt specified pinned versions.

HTML prototypes

The component code is a complete HTML document. Save it directly to a .html file. No build step needed.

Native frameworks (React Native, SwiftUI, etc.)

Use both the HTML code and the screenshots together:

  • HTML code is the implementation reference: it contains the exact structure, layout, styling, colors, spacing, content, image URLs, and icon names.
  • Screenshots are the visual target: use them to verify your implementation matches the intended look.

The HTML tells you how to build it; the screenshot tells you what it should look like.

#### Icons

Sleek uses Iconify icons in the format prefix:name (e.g., solar:heart-bold, material-symbols:search-rounded, lucide:settings). The most common sets are Solar, Hugeicons, Material Symbols and MDI.

Use the exact icons from the HTML code. Do not substitute with a different icon set. Matching icons is important for design fidelity.

When implementing icons:

-

Check if the project already has an icon system that supports the same sets Sleek uses (Solar, Hugeicons, Material Symbols, MDI). If so, use it. Note: @expo/vector-icons does not support these sets, so do not use it as a substitute.

-

Otherwise, fetch the SVGs from the Iconify API and embed them in the code:

GET https://api.iconify.design/{prefix}/{name}.svg

Example: https://api.iconify.design/solar/heart-bold.svg

Collect all icon names from the HTML, fetch their SVGs, and save them as static assets or string constants in the codebase. For React Native / Expo, render them with react-native-svg's SvgXml component, which works in Expo Go with no additional native dependencies.

#### Fonts

The HTML includes Google Fonts via <link> tags in the <head>. Use the same fonts and weights when implementing in a native framework. Extract the font family names and weights from the <link> tags.

#### Navigation

The designs may include navigation elements like tab bars and headers. Update the project's navigation styling and structure to match the designs. Don't just implement the screen content while leaving the default navigation untouched.

Quick Reference: All Endpoints

MethodPathScopeDescription
GET/api/v1/projectsprojects:readList projects
POST/api/v1/projectsprojects:writeCreate project
GET/api/v1/projects/:idprojects:readGet project
DELETE/api/v1/projects/:idprojects:writeDelete project
GET/api/v1/projects/:id/componentscomponents:readList components
GET/api/v1/projects/:id/components/:componentIdcomponents:readGet component
GET/api/v1/referencesany valid keyList references
POST/api/v1/projects/:id/chat/messageschats:writeSend chat message
GET/api/v1/projects/:id/chat/runs/:runIdchats:readPoll run status
POST/api/v1/projects/:id/chat/runs/:runId/cancelchats:writeCancel run
POST/api/v1/screenshotsscreenshotsRender screenshot

Endpoints

Projects

#### List projects

GET /api/v1/projects?limit=50&offset=0

Authorization: Bearer $SLEEK_API_KEY

Response 200:

{

  "data": [

    {

      "id": "proj_abc",

      "name": "My App",

      "slug": "my-app",

      "createdAt": "2026-01-01T00:00:00Z",

      "updatedAt": "..."

    }

  ],

  "pagination": { "total": 12, "limit": 50, "offset": 0 }

}

#### Create project

POST /api/v1/projects

Authorization: Bearer $SLEEK_API_KEY

Content-Type: application/json

{ "name": "My New App" }

Response 201: same shape as a single project.

#### Get / Delete project

GET    /api/v1/projects/:projectId

DELETE /api/v1/projects/:projectId   → 204 No Content

Components

#### List components

GET /api/v1/projects/:projectId/components?limit=50&offset=0

Authorization: Bearer $SLEEK_API_KEY

Both list and get accept an optional inlineIcons query param (default false). When omitted, icons render as <iconify-icon> web components and the HTML pulls in the Iconify script, so leave it off by default. Pass ?inlineIcons=true only when the consumer needs self-contained SVGs in the HTML (for example, importing into tools that don't run scripts).

Response 200:

{

  "data": [

    {

      "id": "cmp_xyz",

      "name": "Hero Section",

      "activeVersion": 3,

      "versions": [

        {

          "id": "ver_001",

          "version": 1,

          "code": "<!DOCTYPE html>...</html>",

          "createdAt": "..."

        }

      ],

      "createdAt": "...",

      "updatedAt": "..."

    }

  ],

  "pagination": { "total": 5, "limit": 50, "offset": 0 }

}

#### Get component

Fetches a single component by ID. Use this when you need the code for a specific screen (e.g., after a chat run returns a componentId in its operations).

GET /api/v1/projects/:projectId/components/:componentId

Authorization: Bearer $SLEEK_API_KEY

Response 200: { "data": ... } with a single component in the same shape as a list item.

References

References are curated design styles from featured Sleek projects. They are world-readable: any valid API key can list them, no scope needed.

GET /api/v1/references?limit=50&offset=0

Authorization: Bearer $SLEEK_API_KEY

Response 200:

{

  "data": [

    {

      "id": "proj_ref1",

      "name": "Ember Fitness",

      "previewImageUrls": ["https://.../screenshot.png"]

    }

  ],

  "pagination": { "total": 44, "limit": 50, "offset": 0 }

}

To use one, pass its id as referenceId on [Send Message](#chat-send-message).

Chat: Send Message

This is the core action: describe what you want in message.text and the AI creates or modifies screens.

POST /api/v1/projects/:projectId/chat/messages?wait=false

Authorization: Bearer $SLEEK_API_KEY

Content-Type: application/json

idempotency-key: <optional, max 255 chars>

{

  "message": { "text": "Add a pricing section with three tiers" },

  "source": "claude-code",

  "imageUrls": ["https://example.com/ref.png"],

  "target": { "screenId": "scr_abc" },

  "referenceId": "proj_ref1"

}
FieldRequiredNotes
message.textYes1+ chars, trimmed
sourceYesSlug of the tool sending the request (see [step 2 of Designing](#2-send-a-chat-message))
imageUrlsNoHTTPS URLs only; included as visual context
target.screenIdNoEdit a specific screen using its screenId (not componentId); omit to let AI decide
referenceIdNoSeed the design style from a reference (see [References](#references)); invalid id → 400
?wait=true/falseNoSync wait mode (default: false)
idempotency-key headerNoReplay-safe re-sends

#### Response: async (default, wait=false )

Status 202 Accepted. result and error are absent until the run reaches a terminal state.

{

  "data": {

    "runId": "run_111",

    "status": "queued",

    "statusUrl": "/api/v1/projects/proj_abc/chat/runs/run_111"

  }

}

#### Response: sync ( wait=true )

Blocks up to 300 seconds. Returns 200 when completed, 202 if timed out.

{

  "data": {

    "runId": "run_111",

    "status": "completed",

    "statusUrl": "...",

    "result": {

      "assistantText": "I added a pricing section with...",

      "operations": [

        {

          "type": "screen_created",

          "screenId": "scr_xyz",

          "screenName": "Pricing",

          "componentId": "cmp_xyz"

        },

        {

          "type": "screen_updated",

          "screenId": "scr_abc",

          "componentId": "cmp_abc"

        },

        { "type": "theme_updated" }

      ]

    }

  }

}

Chat: Poll Run Status

Use this after async send to check progress.

GET /api/v1/projects/:projectId/chat/runs/:runId

Authorization: Bearer $SLEEK_API_KEY

The response has the same data shape as send message: result is present when completed, error when failed:

{

  "data": {

    "runId": "run_111",

    "status": "failed",

    "statusUrl": "...",

    "error": { "code": "execution_failed", "message": "..." }

  }

}

Run status lifecycle: queuedrunningcompleted | failed

Chat: Cancel Run

POST /api/v1/projects/:projectId/chat/runs/:runId/cancel

Authorization: Bearer $SLEEK_API_KEY

Marks a queued or running run as failed with error code cancelled and returns the updated run; already-finished runs are returned unchanged. Use it when the user changes their mind mid-run or a stale run is blocking the project with 409 CONFLICT.

Screenshots

Takes a snapshot of one or more rendered components.

POST /api/v1/screenshots

Authorization: Bearer $SLEEK_API_KEY

Content-Type: application/json

{

  "componentIds": ["cmp_xyz", "cmp_abc"],

  "projectId": "proj_abc",

  "format": "png",

  "scale": 2,

  "gap": 40,

  "padding": 40,

  "background": "transparent"

}
FieldDefaultNotes
formatpngpng or webp
scale21–3 (device pixel ratio)
gap40Pixels between components
padding40Uniform padding on all sides
paddingX(optional)Horizontal padding; overrides padding for left/right when provided
paddingY(optional)Vertical padding; overrides padding for top/bottom when provided
paddingTop(optional)Top padding; overrides paddingY when provided
paddingRight(optional)Right padding; overrides paddingX when provided
paddingBottom(optional)Bottom padding; overrides paddingY when provided
paddingLeft(optional)Left padding; overrides paddingX when provided
backgroundtransparentAny CSS color (hex, named, transparent)
showDotsfalseOverlay a subtle dot grid on the background
radius48Squircle corner radius per component in pixels (integer ≥ 0); pass 0 for sharp corners
componentVersionOverrides(optional)Map of componentIdversions[i].id to render at a pinned version instead of activeVersion (see [Pinned versions](#pinned-versions))
themeVersionOverrides(optional)Map of themeIdversions[i].id to render with a pinned theme version (see [Pinned versions](#pinned-versions))

Padding resolves with a cascade: per-side → axis → uniform. For example, paddingTop falls back to paddingY, which falls back to padding. So { "padding": 20, "paddingX": 10, "paddingLeft": 5 } gives top/bottom 20px, right 10px, left 5px.

When showDots is true, a dot pattern is drawn over the background color. The dots automatically adapt to the background: dark backgrounds get light dots, light backgrounds get dark dots. This has no effect when background is "transparent".

Response: raw binary image/png or image/webp with Content-Disposition: attachment.

Error Shapes

{ "code": "UNAUTHORIZED", "message": "..." }
HTTPCodeWhen
401UNAUTHORIZEDMissing/invalid/expired API key
403FORBIDDENValid key, wrong scope or plan
404NOT_FOUNDResource doesn't exist
400BAD_REQUESTValidation failure
409CONFLICTAnother run is active for this project
500INTERNAL_SERVER_ERRORServer error

Chat run-level errors (inside data.error):

CodeMeaning
out_of_creditsOrganization has no credits left
execution_failedAI execution error
cancelledRun cancelled via the cancel endpoint

Pagination

All list endpoints accept limit (1–100, default 50) and offset (≥0). The response always includes pagination.total so you can page through all results.

GET /api/v1/projects?limit=10&offset=20

Common Mistakes

MistakeFix
Omitting source on chat messagesAlways send source so the run is attributed in the Sleek editor
Using wait=true on long generationsIt blocks 300s max; have a fallback to polling for 202 response
Assuming result is present on 202result is absent until status is completed
Using screenId as componentIds in screenshotsscreenId and componentId are different; always use componentId from operations for screenshots
Confusing versions[i].version (number) with versions[i].id (string)When resolving pinned versions, match by id (e.g. ver_001); version is the numeric index
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card