Skip to main content
skill CX Codex

bun-nuxt — Claude Code skill: run Nuxt 3 on the Bun runtime

A skill that tells the agent how to run Nuxt 3 on Bun: scripts, Nitro preset, server routes and deployment. Useful when you want off Node.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add secondsky/claude-skills --skill bun-nuxt -a claude-code
Open on GitHub

What bun-nuxt does

The skill hands the agent ready-made patterns for pairing Nuxt 3 with Bun. You get the startup commands (bunx nuxi@latest init, bun install, bun run dev), a script variant with the bun --bun flag, and a nuxt.config.ts with nitro.preset: "bun". Skip that preset and server imports like bun:sqlite fail with Cannot find bun:sqlite — worth checking the config when a build complains about the module.

A separate chunk covers the server side: server/api routes, middleware, file handling with Bun.file, bun:sqlite utilities, Nitro plugins and scheduled tasks. There is a table of common errors and a deployment section — building with NITRO_PRESET=bun, running .output/server/index.mjs, and a Dockerfile based on oven/bun:1.

On installing packages the skill is blunt: bunx nuxi init downloads and executes remote code. Bun blocks post-install scripts by default, so allow them per package through trustedDependencies in package.json. It also suggests setting minimumReleaseAge in bunfig.toml and scoring packages with the Socket CLI. For the full setup it points to the dependency-upgrade skill.

What it helps with

  • move an existing Nuxt project onto the Bun runtime
  • configure the Nitro preset so Bun server APIs work
  • wire bun:sqlite into server routes and utilities
  • build a production Docker image for Nuxt on Bun
  • debug errors like Cannot find bun:sqlite or Hydration mismatch

Example prompts for the agent

  • Set up Nuxt 3 on Bun: dev and build scripts with bun --bun, Nitro preset bun
  • Add a server route backed by bun:sqlite that returns the user list
  • Write a Dockerfile for Nuxt on oven/bun:1 and run .output/server/index.mjs

How to install bun-nuxt

1Skills CLI (Vercel)

npx skills add secondsky/claude-skills --skill bun-nuxt -a claude-code

2Manually: put the files in place

~/.claude/skills/bun-nuxt/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/bun-nuxt/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about bun-nuxt

How do I install bun-nuxt in Claude?

Run npx skills add secondsky/claude-skills --skill bun-nuxt -a claude-code. The skill file then lives at ~/.claude/skills/bun-nuxt/SKILL.md.

What does the bun-nuxt skill do?

It guides the agent through running Nuxt 3 on Bun: scripts, Nitro config, server routes, database access and deployment. Common errors are covered too.

What should I watch out for when installing dependencies?

bunx nuxi init downloads and runs remote code. Bun disables post-install scripts by default, so allow them per package via trustedDependencies and hold back fresh versions with minimumReleaseAge.

Source text

SKILL.md · MIT
---
name: bun-nuxt
description: Use when running Nuxt 3 with Bun runtime, building Vue/Nuxt apps with Bun, or configuring Nuxt projects to use Bun for development and production.
license: MIT
---

# Bun Nuxt

Run Nuxt 3 applications with Bun for faster development.

## Quick Start

```bash
# Create new Nuxt project
bunx nuxi@latest init my-app
cd my-app

# Install dependencies
bun install

# Development
bun run dev

# Build
bun run build

# Preview production
bun run preview
```

## Secure Installation

Scaffolding tools like `bunx nuxi init` download and execute remote code. Before running, follow supply chain security best practices:

- **Block post-install scripts** — Bun disables them by default; allow specific packages via `trustedDependencies` in `package.json`
- **Cooldown period** — Configure `minimumReleaseAge` in `bunfig.toml` to wait 7 days for new versions
- **Audit before installing** — Run `socket package score npm <pkg>` or use `socket npm install <pkg>` to check packages

Load the `dependency-upgrade` skill for full security configuration including Socket CLI integration, cooldown setup, lockfile validation, and CI enforcement.

## Project Setup

### package.json

```json
{
  "scripts": {
    "dev": "nuxt dev",
    "build": "nuxt build",
    "generate": "nuxt generate",
    "preview": "nuxt preview",
    "postinstall": "nuxt prepare"
  },
  "dependencies": {
    "nuxt": "^4.0.0",
    "vue": "^3.5.0"
  }
}
```

### Use Bun Runtime

```json
{
  "scripts": {
    "dev": "bun --bun nuxt dev",
    "build": "bun --bun nuxt build",
    "preview": "bun --bun .output/server/index.mjs"
  }
}
```

## Configuration

### nuxt.config.ts

```typescript
export default defineNuxtConfig({
  // Enable SSR
  ssr: true,

  // Nitro configuration
  nitro: {
    // Use Bun preset
    preset: "bun",

    // External packages
    externals: {
      external: ["bun:sqlite"],
    },
  },

  // Development
  devServer: {
    port: 3000,
  },

  // Modules
  modules: ["@nuxt/ui", "@pinia/nuxt"],
});
```

## Using Bun APIs

### Server Routes

```typescript
// server/api/users.ts
import { Database } from "bun:sqlite";

export default defineEventHandler(async (event) => {
  const db = new Database("data.sqlite");
  const users = db.query("SELECT * FROM users").all();
  db.close();

  return users;
});
```

### Server Middleware

```typescript
// server/middleware/auth.ts
export default defineEventHandler(async (event) => {
  const token = getHeader(event, "Authorization");

  if (!token && event.path.startsWith("/api/protected")) {
    throw createError({
      statusCode: 401,
      message: "Unauthorized",
    });
  }
});
```

### File Operations

```typescript
// server/api/files/[name].ts
export default defineEventHandler(async (event) => {
  const name = getRouterParam(event, "name");
  const file = Bun.file(`./data/${name}`);

  if (!(await file.exists())) {
    throw createError({
      statusCode: 404,
      message: "File not found",
    });
  }

  return file.text();
});
```

## Composables

### useFetch with Server Data

```vue
<script setup lang="ts">
// Fetches from server/api/users.ts
const { data: users, pending, error } = await useFetch("/api/users");
</script>

<template>
  <div v-if="pending">Loading...</div>
  <div v-else-if="error">Error: {{ error.message }}</div>
  <ul v-else>
    <li v-for="user in users" :key="user.id">{{ user.name }}</li>
  </ul>
</template>
```

### Server-Only Composables

```typescript
// composables/useDatabase.ts
export const useDatabase = () => {
  // Only runs on server
  if (process.server) {
    const { Database } = require("bun:sqlite");
    return new Database("data.sqlite");
  }
  return null;
};
```

## Server Utilities

### H3 Event Handling

```typescript
// server/api/users.post.ts
export default defineEventHandler(async (event) => {
  // Read body
  const body = await readBody(event);

  // Get query params
  const query = getQuery(event);

  // Get headers
  const auth = getHeader(event, "Authorization");

  // Get cookies
  const session = getCookie(event, "session");

  // Set cookie
  setCookie(event, "visited", "true", {
    httpOnly: true,
    maxAge: 60 * 60 * 24,
  });

  return { success: true };
});
```

### Database Utility

```typescript
// server/utils/db.ts
import { Database } from "bun:sqlite";

let db: Database | null = null;

export function getDb() {
  if (!db) {
    db = new Database("data.sqlite");
    db.run(`
      CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY,
        name TEXT NOT NULL
      )
    `);
  }
  return db;
}
```

```typescript
// server/api/users.ts
export default defineEventHandler(() => {
  const db = getDb();
  return db.query("SELECT * FROM users").all();
});
```

## Nitro Features

### Server Plugins

```typescript
// server/plugins/database.ts
export default defineNitroPlugin((nitroApp) => {
  // Initialize on startup
  console.log("Database initialized");

  // Cleanup on shutdown
  nitroApp.hooks.hook("close", () => {
    console.log("Closing database");
  });
});
```

### Scheduled Tasks

```typescript
// server/tasks/cleanup.ts
export default defineTask({
  meta: {
    name: "cleanup",
    description: "Clean old data",
  },
  run() {
    const db = getDb();
    db.run("DELETE FROM logs WHERE created_at < ?", [
      Date.now() - 7 * 24 * 60 * 60 * 1000,
    ]);
    return { result: "Cleaned" };
  },
});
```

## Deployment

### Build for Bun

```bash
# Build with Bun preset
NITRO_PRESET=bun bun run build

# Run production server
bun .output/server/index.mjs
```

### Docker

```dockerfile
FROM oven/bun:1 AS builder

WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile

COPY . .
RUN bun run build

FROM oven/bun:1

WORKDIR /app
COPY --from=builder /app/.output /app/.output

EXPOSE 3000

CMD ["bun", ".output/server/index.mjs"]
```

### Environment Variables

```bash
# .env
NUXT_PUBLIC_API_URL=https://api.example.com
DATABASE_URL=./data.sqlite
```

```typescript
// Access in code
const config = useRuntimeConfig();
console.log(config.public.apiUrl);
console.log(config.databaseUrl); // Server only
```

```typescript
// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    databaseUrl: "",
    public: {
      apiUrl: "",
    },
  },
});
```

## Common Errors

| Error | Cause | Fix |
|-------|-------|-----|
| `Cannot find bun:sqlite` | Wrong preset | Set `nitro.preset: "bun"` |
| `Module parse failed` | Build issue | Clear `.nuxt` and rebuild |
| `Hydration mismatch` | Server/client diff | Check async data |
| `EADDRINUSE` | Port in use | Change port or kill process |

## When to Load References

Load `references/nitro.md` when:
- Advanced Nitro configuration
- Storage drivers
- Cache handlers

Load `references/deployment.md` when:
- Edge deployment
- Cloudflare Workers
- Vercel/Netlify

© secondsky · MIT · secondsky/claude-skills

Similar skills

Everything for Frontend and UI →

From the same set94

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor