Quick Start

This guide will walk you through creating your first API and admin panel with Nuxt Auto in under 10 minutes.

Quick Start

This guide will walk you through creating your first API and admin panel with Nuxt Auto in under 10 minutes.

Project Setup

1. Create a New Nuxt Project

npx nuxi@latest init my-app
cd my-app

2. Install Nuxt Auto

npm install @websideproject/nuxt-auto-api @websideproject/nuxt-auto-admin @nuxt/ui
npm install drizzle-orm better-sqlite3
npm install -D drizzle-kit @types/better-sqlite3

3. Configure Nuxt

Update nuxt.config.ts:

export default defineNuxtConfig({
  modules: [
    '@nuxt/ui',
    '@websideproject/nuxt-auto-api',
    '@websideproject/nuxt-auto-admin',
  ],

  autoApi: {
    prefix: '/api',
    database: {
      client: 'better-sqlite3',
    },
  },

  autoAdmin: {
    prefix: '/admin',
    branding: {
      title: 'Blog Admin',
    },
  },

  compatibilityDate: '2024-01-01',
})

Create Your Schema

1. Define Database Schema

Create server/database/schema.ts:

import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'

export const posts = sqliteTable('posts', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  title: text('title').notNull(),
  slug: text('slug').notNull().unique(),
  content: text('content'),
  published: integer('published', { mode: 'boolean' }).default(false),
  createdAt: integer('created_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
  updatedAt: integer('updated_at', { mode: 'timestamp' }).$defaultFn(() => new Date()),
})

export const authors = sqliteTable('authors', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  bio: text('bio'),
})

2. Initialize Database

Create server/plugins/database.ts:

import { drizzle } from 'drizzle-orm/better-sqlite3'
import Database from 'better-sqlite3'
import { initializeDatabase } from '@websideproject/nuxt-auto-api/database'
import * as schema from '../database/schema'

export default defineNitroPlugin(() => {
  const sqlite = new Database('sqlite.db')
  const db = drizzle(sqlite, { schema })

  initializeDatabase(db, 'better-sqlite3')
})

3. Configure Drizzle Kit

Create drizzle.config.ts:

import type { Config } from 'drizzle-kit'

export default {
  schema: './server/database/schema.ts',
  out: './drizzle',
  driver: 'better-sqlite3',
  dbCredentials: {
    url: 'sqlite.db',
  },
} satisfies Config

4. Generate Database

npx drizzle-kit push:sqlite

Register Resources

1. Create a Module

Create modules/base/index.ts:

import { defineNuxtModule, createResolver } from '@nuxt/kit'
import { createModuleImport } from '@websideproject/nuxt-auto-api'

export default defineNuxtModule({
  meta: {
    name: 'base',
  },
  setup(_options, nuxt) {
    const resolver = createResolver(import.meta.url)

    nuxt.hook('autoApi:registerSchema', (registry) => {
      registry.register('posts', {
        schema: createModuleImport(
          resolver.resolve('../../server/database/schema'),
          'posts'
        ),
      })

      registry.register('authors', {
        schema: createModuleImport(
          resolver.resolve('../../server/database/schema'),
          'authors'
        ),
      })
    })
  },
})

2. Load the Module

Update nuxt.config.ts to include your module:

export default defineNuxtConfig({
  modules: [
    '@nuxt/ui',
    '@websideproject/nuxt-auto-api',
    '@websideproject/nuxt-auto-admin',
    './modules/base',  // Add this
  ],

  // ... rest of config
})

Test Your API

Start the development server:

npm run dev

API Endpoints

Your API is now available at:

GET    /api/posts           # List all posts
GET    /api/posts/:id       # Get single post
POST   /api/posts           # Create post
PATCH  /api/posts/:id       # Update post
DELETE /api/posts/:id       # Delete post

GET    /api/authors         # List all authors
GET    /api/authors/:id     # Get single author
POST   /api/authors         # Create author
PATCH  /api/authors/:id     # Update author
DELETE /api/authors/:id     # Delete author

Test with cURL

# Create an author
curl -X POST http://localhost:3000/api/authors \
  -H "Content-Type: application/json" \
  -d '{"name":"John Doe","email":"john@example.com"}'

# Create a post
curl -X POST http://localhost:3000/api/posts \
  -H "Content-Type: application/json" \
  -d '{"title":"Hello World","slug":"hello-world","content":"My first post"}'

# List posts
curl http://localhost:3000/api/posts

Access Admin Panel

Navigate to http://localhost:3000/admin

You'll see:

  • Posts resource with list, create, edit, and delete pages
  • Authors resource with full CRUD operations
  • Auto-generated forms based on your schema

Use in Frontend

1. List Posts

<template>
  <div>
    <h1>Blog Posts</h1>

    <div v-if="isLoading">Loading...</div>

    <ul v-else>
      <li v-for="post in posts?.data" :key="post.id">
        <h2>{{ post.title }}</h2>
        <p>{{ post.content }}</p>
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
const { data: posts, isLoading } = useAutoApiList('posts', {
  filter: { published: true },
  sort: '-createdAt',
  limit: 10,
})
</script>

2. Create Post

<template>
  <form @submit.prevent="handleSubmit">
    <input v-model="form.title" placeholder="Title" required>
    <textarea v-model="form.content" placeholder="Content"></textarea>
    <button type="submit" :disabled="isPending">
      {{ isPending ? 'Creating...' : 'Create Post' }}
    </button>
  </form>
</template>

<script setup lang="ts">
const form = reactive({
  title: '',
  slug: '',
  content: '',
})

const { mutateAsync: createPost, isPending } = useAutoApiMutation('posts', 'create', {
  toast: {
    success: { title: 'Post created!' },
    error: { title: 'Failed to create post' }
  }
})

const handleSubmit = async () => {
  form.slug = form.title.toLowerCase().replace(/\s+/g, '-')
  await createPost(form)
  Object.assign(form, { title: '', slug: '', content: '' })
}
</script>

Customize Admin Panel

Configure Resources

Update nuxt.config.ts:

export default defineNuxtConfig({
  // ... modules

  autoAdmin: {
    prefix: '/admin',
    branding: {
      title: 'Blog Admin',
      logo: '/logo.svg',
    },
    resources: {
      posts: {
        displayName: 'Blog Posts',
        icon: 'i-heroicons-document-text',
        group: 'Content',
        listFields: ['id', 'title', 'published', 'createdAt'],
        formFields: {
          edit: [
            { name: 'title', widget: 'TextInput', required: true },
            { name: 'slug', widget: 'SlugInput', options: { generateFrom: 'title' } },
            { name: 'content', widget: 'MarkdownEditor' },
            { name: 'published', widget: 'Checkbox' },
          ],
        },
      },
      authors: {
        displayName: 'Authors',
        icon: 'i-heroicons-user-group',
        group: 'Content',
        listFields: ['id', 'name', 'email'],
      },
    },
  },
})

Next Steps

Now that you have a working setup:

Learn More About Auto API

Learn More About Auto Admin

Example Project

Clone the example project for a complete working setup:

git clone https://github.com/websideproject/nuxt-auto
cd nuxt-auto/apps/playground
bun install
bun dev

Visit http://localhost:3000 to see the example in action.

Need a Landing Page?

Modern landing pages with optional modules (blog, docs, forms, i18n). Let's discuss your project.

Build Your MVP

Full-stack SaaS development. Expert in database design, multi-tenancy, and scalable architecture.

Deployment Help

Dockerize your backend, set up CI/CD pipelines, deploy to Cloudflare or Hetzner. Early-stage setup.

Suggest a SaaS Tool

Missing a calculator or tool? Suggest what you'd like to see on our site.