Documentation Index
Fetch the complete documentation index at: https://docs.faces.app/llms.txt
Use this file to discover all available pages before exploring further.
new
Create a new blank project. Returns the projectSlug and editorUrl. Add slides with faces slides create + faces slides update. The project is created under the team your API key is scoped to (see Authentication).
Options:
| Flag | Description |
|---|
--name <text> | Display name for the new project (default: Untitled) |
--api-key <key> | API key override |
Output:
{
"projectId": "cm1abc123...",
"projectSlug": "xK9mP2qR",
"projectVersionId": "cm1ver456...",
"editorUrl": "https://faces.app/s/xK9mP2qR"
}
Examples:
faces new
faces new --name "Q4 Roadmap"
generate
Generate a new interactive presentation from a text prompt. Describe what you want (a pitch, portfolio, guide, or proposal) and Faces handles the content, animations, and layout.
faces generate --prompt "5-slide pitch deck about AI in healthcare"
Options:
| Flag | Description |
|---|
--prompt <text> | (required) Description of the project to generate |
--template <id> | Use an existing project as a template |
--wait | Wait for the project to finish generating |
--api-key <key> | API key override |
Output:
{
"jobId": "cm1abc123...",
"status": "processing",
"editorUrl": "https://faces.app/s/xK9mP2qR"
}
Examples:
# Basic generation
faces generate --prompt "Company intro deck with 3 slides"
# Using a template
faces generate --prompt "Same deck for fintech" --template cm1xyz789
# Wait for completion
faces generate --prompt "Team intro" --wait
status
Check the status of a generation job.
Options:
| Flag | Description |
|---|
--wait | Poll until the job completes or fails |
--api-key <key> | API key override |
Examples:
# Check once
faces status cm1abc123...
# Wait for completion
faces status cm1abc123... --wait
list
List your projects.
Options:
| Flag | Description |
|---|
--published | Only show published projects |
--limit <n> | Max results (default: 20, max: 100) |
--api-key <key> | API key override |
Examples:
faces list --published --limit 5
faces list | jq '.projects[].slug'
get
Get details of a specific project.
Examples:
faces get xK9mP2qR
faces get xK9mP2qR | jq '.publishedUrl'
slides list
List all slides in a project.
Examples:
faces slides list xK9mP2qR
faces slides list xK9mP2qR | jq '.slides[].id'
slides get
Read a slide’s source files (face.tsx, face.content.json, face.controls.json).
faces slides get <slug> <slide-id>
Examples:
faces slides get xK9mP2qR abc123
faces slides get xK9mP2qR abc123 | jq '.files["face.tsx"]'
slides create
Create a new empty slide. Returns the new slide ID.
faces slides create <slug> --name "Slide Name"
Options:
| Flag | Description |
|---|
--name <text> | (required) Display name for the new slide |
--after <slide-id> | Insert after this slide. Omit to append at the end |
--editing | Immediately show the loading gradient on the new slide. Call slides finish-editing when done |
--api-key <key> | API key override |
Examples:
faces slides create xK9mP2qR --name "Hero Section"
faces slides create xK9mP2qR --name "Features" --after abc123
faces slides create xK9mP2qR --name "Pricing" --editing
slides update
Update a slide’s source files. Only provided files are changed. The code is validated before saving — returns errors if it doesn’t compile.
faces slides update <slug> <slide-id> [options]
Options:
| Flag | Description |
|---|
--tsx <file> | Path to face.tsx file (or inline code) |
--content <file> | Path to face.content.json file (or inline JSON) |
--controls <file> | Path to face.controls.json file (or inline JSON) |
--api-key <key> | API key override |
Examples:
# Update the React component
faces slides update xK9mP2qR abc123 --tsx ./my-slide.tsx
# Update content and controls
faces slides update xK9mP2qR abc123 --content ./content.json --controls ./controls.json
# Update all three files
faces slides update xK9mP2qR abc123 --tsx ./face.tsx --content ./content.json --controls ./controls.json
slides start-editing
Show a loading indicator in the editor while editing a slide. Call before making changes, and always call finish-editing when done.
faces slides start-editing <slug> <slide-id>
Options:
| Flag | Description |
|---|
--api-key <key> | API key override |
slides finish-editing
Clear the loading indicator for a slide. Always call this after editing, even if the edit failed.
faces slides finish-editing <slug> <slide-id>
slides guide
Print the slide authoring reference — the same guide the MCP server and API return. Covers face.tsx structure, face.content.json block types, face.controls.json control types, typography, fonts, CSS, and code examples. Read this before writing slide code for the first time.
Options:
| Flag | Description |
|---|
--api-key <key> | API key override |
Examples:
# Save the guide to a file
faces slides guide | jq -r '.guide' > slide-guide.md
# Pipe directly into an agent prompt
faces slides guide | jq -r '.guide' | pbcopy
Slide file reference
Each slide consists of three files:
face.tsx — React component
import React from "react";
import { blocks } from "./face.content.json";
import { controls } from "./face.controls.json";
import { TextContent } from "@/components/ui/text-content";
import { Icon } from "@/components/ui/icon";
export default function HeroFace() {
return (
<div className="w-full h-full bg-background flex flex-col items-center justify-center p-16">
<Icon name={blocks.heroIcon.name} size={48} className="text-primary mb-6" />
<TextContent content={blocks.title.content} className="text-7xl font-bold text-center" />
<TextContent content={blocks.subtitle.content} className="text-2xl text-muted-foreground mt-4" />
</div>
);
}
Rules:
- Must default-export a React component
- Outer div must have
w-full h-full (canvas: 1920×1080 desktop, 720×1280 mobile)
- Use Tailwind CSS and container queries (
@sm:, @md:, @lg:, @xl:) instead of media queries
- Never hardcode text — store all user-visible text in face.content.json
- Can import any npm package (auto-resolved, no install needed)
- Available:
react, motion/react (Framer Motion), lucide-react, @radix-ui/*
- UI components:
TextContent from @/components/ui/text-content, Icon from @/components/ui/icon
face.content.json — editable content
{
"blocks": {
"heroIcon": { "type": "icon", "name": "sparkles" },
"title": { "type": "text", "content": "Welcome to <strong>Faces</strong>" },
"subtitle": { "type": "text", "content": "Build beautiful presentations" },
"logo": { "type": "image", "src": "https://example.com/logo.png" }
}
}
Block types:
text: { "type": "text", "content": "HTML string" } — render with <TextContent content={blocks.key.content} />
image: { "type": "image", "src": "url | null" } — render with <img src={blocks.key.src} />
icon: { "type": "icon", "name": "lucide-icon-name" } — render with <Icon name={blocks.key.name} />
table: { "type": "table", "columns": [...], "rows": [...] } — iterate with blocks.key.rows.map(...)
face.controls.json — editor controls
{
"controls": {
"titleSize": { "type": "selector", "options": ["Medium", "Large", "Extra Large"], "value": "Large" },
"showSubtitle": { "type": "switch", "value": true },
"spacing": { "type": "slider", "min": 16, "max": 96, "step": 8, "value": 48 }
}
}
Control types:
slider: { "type": "slider", "min": 0, "max": 100, "step": 1, "value": 50 }
switch: { "type": "switch", "value": true }
selector: { "type": "selector", "options": ["A", "B"], "value": "A" }
Access in face.tsx: controls.key.value
login
Sign in and store an API key.
Options:
| Flag | Description |
|---|
--team <slug-or-id> | Scope the API key to a specific team (default: your personal team) |
--api-url <url> | API base URL (default: FACES_API_URL or https://faces.app) |
Examples:
faces login
faces login --team acme
faces login --team clxxx...
Opens your browser to authenticate, then saves the key to ~/.config/faces/credentials.json. The --team value can be a team slug or team id (see GET /api/v1/teams). Omit --team to scope the key to your personal team.