Build with Altask
The component library, REST API, webhooks, and embed snippets for shipping marketing sites that look like product. Less plumbing, more shipping.
Quickstart
Three minutes from a clean install to a deployed page. Pick your runtime — the snippet stays the same.
// 1 · install npm install @altask/sdk // 2 · authenticate import { Altask } from "@altask/sdk"; const client = new Altask({ token: process.env.ALTASK_KEY }); // 3 · ship await client.sites.deploy({ id: "site_8aL2k9X" });
# 1 · install pip install altask # 2 · authenticate from altask import Altask client = Altask(token=os.environ["ALTASK_KEY"]) # 3 · ship client.sites.deploy(id="site_8aL2k9X")
# deploy a site curl -X POST https://api.altask.dev/v1/sites/site_8aL2k9X/deploys \ -H "Authorization: Bearer $ALTASK_KEY"
Pin the SDK to a major version (^3.0) so minor releases roll in without breaking your build. Breaking changes only ship behind a new major.
SDK install
Install the Altask SDK with your package manager of choice. The same client supports server, edge, and worker runtimes.
npm install @altask/sdk @altask/components
pnpm add @altask/sdk @altask/components
yarn add @altask/sdk @altask/components
bun add @altask/sdk @altask/components
| Package | Description | Size (gz) |
|---|---|---|
@altask/sdk | REST client + Webhook helpers | 4.8 KB |
@altask/components | React components used by the editor | 21 KB |
@altask/cli | CLI for local dev, preview, deploy | — |
Authentication
The Altask API uses Bearer tokens. Generate keys in Dashboard → Settings → API keys. Tokens scope to a single workspace and rotate on demand.
Server keys
Use for backend calls only. Full read/write scope. Treat as a secret.
Public keys
Embed in client code. Read-only, scoped per origin. Rotate freely.
# every request curl https://api.altask.dev/v1/me \ -H "Authorization: Bearer $ALTASK_KEY" # response { "workspace": "acme", "plan": "pro", "scopes": ["sites:read", "sites:write"] }
<Hero/> component
Component
The Hero is the headline-and-CTA block at the top of most marketing pages. It accepts a title, subtitle, and call-to-action; switch variant for a centered or split layout.
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | — | Headline text. Required. |
subtitle | string | — | Supporting copy beneath the headline. |
cta | { label, href } | — | Primary call-to-action. |
secondaryCta | { label, href } | — | Optional secondary button. |
variant | "centered" | "split" | "centered" | Layout style. |
theme | "light" | "dark" | "light" | Color theme override. |
media | { src, alt } | — | Image rendered for the split variant. |
import { Hero } from "@altask/components"; export default function Page() { return ( <Hero title="Build websites visually" subtitle="No code. Full control." cta={{ label: "Start free", href: "/editor" }} variant="centered" /> ); }
<Pricing/> component
Component
Render a pricing table with monthly/yearly toggle, feature lists, and an optional highlighted plan. Plans are passed as an array; the order on the page matches the order in the array.
| Prop | Type | Default | Description |
|---|---|---|---|
plans | Plan[] | — | Plans to render. Required. |
billing | "monthly" | "yearly" | "monthly" | Initial billing period. |
currency | string | "USD" | ISO currency code. |
highlight | string | — | Plan ID to render as featured. |
<Pricing plans={[ { id: "free", name: "Free", price: 0, features: ["1 site"] }, { id: "pro", name: "Pro", price: 19, features: ["Unlimited sites"] }, { id: "team", name: "Team", price: 59, features: ["Roles & SSO"] } ]} highlight="pro" />
<Form/> component
Component
A composable form with built-in validation, server-action support, and accessible labels. Use the fields prop for quick declarative forms or compose <Form.Field/> children for full control.
| Prop | Type | Default | Description |
|---|---|---|---|
fields | Field[] | — | Declarative field list. Optional. |
action | (values) => Promise | — | Submit handler. Receives sanitised values. |
submitLabel | string | "Submit" | Submit button label. |
validateOn | "blur" | "change" | "blur" | When to run field validation. |
<Form fields={[ { name: "email", type: "email", label: "Email", required: true }, { name: "company", type: "text", label: "Company" } ]} action={subscribe} submitLabel="Subscribe" />
Sites
REST APICreate, list, update, and delete sites. Every site has at least one page and one deploy.
-
POST
/v1/sitesCreate a site -
GET
/v1/sitesList all sites -
GET
/v1/sites/{id}Retrieve a site -
PATCH
/v1/sites/{id}Update a site -
DEL
/v1/sites/{id}Archive a site
Create a site
# request curl -X POST https://api.altask.dev/v1/sites \ -H "Authorization: Bearer $ALTASK_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "habits-app", "template": "lift"}' # response · 201 { "id": "site_8aL2k9X", "name": "habits-app", "url": "https://habits-app.altask.dev", "publish_token": "pt_••••••••", "created_at": "2026-09-14T18:42:00Z" }
Pages
REST APIPages live inside a site. Each page has a slug, a JSON content tree, and an SEO block. Updates are atomic — partial PATCH bodies are merged server-side.
- GET
/v1/sites/{id}/pagesList pages - POST
/v1/sites/{id}/pagesCreate a page - GET
/v1/pages/{id}Retrieve a page - PATCH
/v1/pages/{id}Update slug, blocks, or SEO - DEL
/v1/pages/{id}Archive a page
Update SEO meta
curl -X PATCH https://api.altask.dev/v1/pages/page_4Bz1 \ -H "Authorization: Bearer $ALTASK_KEY" \ -H "Content-Type: application/json" \ -d '{"seo": {"title": "Pricing — Altask", "description": "Plans for every team."}}'
Deploys
REST APIEach deploy is an immutable snapshot of a site. Deploys are queued, built, and promoted to the global edge. Use state to track progress; promote previews to production with a single PATCH.
- POST
/v1/sites/{id}/deploysTrigger a deploy - GET
/v1/sites/{id}/deploysList recent deploys - GET
/v1/deploys/{id}Inspect a deploy - PATCH
/v1/deploys/{id}Promote to production
| State | Meaning |
|---|---|
queued | Accepted, waiting for a build runner. |
building | Asset pipeline is running. |
preview | Live at a preview URL, not promoted. |
live | Promoted to the production domain. |
failed | Failed validation, build, or health check. |
Webhooks
Subscribe to lifecycle events to keep your CMS, CI, or analytics in sync. Payloads are signed with HMAC-SHA256 — verify with the X-Altask-Signature header.
| Event | When it fires |
|---|---|
site.created | A new site is created via dashboard or API. |
page.published | A page is published or republished. |
deploy.succeeded | A deploy lands on the global edge with a 2xx health check. |
deploy.failed | A deploy fails build, validation, or health check. |
domain.verified | A custom domain passes DNS & SSL verification. |
Embed snippet
Drop a single script tag into any HTML page to render an Altask block in place. Snippets render server-side at the edge and hydrate progressively.
<div id="altask-pricing"></div> <script src="https://embed.altask.dev/v1/altask.js" data-block="pricing" data-site="site_8aL2k9X" data-mount="#altask-pricing" defer ></script>
Error reference
Errors return a JSON body with code, message, and an optional request_id. Always log request_id when contacting support — it pins the request to a single trace.
| Status | Code | When you'll see it |
|---|---|---|
| 400 | invalid_request | Body fails schema validation. Inspect errors[]. |
| 401 | unauthenticated | Missing or expired token. |
| 403 | forbidden | Token lacks the required scope. |
| 404 | not_found | Resource doesn't exist or is archived. |
| 409 | conflict | Slug or domain is already taken in this workspace. |
| 429 | rate_limited | Too many requests. Honor Retry-After. |
| 500 | internal_error | Transient server error. Retry with backoff. |
# example error { "code": "invalid_request", "message": "slug must match ^[a-z0-9-]+$", "request_id": "req_3rWv0pY", "errors": [ { "path": "slug", "rule": "pattern" } ] }
Wire up a CMS
GuidePull content from any headless CMS and let editors update copy without touching layout. The block tree stays in Altask, the strings live in the CMS.
- Map fields. In the editor, mark text props as bound and pick a CMS path (e.g.
hero.title). - Add a fetch hook. Server-side, fetch your CMS, then pass the JSON to
client.pages.render({ id, data }). - Subscribe. Listen for the
page.publishedwebhook to revalidate caches in your CMS layer.
const data = await fetchCms("home"); const html = await client.pages.render({ id: "page_4Bz1", data });
Custom domains
GuideApex domains, subdomains, and wildcards. Add a CNAME, hit verify, done. We handle DNSSEC, CAA, and edge propagation automatically.
| Type | Record | Value |
|---|---|---|
| Apex | A | 76.76.21.21 |
| Subdomain | CNAME | edge.altask.dev |
| Wildcard | CNAME for * | edge.altask.dev |
# verify a domain after DNS update curl -X POST https://api.altask.dev/v1/sites/site_8aL2k9X/domains/verify \ -H "Authorization: Bearer $ALTASK_KEY" \ -d '{"hostname": "habits-app.com"}'
CLI & CI
GuideThe Altask CLI runs the same build pipeline as the cloud — preview locally, lint your blocks, and ship from CI without leaving your terminal.
npx @altask/cli login npx @altask/cli dev # preview at localhost:3010 npx @altask/cli build # static export to ./dist
# .github/workflows/deploy.yml - name: Deploy run: | npm i -g @altask/cli altask deploy --site $SITE_ID --token ${{ secrets.ALTASK_KEY }}
Need something specific?
Our team replies in under a working day. Open a thread, share a repro, get unstuck.