> ## Documentation Index
> Fetch the complete documentation index at: https://docs.webstorio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Your first site with the CLI

> Scaffold a Webstorio site as local .tsx files, preview it, and deploy it live — a step-by-step tutorial for developers.

In this tutorial you'll scaffold a Webstorio project on your machine, edit a page
as a React component, preview it with live reload, and deploy it live with one
command. By the end you'll have a real site at your own `webstor.io` address.

You only need **Node.js** with a package manager (npm, pnpm, yarn, or bun) and a
free [Webstorio account](https://webstorio.com).

Prefer the dashboard AI builder instead? See [Create your first site](/guides/create-your-site).

## Step 1 — Scaffold a project

Create a new project with the CLI, then install its dependencies:

```bash theme={"dark"}
npx @webstorio/cli@latest init my-site
cd my-site
npm install
```

`init` scaffolds a ready-to-run project: a `webstorio.config.ts`, a `brand/` folder, a `pages/` folder with a
`home.tsx`, `components/_header.tsx` and `_footer.tsx`, plus a `package.json`,
`tsconfig.json`, and `.gitignore`. The directory name seeds your project's
default name and subdomain.

## Step 2 — Explore the structure

A Webstorio site is a small set of files:

```text theme={"dark"}
my-site/
├─ webstorio.config.ts   # pages, components, features, branding, SEO
├─ brand/
│  ├─ brand-info.md
│  └─ design-system.md
├─ components/
│  ├─ _header.tsx
│  └─ _footer.tsx
├─ pages/
│  └─ home.tsx           # one .tsx module per page
└─ schemas/              # CMS / forms / App Data JSON (optional until you enable features)
   ├─ content/
   ├─ forms/
   └─ data/
```

Each page is plain **React** with a `default` export. `webstorio.config.ts` maps
each file to a route:

```ts webstorio.config.ts theme={"dark"}
import { defineConfig } from "@webstorio/cli/config";

export default defineConfig({
  name: "My Site",
  subdomain: "my-site",
  description: "Welcome to My Site.",
  schemasDir: "schemas",
  features: {
    header: true,
    footer: true,
    content: false,
    form_and_survey: false,
    online_store: false,
    user_authentication: false,
    app_data: false,
    webstorio_badge: true,
  },
  branding: {
    colors: {
      primary: "#0084d1",
      secondary: "#009966",
      background: "#ffffff",
      text: "#171717",
    },
    fonts: { primary: "inter", secondary: "open_sans" },
    brandInfoFile: "brand/brand-info.md",
    designSystemFile: "brand/design-system.md",
  },
  components: [
    { file: "components/_header.tsx", slug: "_header", title: "Header" },
    { file: "components/_footer.tsx", slug: "_footer", title: "Footer" },
  ],
  pages: [
    {
      file: "pages/home.tsx",
      slug: "/",
      title: "Home",
      type: "system",
      seo: {
        title: "My Site",
        description: "Welcome to My Site.",
      },
    },
  ],
  dev: { dataMode: "dummy" },
});
```

`init` also writes a `compatibilityDate` that pins your
[supported library](/api-reference/supported-libraries) versions. See the full
schema in [Configuration](/cli/configuration).

The empty `schemas/` folders are ready when you turn on CMS, forms, or App Data
— see [Feature schemas](/developer/schemas). For this tutorial you can ignore
them.

## Step 3 — Preview locally

Start the dev server:

```bash theme={"dark"}
npx webstorio dev
# Local: http://localhost:9678
```

Open the URL in your browser. The dev server watches `pages/**`,
`components/**`, and `webstorio.config.ts`, recompiling and reloading whenever you
save. It runs fully offline using mock data ([data modes](/developer/local-development)).

## Step 4 — Edit a page

Open `pages/home.tsx` and make it your own. It's just React — style with Tailwind
classes (including brand utilities like `bg-brand-primary` and
`font-brand-primary` from your [branding](/cli/configuration#branding) config)
and import icons from the allowlist:

```tsx pages/home.tsx theme={"dark"}
import { Sparkles } from "lucide-react";

export default function Home() {
  return (
    <main className="mx-auto max-w-2xl px-6 py-24 text-center">
      <Sparkles className="mx-auto h-10 w-10 text-sky-500" />
      <h1 className="mt-4 text-4xl font-bold tracking-tight">
        Hello from the CLI
      </h1>
      <p className="mt-4 text-lg text-neutral-600">
        Edit <code>pages/home.tsx</code> and save to see it reload.
      </p>
    </main>
  );
}
```

Save the file and watch the preview update instantly.

<Tip>
  You can only import from the [supported
  libraries](/api-reference/supported-libraries); anything else must be a
  relative import, which the CLI bundles into the page. After adding a new
  supported library, run `npx webstorio update` to install matching versions.
</Tip>

## Step 5 — Add another page

Create `pages/about.tsx` with a default export:

```tsx pages/about.tsx theme={"dark"}
export default function About() {
  return (
    <main className="mx-auto max-w-2xl px-6 py-24">
      <h1 className="text-3xl font-bold">About</h1>
    </main>
  );
}
```

Then register it in `webstorio.config.ts` so it gets a route:

```ts theme={"dark"}
pages: [
  { file: "pages/home.tsx", slug: "/", title: "Home", type: "system" },
  { file: "pages/about.tsx", slug: "about", title: "About" },
],
```

The new page is live in your preview at `/about`.

<Tip>
  Need real CMS, store, or form data on a page? Call the
  [`window.webstorio`](/api-reference/sdk/overview) SDK and set `dev.dataMode`
  to `preview` to proxy your real project data.
</Tip>

## Step 6 — Log in

Authenticate the CLI through your browser:

```bash theme={"dark"}
npx webstorio login
```

This opens Webstorio, you approve, and a token is stored securely on your
machine.

## Step 7 — Deploy

Optional: preview what will sync with a read-only diff:

```bash theme={"dark"}
npx webstorio status
```

Then sync and publish in one command:

```bash theme={"dark"}
npx webstorio push --publish
```

The CLI composes each page, resolves your project by its `subdomain` (creating it
if it doesn't exist), and uploads the source. The **Webstorio server compiles it
authoritatively** and publishes the site. You'll see a per-page report:

```text theme={"dark"}
✓ / — created
✓ about — created
✓ _header — created
✓ _footer — created
```

Your site is now live at:

```text theme={"dark"}
https://my-site.webstor.io
```

<Note>
  Run `npx webstorio push` without `--publish` to sync changes as drafts. Push
  is idempotent — re-running updates existing pages in place and writes a new
  version each time. More on status and push: [Deploying](/developer/deploying).
</Note>

## Next steps

You've built and deployed a Webstorio site from code. Keep going:

<CardGroup cols={2}>
  <Card title="Project structure" icon="folder-tree" href="/developer/project-structure">
    Config, pages, components, brand, assets, and schemas.
  </Card>

  <Card title="Local development" icon="monitor" href="/developer/local-development">
    Data modes, live reload, and preview fidelity.
  </Card>

  <Card title="Deploying" icon="rocket" href="/developer/deploying">
    Login, status, push, and publish.
  </Card>

  <Card title="Feature schemas" icon="database" href="/developer/schemas">
    Version CMS, forms, and App Data as JSON in the repo.
  </Card>

  <Card title="Use AI agents" icon="bot" href="/developer/ai-agents">
    Edit local `.tsx` with Cursor, Claude Code, Codex, etc.
  </Card>

  <Card title="Connect MCP" icon="server" href="/developer/connect-mcp">
    Manage CMS, forms, and store from an agent.
  </Card>

  <Card title="Commands" icon="square-terminal" href="/cli/commands">
    Every command and option.
  </Card>

  <Card title="Client SDK" icon="braces" href="/api-reference/sdk/overview">
    Read and write site data with `window.webstorio`.
  </Card>
</CardGroup>
