Getting Started
Quick Start
Get your first Stackable extension running locally in minutes, then deploy it to the marketplace. This guide walks you through scaffolding, previewing, and publishing using the CLI.
Choosing your path
Stackable supports two authoring paths. Both produce the same kind of extension and ship to the same marketplace.
| AI Extension Studio | CLI (this guide) | |
|---|---|---|
| Best for | Prototyping, learning, quick iterations | Production extensions, team workflows |
| Code structure | Single file | Multi-file (surfaces/, components/, lib/) |
| Preview | Built-in live preview | Local dev server + Cloudflare tunnel |
| AI assistance | Sidekick chat + smart insertion | Skills, MCP server, and Claude Code plugin (see AI-Accelerated Development) |
| Version control | Auto-saved to cloud | Git-based |
| Deployment | Link to extension + deploy | CLI deploy command |
Both produce the same output — a Stackable extension that runs inside the embedding application via the same Remote DOM pipeline. This guide covers the CLI path. For Studio, see AI Extension Studio.
Prerequisites
- Node.js 22 or later
- pnpm (recommended) or npm
1. Create a New Extension
Scaffold a new extension project:
pnpm --config.dlx-cache-max-age=0 dlx @stackable-labs/cli-app-extension@latest create my-extension
cd my-extension
pnpm install
This creates a project with:
- A working extension with header, content, and footer surfaces
- A local preview host for development
- TypeScript configuration
- A manifest with default permissions and targets
2. Preview Your Extension
Run the Stackable CLI dev server from your project directory:
pnpm --config.dlx-cache-max-age=0 dlx @stackable-labs/cli-app-extension@latest dev
Note: This uses
pnpm dlxto run the Stackable CLI without installing it globally. The--config.dlx-cache-max-age=0flag ensures you always get the latest version.
The dev command:
- Starts a local Vite dev server for your extension with hot reload
- Creates a public Cloudflare tunnel to your local server
- Displays a query parameter you can use to preview your extension
Testing against your extension
The CLI outputs a query param like:
?_stackable_dev=ext-123%3Ahttps%3A%2F%2Fabc.trycloudflare.com
Append this to the host site's URL (the site or product where your extension is installed/authorized) to load your local extension instead of the production bundle. For example:
https://your-host-site.com/dashboard?_stackable_dev=ext-123%3Ahttps%3A%2F%2Fabc.trycloudflare.com
This override is browser-session only — no database changes, no shared state. Each developer gets isolated overrides. Changes made locally appear immediately in your extension via hot reload.
Use --no-tunnel if you only want to run the local Vite dev server without a tunnel.
3. Explore the Project
my-extension/
packages/
extension/
public/
manifest.json # Targets, permissions, allowed domains
src/
index.tsx # Entry point — createExtension bootstraps the runtime
store.ts # Shared state across surfaces
surfaces/ # One component per surface slot
Header.tsx
Content.tsx
Footer.tsx
components/ # Feature components used by surfaces
lib/ # API wrappers and utilities
preview/ # Local preview host — DO NOT MODIFY
4. Make Your First Change
Open packages/extension/src/surfaces/Content.tsx and modify the content:
import { Surface, ui } from '@stackable-labs/sdk-extension-react'
export const Content = () => (
<Surface id="slot.content">
<ui.Card>
<ui.CardContent>
<ui.Heading level={3}>Hello, Stackable!</ui.Heading>
<ui.Text>My first extension is working.</ui.Text>
</ui.CardContent>
</ui.Card>
</Surface>
)
Save the file — the preview updates automatically.
5. Add a Capability
To read host context data (customer info, etc.):
- Add the permission to
manifest.json:
{
"permissions": ["context:read"]
}
- Use it in a surface:
import { Surface, useContextData, ui } from '@stackable-labs/sdk-extension-react'
export const Content = () => {
const { loading, customerId } = useContextData()
if (loading) {
return (
<Surface id="slot.content">
<ui.Skeleton />
</Surface>
)
}
return (
<Surface id="slot.content">
<ui.Card>
<ui.CardContent>
<ui.Text>Customer: {customerId}</ui.Text>
</ui.CardContent>
</ui.Card>
</Surface>
)
}
6. Submit for review
When your extension is ready, open it in the Stackable admin dashboard, fill in the marketplace listing (icon, screenshots, description, tagline, support links), and submit for review. Most reviews complete within a few business days.
CLI
validateanddeploycommands are on the roadmap (see CLI Reference). Today, manifests are validated server-side during submission and via thevalidate_manifestMCP tool.
Next Steps
- Components — browse the full UI component catalog
- Capabilities — learn about data.query, data.fetch, and more
- Surfaces — understand surface types and layout slots
- Patterns — see common extension code patterns