---
title: "Setup Nuxt Studio"
description: "Learn how to install and configure Nuxt Studio to edit your content in production with GitHub authentication."
canonical_url: "https://nuxt.studio/setup"
---
# Setup Nuxt Studio

> Learn how to install and configure Nuxt Studio to edit your content in production with GitHub authentication.

## Installation

<warning to="https://content.nuxt.com">

Nuxt Studio allows content edition of Nuxt Content websites only.

</warning>

Install Nuxt Studio using the Nuxt CLI within your project:

```bash [Terminal]
npx nuxt module add nuxt-studio
```

<tip icon="i-lucide-rocket">

Start your development server and start editing your Nuxt Content website.

</tip>

## Development mode

Previous section is enough to be able to edit your content. Just click on the floating button on the bottom left of your page.

When running locally, **any file changes will be synchronized in real time with your local filesystem**.

<note>

The publish system is only available in production mode. Use your current workflow (git command, IDE, GitHub Desktop...) to commit your changes.

</note>

## Production mode

Studio's main advantage is publishing content changes directly from your production website. This requires two configurations:

<steps>

### Git Provider

Configure where your content is stored and where changes will be committed.

When deploying on **Vercel**, **Netlify**, **GitHub Actions**, or **GitLab CI**, the repository details (`provider`, `owner`, `repo`, and `branch`) are **automatically detected** from the CI environment variables — no manual configuration is needed.

<note>

On Vercel, make sure that the **Automatically expose System Environment Variables** option is enabled in your project settings for auto-detection to work.

</note>

For other platforms, or to override the detected values, configure the repository manually:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    repository: {
      provider: 'github', // 'github' or 'gitlab'
      owner: 'your-username',
      repo: 'your-repo',
      branch: 'main'
    }
  }
})
```

<tip to="https://nuxt.studio/git-providers">

Learn more about GitHub and GitLab providers.

</tip>

### Auth Provider

Configure how users authenticate to access Studio. Choose from GitHub, GitLab, Google OAuth, or custom authentication:

```bash [.env]
# Example with GitHub OAuth
NUXT_STUDIO_AUTH_GITHUB_CLIENT_ID=<your_client_id>
NUXT_STUDIO_AUTH_GITHUB_CLIENT_SECRET=<your_client_secret>
```

<tip to="https://nuxt.studio/auth-providers">

Follow the complete setup instructions for your auth provider.

</tip>

### Deployment

Nuxt Studio requires a server-side route for authentication.

While static generation remains supported with [Nuxt hybrid rendering](https://nuxt.com/docs/4.x/guide/concepts/rendering#hybrid-rendering), your site must be **deployed on a platform that supports server-side rendering (SSR)** using `nuxt build` command.

If you want to pre-render all your pages, use the following configuration:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  nitro: {
    prerender: {
      // Pre-render the homepage
      routes: ['/'],
      // Then crawl all the links on the page
      crawlLinks: true
    }
  }
})
```

### Open Studio

Once deployed, open Studio by navigating to your configured route (default: `/_studio`):

1. Click the login button if it does not directly redirect to the OAuth app authorization page
2. Authorize the OAuth application
3. You'll be redirected back to Studio ready to edit your content

<tip>

You can also use the shortcut `CMD` + `.` to redirect to the Studio route.

</tip>
</steps>

## Options

Add the module to your `nuxt.config.ts` and configure your repository based on your Git provider:

### Admin route

Customize the login route using the `route` option:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    route: '/admin', // default: '/_studio'
  }
})
```

### Repository

Use the `repository` option to specify your git repository to sync in production mode.

When deploying on supported platforms, the repository details are **automatically detected** from CI environment variables:

<table>
<thead>
  <tr>
    <th>
      Platform
    </th>
    
    <th>
      Provider
    </th>
    
    <th>
      Owner
    </th>
    
    <th>
      Repo
    </th>
    
    <th>
      Branch
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <strong>
        Vercel
      </strong>
    </td>
    
    <td>
      <code>
        VERCEL_GIT_PROVIDER
      </code>
    </td>
    
    <td>
      <code>
        VERCEL_GIT_REPO_OWNER
      </code>
    </td>
    
    <td>
      <code>
        VERCEL_GIT_REPO_SLUG
      </code>
    </td>
    
    <td>
      <code>
        VERCEL_GIT_COMMIT_REF
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        Netlify
      </strong>
    </td>
    
    <td>
      from <code>
        REPOSITORY_URL
      </code>
    </td>
    
    <td>
      from <code>
        REPOSITORY_URL
      </code>
    </td>
    
    <td>
      from <code>
        REPOSITORY_URL
      </code>
    </td>
    
    <td>
      <code>
        BRANCH
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        GitHub Actions
      </strong>
    </td>
    
    <td>
      <code>
        github
      </code>
    </td>
    
    <td>
      from <code>
        GITHUB_REPOSITORY
      </code>
    </td>
    
    <td>
      from <code>
        GITHUB_REPOSITORY
      </code>
    </td>
    
    <td>
      <code>
        GITHUB_REF_NAME
      </code>
    </td>
  </tr>
  
  <tr>
    <td>
      <strong>
        GitLab CI
      </strong>
    </td>
    
    <td>
      <code>
        gitlab
      </code>
    </td>
    
    <td>
      <code>
        CI_PROJECT_NAMESPACE
      </code>
    </td>
    
    <td>
      <code>
        CI_PROJECT_NAME
      </code>
    </td>
    
    <td>
      <code>
        CI_COMMIT_BRANCH
      </code>
    </td>
  </tr>
</tbody>
</table>

Auto-detection applies to all fields, including `branch`. CI-detected values take precedence over manually configured values in `nuxt.config.ts`.

To override or for unsupported platforms, configure the repository manually:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    repository: {
      provider: 'github', // 'github' or 'gitlab', default: 'github'
      owner: 'your-username', // your GitHub/GitLab username or organization
      repo: 'your-repo', // your repository name
      branch: 'main', // the branch to commit to (default: main)
    }
  }
})
```

#### Instance URL

For GitHub Enterprise or self-hosted GitLab, you can specify the instance URL.

Default value is based on the provider:

- **GitHub**: `https://github.com`
- **GitLab**: `https://gitlab.com`

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    repository: {
      ...
      instanceUrl: 'https://<github/gitlab>.company.com' 
    }
  }
})
```

<note>

Can be overridden by the `NUXT_STUDIO_AUTH_GITHUB_INSTANCE_URL` or `NUXT_STUDIO_AUTH_GITLAB_INSTANCE_URL` environment variable.

</note>

#### Root directory `default: ''`

If your Nuxt Content application is in a monorepo or subdirectory, specify the `rootDir` option to point to the correct location.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    repository: {
      ...
      rootDir: 'docs'
    }
  }
})
```

#### Private Repository Access `default: true`

By default, Studio requests access to both public and private repositories.

Setting `private: false` limits the OAuth scope to public repositories only, which may be preferable for security or compliance reasons when working with public repositories.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    repository: {
      ...
      private: false
    }
  }
})
```

### Internationalization

Nuxt Studio includes built-in internationalization support with the following languages available:

- 🇬🇧 **English** (default)
- 🇸🇦 **Arabic**
- 🇧🇬 **Bulgarian**
- 🇩🇪 **German**
- 🇪🇸 **Spanish**
- 🇮🇷 **Farsi**
- 🇫🇮 **Finnish**
- 🇫🇷 **French**
- 🇮🇩 **Indonesian**
- 🇮🇹 **Italian**
- 🇯🇵 **Japanese**
- 🇳🇱 **Dutch**
- 🇵🇱 **Polish**
- 🇧🇷 **Portuguese (Brazil)**
- 🇺🇦 **Ukrainian**
- 🇨🇳 **Chinese**
- 🇰🇷 **Korean**
- 🇨🇿 **Czech**
- 🇳🇴 **Norwegian (Bokmål)**
- 🇳🇴 **Norwegian (Nynorsk)**
- 🇷🇺 **Russian**
- 🇹🇼 **Chinese (Traditional, Taiwan)**
- 🇰🇭 **Khmer**
- 🇸🇰 **Slovak**
- 🇭🇺 **Hungarian**

Set your preferred language using the `i18n` option:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    i18n: {
      defaultLocale: 'fr' // 'en', 'fr' or 'de'
    }
  }
})
```

This will translate:

- All UI elements and labels
- Monaco editor snippets and code completion
- Contextual messages and notifications

<callout icon="i-lucide-heart-handshake">

Community contributions for new language translations are welcome! If you'd like to add support for a new language, please visit the [GitHub repository](https://github.com/nuxt-content/studio) and drop a pull request.

</callout>

### Dev mode

If you want to test your production setup locally, disable the `dev` option:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    dev: false
  }
})
```

Make sure to configure your OAuth provider to redirect to your local dev server (usually [http://localhost:3000](http://localhost:3000)).

### Editor

You can customize the appearance and behavior of Nuxt Studio by configuring the `editor` object in your `nuxt.config.ts` file

#### Filter components

You can control which components are visible and how they are displayed in Nuxt Studio using the `editor.components` option in your `nuxt.config.ts`.

This is useful if you want to hide specific components or only show a subset.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    editor: {
      components: {
        // White-list: If defined, ONLY these components will be visible
        include: ['Content*', 'MySpecificComponent'],

        // Black-list: These components will be hidden
        exclude: ['HiddenComponent', 'content/prose/**']
      }
    }
  }
})
```

Patterns support glob syntax (`*`, `**`) and can match against:

- **Component Name**: e.g. `Button`, `Content*`
- **File Path**: If the pattern contains a `/`, e.g. `content/prose/**`

#### Organize Components

You can organize components into labeled groups in the editor's component picker using the `editor.components.groups` option. This is useful when your project has many components and you want to structure them by category.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    editor: {
      components: {
        groups: [
          { label: 'Content', include: ['content*'] },
          { label: 'Landing', include: ['landing*'] },
          { label: 'UI', include: ['app/components/ui/**'] },
        ],
        ungrouped: 'include',
      }
    }
  }
})
```

- **groups**: Array of `{ label, include }`. Each group appears as a separate section in the slash menu.
- **ungrouped**: `'include'` (default) shows unmatched components in a fallback group; `'omit'` hides them.

#### Icon libraries

Restrict every Studio icon picker (collection forms and Vue component props in the visual editor) to a specific set of [Iconify](https://icones.js.org/) libraries using `editor.iconLibraries`. Values are Iconify collection prefixes.

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    editor: {
      iconLibraries: ['material-symbols', 'lucide'],
    },
  },
})
```

Per-field `iconLibraries` in `.editor()` overrides this global list when set — see [Icon field option](https://nuxt.studio/content#iconlibraries-arraystring).

#### Commands

The `/` menu includes built-in TipTap sections (**Style** and **Insert**) for headings, lists, marks, images, and so on. Use `editor.commands.exclude` to hide specific built-in entries:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    editor: {
      commands: {
        exclude: ['blockquote', 'horizontalRule', 'video'],
      },
    },
  },
})
```

Pass `'style'` or `'insert'` to remove an entire section at once:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    editor: {
      commands: {
        exclude: ['style', 'insert'],
      },
    },
  },
})
```

Supported keys: `style`, `insert` (whole sections), plus `paragraph`, `heading1`–`heading4`, `bulletList`, `orderedList`, `blockquote`, `codeBlock`, `bold`, `italic`, `strike`, `code`, `image`, `video`, `horizontalRule`.

### Git

You can configure the Git behavior of Nuxt Studio by configuring the `git` object in your `nuxt.config.ts` file

#### Commit message prefix

Content editors may not be familiar with conventional commit format. You can configure a prefix to prepend to all commit messages for Commitizen/CI compatibility:

```ts [nuxt.config.ts]
export default defineNuxtConfig({
  studio: {
    git: {
      commit: {
        // Prefix to prepend (include trailing colon for conventional format)
        messagePrefix: 'content:'  // e.g. 'docs:', 'feat:', 'chore:'
      }
    }
  }
})
```

When set, user-entered messages like "Add 2 links on landing page" become "content: Add 2 links on landing page".


## Sitemap

See the full [sitemap](https://nuxt.studio/sitemap.md) for all pages.
