# Preview and publish

A repository opens on its **Preview**: the app running from its default branch, full width, with **Publish** in the header. A **Preview / Settings** switch sits at the top right, on a computer and on a phone. **Settings** opens the repository's [settings](https://kosuke.ai/docs/set-up/project-settings.md), and the page remembers which of the two you had open.

Every repository has a Preview once its main sandbox can run the app: its [services](https://kosuke.ai/docs/set-up/project-settings.md) are set and it has been deployed. These are the same settings a chat session's Preview starts from. A repository without them opens on Settings. Its **Preview** button is turned off, and its tooltip starts with "Preview is off.", then says what is missing and what to do next:

| Missing | The tooltip goes on |
| --- | --- |
| No services | "This repository has no services to start. Add them in Settings, Services, or ask the deploy agent in the chat to set them up." |
| No deploy yet | "The main sandbox is not deployed yet. Ask the deploy agent in the chat to deploy main, then open Preview." |

### An imported repository's Preview

A repository without the kosuke-starter layout starts nothing when you open it. Its Preview reads "Preview not started" with **Start preview**:

1. Press **Start preview**. The main sandbox wakes, and the Preview reads **Starting**.
2. Its services start. The Preview shows how many run, such as "Starting services, 2 of 3 running".
3. The app shows once they all answer.

If a service does not start, the Preview reads "App stack could not start" with the reason, and **Logs** in the header has the full output. If the sandbox itself does not start, it reads "Preview could not start". Press **Try again** on either: on the first it restarts the services, on the second it starts the sandbox again. `kosuke preview get --services restart` restarts the services of a running main sandbox, and `--services wait` waits for them.

Publish shows in the header too. Its menu shows the address and why Publish needs the kosuke-starter layout, with no Publish button. See [The kosuke-starter layout](https://kosuke.ai/docs/set-up/preview-and-publish.md#the-kosuke-starter-layout).

## Start from kosuke-starter

Kosuke staff turn this feature flag on or off for each deployment. While it is off, the New repository dialog offers **Import from GitHub** alone, and every other way of making a repository from kosuke-starter is refused. Repositories already made from it keep their Preview, deploys and pushes.

In the sidebar, hover the workspace's row and press its **+**. The New repository dialog opens on **Start from kosuke-starter**.

1. Under "What do you want to build?", describe it in a sentence, such as "A booking page for my yoga classes".
2. Under **Merge mode**, keep **Merge train** with Go-ahead **When checks pass**, marked **Default**, or pick another. You can change it later in Settings > [Merge agent](https://kosuke.ai/docs/set-up/project-settings.md#merge-agent).
3. Press **Create repository**.

Sensei makes a private repository in Kosuke-Org from kosuke-starter, deploys it, and starts the first task on your sentence. The repository opens on its Preview while the first deploy runs, with three steps: Create, Deploy, and Start the first task. Once the deploy lands, the first task runs `/kosuke:ship` like any other task. When its checks pass, it merges and becomes Version 1.

If the first deploy fails, the Preview reads "Deployment failed" with **Retry deploy** and **Open the logs**, which opens Settings on its logs.

With the CLI, `kosuke projects create --description "<what to build>"` does the same. With [Sensei](https://kosuke.ai/docs/automate/sensei.md), pick **Build a new app**, or ask it to build something: it shows the Describe card, and **Create repository** on it creates the repository.

## The kosuke-starter layout

The layout is what Publish needs to build the app as a Cloudflare Worker with bun and `@cloudflare/vite-plugin`:

- a `bun.lock` and a `build` script,
- `@cloudflare/vite-plugin`,
- a `wrangler.jsonc`, `wrangler.json` or `wrangler.toml` naming `main` and `compatibility_date`, with no D1 database.

The app keeps its data in its own Turso database. The Preview and the published app share it through `TURSO_DATABASE_URL` and `TURSO_AUTH_TOKEN`. A task's sandbox never gets the live database.

Every repository made from kosuke-starter has the layout. An imported repository has it when it carries those files on the branch its Preview runs. Sensei checks the layout at that branch's latest commit, so a repository can gain or lose Publish. Without the layout, the API refuses Versions and Publish with 409 `NO_STARTER_LAYOUT`. The Preview does not need the layout.

## The live preview

The Preview shows the project's main sandbox, which runs the default branch, or the branch set in **Branch tasks from** under [Advanced](https://kosuke.ai/docs/set-up/project-settings.md#advanced). It follows every merge and every Chat push by itself, usually within a minute. Every member who can open the project sees it.

- While the sandbox starts, the Preview reads **Starting**. Publish works meanwhile.
- A badge reads **Version N** for the latest Version, or **First deploy** before there is one.
- When tasks of the repository run, a link such as "1 task running" opens Tasks.

The page has no New task button. Tasks live in the Tasks list like any other, and a task starts from its modal.

## Versions

Each task that merges into the default branch is a **Version**, and so is each [Chat push](https://kosuke.ai/docs/set-up/preview-and-publish.md#chat-and-versions). A merged task's modal shows **See Version N in Preview**, which opens the Preview. The Versions you published are listed in **Publish**'s dropdown in the header. `kosuke projects versions list` lists every Version, newest first.

## Chat and Versions

[Chat](https://kosuke.ai/docs/set-up/project-settings.md#chat) pushes straight to the default branch, with no pull request. On a repository with the kosuke-starter layout, each Chat push becomes a Version: one push, one Version, titled after its commit. Under the turn, a row such as "Version 6 saved to main" links to the commit.

The Preview follows the push like a merge. Until the main sandbox runs the push, the Preview keeps the old page, with "Updating to Version N" over it. Then it shows the change.

A repository without the layout has no Preview and gets no Version. Chat still works there, and you see the result on GitHub. Under the turn, a row such as "Pushed to main" links to the commit, and reads "No Version, because this repository has no Preview."

## Publish

**Publish** in the header puts a Version live at the repository's address, `<label>.kosuke.app`. A repository made from kosuke-starter is addressed by its repository's name. An imported one is addressed by the project's name and the start of its id, such as `todo-app-3f9a1c2b.kosuke.app`.

1. Press **Publish**. A popover shows the address and **Publish version N** for the latest Version.
2. Confirm with **Publish**. The button reads **Publishing**, then **Live: vN**.

A dot on the button means a newer Version is not live yet. When a release fails, the popover says so, and the Version before it stays live.

The popover lists the **Releases**. **Roll back** puts an earlier Release live again, and **Make live** a later one. Neither builds anything: the traffic switches at once. **Unpublish** takes the app down without deleting its data, and **Publish** puts it back at the same address.

A repository that lost the layout but still has a published app keeps **Unpublish** in its settings.

## Apps became repositories

Apps, the projects that worked in one chat, are gone. Every App became a repository:

- It runs on **Merge train** with Go-ahead **When checks pass**.
- Its chat is one Done task, whose history stays readable in **Open chat**.
- Its Backlog items and the messages that waited Up next in its chat are Todo tasks, with their attachments.
- A published App stays live at the same address, with its Versions and Releases.
- Changes a running Turn had not saved went to a branch named `kosuke/app-unsaved-…`, with a Todo task to finish them.

## Next steps

- [Project settings](https://kosuke.ai/docs/set-up/project-settings.md)
- [Deploy your project](https://kosuke.ai/docs/set-up/deploy.md)
- [Chat sessions and tasks](https://kosuke.ai/docs/sessions/chat-sessions.md)
