nuxthub-migration
Use when migrating NuxtHub projects or when user mentions NuxtHub Admin sunset, GitHub Actions deployment removal, self-hosting NuxtHub, or upgrading to v1/nightly. Covers v0.9.X self-hosting (stable) and v1/nightly multi-cloud (experimental, database/blob not ready).
Install
mkdir -p .claude/skills/nuxthub-migration && curl -L -o skill.zip "https://mcp.directory/api/skills/download/348" && unzip -o skill.zip -d .claude/skills/nuxthub-migration && rm skill.zipInstalls to .claude/skills/nuxthub-migration
About this skill
NuxtHub Migration
When to Use
Activate this skill when:
- User mentions NuxtHub Admin deprecation or sunset (Dec 31, 2025)
- Project uses
.github/workflows/nuxthub.ymlor NuxtHub GitHub Action - User wants to self-host NuxtHub on Cloudflare Workers
- User asks about migrating to v0.10 or nightly version
- Project has
NUXT_HUB_PROJECT_KEYorNUXT_HUB_PROJECT_DEPLOY_TOKENenv vars
Two-phase migration. Phase 1 is stable and recommended. Phase 2 is multi-cloud.
Phase 1: Self-Hosting (v0.9.X) - RECOMMENDED
Migrate from NuxtHub Admin / GitHub Actions to self-hosted Cloudflare Workers. No code changes required.
1.1 Remove GitHub Action Deployment
Delete .github/workflows/nuxthub.yml or any NuxtHub-specific GitHub Action. Workers CI (step 1.4) replaces this.
Remove deprecated env vars from CI/CD and .env:
NUXT_HUB_PROJECT_KEYNUXT_HUB_PROJECT_DEPLOY_TOKEN
Also remove any GitHub Actions secrets related to NuxtHub deployment.
Check and clean up Cloudflare Worker secrets:
npx wrangler secret list --name <worker-name>
npx wrangler secret delete NUXT_HUB_PROJECT_DEPLOY_TOKEN --name <worker-name>
1.2 Get or Create Cloudflare Resources
NuxtHub Admin already created resources in your Cloudflare account. Reuse them to preserve existing data.
List existing resources:
npx wrangler d1 list # Find existing D1 databases
npx wrangler kv namespace list # Find existing KV namespaces
npx wrangler r2 bucket list # Find existing R2 buckets
Look for resources named after your project. Use their IDs in wrangler.jsonc.
Only create new resources if none exist:
# D1 Database (if hub.database: true)
npx wrangler d1 create my-app-db
# KV Namespace (if hub.kv: true)
npx wrangler kv namespace create KV
# KV Namespace for cache (if hub.cache: true)
npx wrangler kv namespace create CACHE
# R2 Bucket (if hub.blob: true)
npx wrangler r2 bucket create my-app-bucket
1.3 Create wrangler.jsonc
Create wrangler.jsonc in project root. See references/wrangler-templates.md for full examples.
Minimal example with database:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-app",
"main": "dist/server/index.mjs",
"assets": { "directory": "dist/public" },
"compatibility_date": "2025-12-01",
"compatibility_flags": ["nodejs_compat"],
"d1_databases": [{ "binding": "DB", "database_name": "my-app-db", "database_id": "<from-wrangler-output>" }]
}
Note: Nuxt cloudflare-module preset outputs to
dist/, not.output/.
Required binding names:
| Feature | Binding | Type |
|---|---|---|
| Database | DB | D1 |
| KV | KV | KV Namespace |
| Cache | CACHE | KV Namespace |
| Blob | BLOB | R2 Bucket |
1.4 Set Up Workers Builds CI/CD
Ensure nuxt.config.ts uses the cloudflare_module preset:
nitro: { preset: 'cloudflare_module' }
In Cloudflare Dashboard:
- Workers & Pages → Create → Import from Git
- Connect GitHub/GitLab repository
- Configure build settings (both fields required):
- Build command:
pnpm build(ornpm run build) - Deploy command:
npx wrangler deploy
- Build command:
- Add environment variables (e.g., secrets, API keys)
Common mistake: Only setting deploy command. Build must run first to generate
.output/.
1.5 Configure Environment Variables (Optional)
For advanced features (blob presigned URLs, cache DevTools, AI):
NUXT_HUB_CLOUDFLARE_ACCOUNT_ID=<account-id>
NUXT_HUB_CLOUDFLARE_API_TOKEN=<token-with-appropriate-permissions>
# Feature-specific (as needed):
NUXT_HUB_CLOUDFLARE_BUCKET_ID=<bucket-id>
NUXT_HUB_CLOUDFLARE_CACHE_NAMESPACE_ID=<namespace-id>
1.6 Test Remote Development
npx nuxt dev --remote
Phase 1 Checklist
- Delete
.github/workflows/nuxthub.yml - Remove
NUXT_HUB_PROJECT_KEYandNUXT_HUB_PROJECT_DEPLOY_TOKENenv vars - Clean up old Worker secrets (
wrangler secret list/delete) - Get existing or create new Cloudflare resources (D1, KV, R2 as needed)
- Create
wrangler.jsoncwith bindings - Set
nitro.preset: 'cloudflare_module'in nuxt.config.ts - Connect repo to Cloudflare Workers Builds
- Test with
npx nuxt dev --remote
No code changes required. Keep hub.database: true, server/database/, hubDatabase(), and @nuxthub/core.
Phase 2: v0.10/Nightly - MULTI-CLOUD
Multi-cloud support (Cloudflare, Vercel, Deno, Netlify). Breaking changes from v0.9.X.
2.1 Update Package
pnpm remove @nuxthub/core
pnpm add @nuxthub/core-nightly
2.2 Update nuxt.config.ts
Before (v0.9.X):
hub: { database: true, kv: true, blob: true, cache: true }
After (v0.10):
hub: { db: 'sqlite', kv: true, blob: true, cache: true }
Key change: database: true → db: '<dialect>' (sqlite | postgresql | mysql)
2.3 Rename Database Directory
mv server/database server/db
Update imports: ~/server/database/ → ~/server/db/
Migrations generated via npx nuxt db generate go to server/db/migrations/{dialect}/.
2.4 Migrate Database API (hubDatabase → Drizzle)
Before:
const db = hubDatabase()
const users = await db.prepare('SELECT * FROM users').all()
After:
import { db, schema } from 'hub:db'
// Note: db and schema are auto-imported on server-side
const users = await db.select().from(schema.users)
2.5 Migrate KV API (hubKV → kv)
Before:
import { hubKV } from '#hub/server'
await hubKV().set('vue', { year: 2014 })
await hubKV().get('vue')
await hubKV().has('vue')
await hubKV().del('vue')
await hubKV().keys('vue:')
await hubKV().clear('vue:')
After:
import { kv } from 'hub:kv'
// Note: kv is auto-imported on server-side
await kv.set('vue', { year: 2014 })
await kv.get('vue')
await kv.has('vue')
await kv.del('vue')
await kv.keys('vue:')
await kv.clear('vue:')
Key change: hubKV() function call → kv direct object. Same methods, different access pattern.
2.6 Migrate Blob API (hubBlob → blob)
Before:
const blob = hubBlob()
await blob.put('file.txt', body, { contentType: 'text/plain' })
await blob.get('file.txt')
await blob.list({ prefix: 'uploads/' })
await blob.del('file.txt')
await blob.serve(event, 'file.txt')
After:
import { blob } from 'hub:blob'
// Note: blob is auto-imported on server-side
await blob.put('file.txt', body, { contentType: 'text/plain' })
await blob.get('file.txt')
await blob.list({ prefix: 'uploads/' })
await blob.del('file.txt')
await blob.serve(event, 'file.txt')
Key change: hubBlob() function call → blob direct object. Same methods, different access pattern.
2.7 New Import Pattern (Summary)
v0.10 uses virtual module imports. All are auto-imported on server-side:
import { db, schema } from 'hub:db' // Database
import { kv } from 'hub:kv' // KV Storage
import { blob } from 'hub:blob' // Blob Storage
2.8 CLI Commands
npx nuxt db generate # Generate migrations from schema
npx nuxt db migrate # Apply migrations
npx nuxt db mark-as-migrated [NAME] # Mark migration as applied without running
npx nuxt db drop <TABLE> # Drop a table
npx nuxt db sql [QUERY] # Execute SQL query
npx nuxt db sql < dump.sql # Execute SQL from file
# All commands support:
--cwd <dir> # Run in different directory
--dotenv <file> # Use different .env file
-v, --verbose # Verbose output
2.9 Provider-Specific Setup (Non-Cloudflare)
Database Providers
PostgreSQL:
pnpm add drizzle-orm drizzle-kit postgres @electric-sql/pglite
- Uses PGlite locally if no env vars set
- Uses postgres-js if
DATABASE_URL,POSTGRES_URL, orPOSTGRESQL_URLset
MySQL:
pnpm add drizzle-orm drizzle-kit mysql2
- Requires
DATABASE_URLorMYSQL_URLenv var
SQLite (Turso):
pnpm add drizzle-orm drizzle-kit @libsql/client
- Uses libsql locally at
.data/db/sqlite.db - Uses Turso if
TURSO_DATABASE_URLandTURSO_AUTH_TOKENset
KV Providers
| Provider | Package | Env Vars |
|---|---|---|
| Upstash | @upstash/redis | UPSTASH_REDIS_REST_URL, UPSTASH_REDIS_REST_TOKEN |
| Redis | ioredis | REDIS_URL |
| Cloudflare KV | - | KV binding in wrangler.jsonc |
| Deno KV | - | Auto on Deno Deploy |
| Vercel | - | KV_REST_API_URL, KV_REST_API_TOKEN |
Blob Providers
| Provider | Package | Config |
|---|---|---|
| Vercel Blob | @vercel/blob | Dashboard setup |
| Cloudflare R2 | - | BLOB binding in wrangler.jsonc |
| S3 | aws4fetch | S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_BUCKET, S3_REGION |
| Netlify Blobs | @netlify/blobs | NETLIFY_BLOB_STORE_NAME |
2.10 Database Hooks (For Nuxt Modules)
// Extend schema
nuxt.hook('hub:db:schema:extend', async ({ dialect, paths }) => {
paths.push(await resolvePath(`./schema/pages.${dialect}`))
})
// Add migration directories
nuxt.hook('hub:db:migrations:dirs', (dirs) => {
dirs.push(resolve('./db-migrations'))
})
// Post-migration queries (must be idempotent)
nuxt.hook('hub:db:queries:paths', (paths, dialect) => {
paths.push(resolve(`./db-queries/seed.${dialect}.sql`))
})
2.11 Schema Files
Schema can be in multiple locations:
server/db/schema.tsserver/db/schema.{dialect}.tsserver/db/schema/*.tsserver/db/schema/*.{dialect}.ts
Generated schema at .nuxt/hub/db/schema.mjs.
Deprecated Features (v0.10)
Cloudflare-specific features removed:
hubAI()- Use AI SDK with Workers AI ProviderhubBrowser()- PuppeteerhubVectorize()- VectorizehubAutoRAG()- AutoRAG
Phase 2 Checklist
- Complete Phase 1 first
- Replace
@nuxthub/corewith@nuxthub/core-nightly - Change
hub.database: truetohub.db: 'sqlite'(or other dialect) - Rename
server/database/toserver/db/ - Update imports from
~/server/database/to~/server/db/ - Migrate
hubDatabase()→dbfromhub:db - Migrate
hubKV()→kvfromhub:kv - Migrate
hubBlob()→blobfromhub:blob - Update table references:
tables.X→schema.X - Run
npx nuxt db generateto generate migrations - Test all database, KV, and blob operations
Quick Reference
| Aspect | v0.9.X (Phase 1) | v0.10/Nightly (Phase 2) |
|---|---|---|
| Package | @nuxthub/core | @nuxthub/core-nightly |
| Database config | hub.database: true | hub.db: 'sqlite' |
| Directory | server/database/ | server/db/ |
| DB access | hubDatabase() | db from hub:db |
| Schema access | N/A | schema from hub:db |
| KV access | hubKV() | kv from hub:kv |
| Blob access | hubBlob() | blob from hub:blob |
| Migrations | Manual SQL | npx nuxt db generate |
| Cloud support | Cloudflare only | Multi-cloud |
Resources
- Self-hosting changelog
- Deploy docs
- v0.10 Installation
- v0.10 Database
- v0.10 KV
- v0.10 Blob
- Legacy v0.9 docs
references/wrangler-templates.md- Cloudflare wrangler.jsonc templates
More by onmax
View all →You might also like
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
drawio-diagrams-enhanced
jgtolentino
Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.
godot
bfollington
This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.
nano-banana-pro
garg-aayush
Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.
ui-ux-pro-max
nextlevelbuilder
"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."
rust-coding-skill
UtakataKyosui
Guides Claude in writing idiomatic, efficient, well-structured Rust code using proper data modeling, traits, impl organization, macros, and build-speed best practices.
Stay ahead of the MCP ecosystem
Get weekly updates on new skills and servers.