# Publish and hand off

> How Publish uploads a theme to your Extension.dev account and opens the import screen, and how the Use this theme menu hands the theme to code.extension.dev.

Canonical: https://docs.extension.dev/themes/publish
This page as Markdown: https://docs.extension.dev/themes/publish.md
Section: Themes
Siblings: [Theme builder](https://docs.extension.dev/themes.md) · [The editor](https://docs.extension.dev/themes/editor.md) · [Colors](https://docs.extension.dev/themes/colors.md) · [Presets and palettes](https://docs.extension.dev/themes/presets.md) · [Images and tints](https://docs.extension.dev/themes/images.md) · [Import a theme](https://docs.extension.dev/themes/import.md) · [Export and install](https://docs.extension.dev/themes/export.md) · [Firefox preview](https://docs.extension.dev/themes/firefox-preview.md)
Map of every page: https://docs.extension.dev/llms.txt · Whole corpus: https://docs.extension.dev/llms-full.txt

---

# Publish and hand off

Publish turns the theme into a GitHub repository on Extension.dev, and the
Use this theme menu sends it to the AI editor on code.extension.dev. Reach
for them when the theme is done in the editor and you want it to live and
build somewhere else.

## Quick start

1. Open **Theme settings** in the editor and click **Publish this theme**.
2. Read the four steps in the dialog and click **Continue**. The theme
   files upload to your account.
3. The import screen opens in a new tab. Name the repository, choose public
   or private, and confirm there.


## How it works

**Publishing is not the store.** The dialog is headed "Before you publish"
and lists what happens in order: the manifest and images upload to your
Extension.dev account, the import screen opens where you name the
repository, Extension.dev creates the GitHub repository and runs the first
build, and submitting to the Chrome Web Store stays a separate step you
start yourself.

**What is sent.** The editor builds the same files the ZIP export holds and
posts them to `www.extension.dev/api/artifacts` with your session cookies,
as a source artifact for the theme surface. The repository slug is the theme
name lowercased with hyphens, cut at 64 characters, or `my-theme` when the
name yields nothing.

**The tab opens first.** The new tab is claimed before the upload starts,
so the browser never treats it as a popup. When the upload lands the tab is
steered to `/import` on www.extension.dev with the artifact id, the slug,
the name and the description in the query. Nothing is created until you
confirm on that screen. A failed upload closes the tab.

**Sign in first.** The upload needs you signed in. A 401 puts the dialog in
a sign-in state with a **Sign in** link, and you publish again afterward.
Accounts need GitHub connected, and they are invite-only while Extension.dev
is in private alpha.

**Size.** An upload whose encoded files pass 8 MiB is refused before it
leaves the page. The dialog reads "This theme is too large to publish" and
suggests shrinking the New Tab background or the frame image, since that is
about 6 MB of images.

**Use this theme.** The header menu offers two items. **Deploy to
Extension.dev** runs the same upload as Publish without the dialog. **Edit
on code.extension.dev** hands the theme to the AI editor so you keep
building it as an extension. That item stays disabled until the alpha door
is open, which the page learns by asking Extension.dev once per load.

**Two hand-off lanes.** Edit first uploads the theme as an artifact and
opens code.extension.dev with `?artifact=` and `source=themes`, images
included. When you are signed out or the upload fails, it falls back to a
prompt URL that carries the manifest JSON as text and no images. That URL
is refused when it would pass 8000 characters. A toast names which lane
ran.

## Reference

| Field | Value |
| --- | --- |
| Upload endpoint | `www.extension.dev/api/artifacts`, with session cookies |
| Artifact kind | `source`, surface `theme` |
| Repository slug | Theme name lowercased, hyphenated, at most 64 characters, default `my-theme` |
| Import screen | `/import` with `artifactId`, `repo`, `name` and `description` |
| Upload limit | 8 MiB encoded, about 6 MB of images |
| Prompt hand-off limit | 8000 URL characters, manifest only |
| Artifact hand-off | `?artifact=<id>&source=themes` on code.extension.dev |

| Dialog state | Shown when |
| --- | --- |
| Before you publish | Dialog opened, four steps listed |
| Uploading your theme | Upload in flight |
| Your theme is uploaded | The import screen is open in a new tab |
| Sign in to Extension.dev first | The upload answered 401 |
| This theme is too large to publish | The encoded files pass 8 MiB |
| Publishing did not finish | Any other failure, nothing was created |

## When it fails

- **"Sign in to Extension.dev first."** You are signed out of Extension.dev.
  Click **Sign in**, then publish again. The theme stays in this editor.
- **"This theme is too large to publish."** The files pass 8 MiB encoded.
  Shrink the New Tab background or the frame image and try again.
- **"Publishing did not finish. Nothing was created."** The upload failed
  for another reason, which the dialog quotes. Click **Try again**.
- **"Export blocked: fix the highlighted theme information first."** The
  name is empty or the version is invalid. Fix it in Theme settings; publish
  builds the same manifest as export.
- **Edit on code.extension.dev is disabled.** That surface is in private
  alpha and opens when the alpha does. Deploy and Publish still work.
- **"This theme is too large to hand off in a link."** You were signed out,
  so the prompt lane ran, and the manifest passed 8000 characters. Sign in
  so the artifact lane carries it, or export the ZIP.
- **"Handed off your theme as text because extension.dev needs you signed
  in."** The prompt lane ran without images. Sign in and hand off again to
  carry them.

## Next

- [Export and install](/themes/export)
- [Import a repository](/guides/import)
- [Publish overview](/publish/overview)
- [The editor](/themes/editor)
