# Quickstart

> Clone, configure, build, run and deploy — with the commands for each.

From an empty directory to a deployed Worker. Every command here is the `moddable`
CLI, which resolves the project root by walking up from wherever you run it — so these work
from anywhere in the tree.

## Requirements

- [Bun](https://bun.sh) 1.2 or newer. Always `bun` — never `npm` or `tsc`.

- A Cloudflare account, for anything past local development.

## Start a project

```
git clone /moddable.cli.git moddable/cli
bun moddable/cli/build.ts
moddable config all
moddable build
```

The CLI build bootstraps rather than assuming. It writes or corrects
`tsconfig.json` — the `paths` every `moddable/…` specifier
resolves through — and `index.d.ts`, then re-runs itself once, because Bun reads a
tsconfig when it starts and the one just written is invisible to the process that wrote it.
An existing tsconfig is corrected in place: missing aliases are added, anything the project
already set is left alone, and every change is printed.

A CLI-only clone cannot bundle on its own — its source imports
`moddable/core` and `moddable/modules/cloudflare`. Rather than a page of
resolver errors, the build names the directories it is missing and prints the
`git clone` for each, deriving the provider from the CLI's own git remote.

## Configure

`moddable config` is how a project gets set up and how a setup gets checked. Each
target takes `generate` or `validate`; a target on its own generates when
it is missing and validates when it is there. With no target at all it walks every target in
order — the one command a fresh clone runs.

```
moddable config # check everything, generate what is missing
moddable config all # generate every target
moddable config wrangler # just the worker config
moddable config dependencies --install
```

Targets include `typescript`, `scripts`, `dependencies`,
`gitignore`, `wrangler`, `settings`, `server`,
`types`, `site`, `storybook`, `tests` and
`repo`.

Three of them are composed rather than copied. `server`, `types` and
`settings` are all written from a single scan of the modules on disk, so adding a
module is making a directory: `moddable config server` then imports it, registers
it, and re-exports its durable objects. Composing is not clobbering — the generators read the
order already in the file and keep it, dropping what is gone and appending what is new.

`-y` answers every prompt with its default so a whole setup is scriptable,
`--force` overwrites files that already exist, and `--install` installs
the packages each setup declares.

## Run it locally

```
moddable dev --watch --protocol=http
```

`moddable config wrangler` creates the `wrangler.json` this needs. That
file holds the account id, the API token and the signing keys, so it is the one entry an
unignored `.gitignore` reports as a failure rather than a note.

## Build

`moddable build` runs everything. The individual targets are worth knowing when you
are iterating on one of them:

Command |
Output |

`moddable server export` |
`moddable/server/dist/index.js` — the Worker |

`moddable app export` |
`moddable/site/app.js` — the browser runtime |

`moddable views export` |
`moddable/site/views/<tag>.js` |

`moddable elements export` |
`moddable/site/elements/<tag>.js` |

`moddable assets export` |
`moddable/site/assets` |

Each of the component builds takes a filter — `moddable views export --view=<dir>`,
`moddable assets export --asset=<path>` — and skips anything whose checksum has
not changed, so a rebuild after one edit compiles one thing.

## Add a page

Make a directory under a module's `api/views` with four files:

```
moddable/core/api/views/HelloView/
├── index.ts
├── template.html
├── style.css
└── logic.ts
```

```
// index.ts
import { makeView } from 'moddable/core/shared/utils/views/makeView'
import template from './template.html'
import style from './style.css'
import logic from './logic'

export default makeView({
name: 'HelloView',
tag: 'hello-view',
pathname: '/hello',
head: { title: 'Hello' },
template,
style,
logic
})
```

Register it in the module's `views/index.ts`, then
`moddable views export`. The tag must be unique across the project — it is both the
custom element name and the filename the bundle is served under.

## Test

```
moddable tests # every suite, every module
moddable tests core # every suite for one module
moddable tests unit # one suite, every module
moddable tests core worker # one suite for one module
```

Module and suite share one positional slot because they never collide, so the two read the same
in either order. Vitest owns `*.test.ts`; Playwright owns `*.spec.ts`. The
end-to-end suite runs against compiled output, so `moddable build` comes first.

Never `bun test` — that is Bun's own runner and it ignores `vitest.config.ts`.

## Deploy

```
moddable build
moddable deploy
```

The worker serves the site it was compiled with, so there is nothing else to upload. Next:
the [Auth API](/docs/auth).
