smithery.ai

Add Database Table

Add a new database table with Drizzle ORM

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 7,800 B
  • docs SUMMARY.md 67 B

History

  1. First recorded snapshot · 1 installs

SKILL.md

Add Database Table Skill

You are helping add a new database table to a Next.js application using Drizzle ORM with PostgreSQL.

Context

  • ORM: Drizzle ORM
  • Database: PostgreSQL
  • Schema Location: apps/web/lib/server/db/schema/
  • Migration Tool: Drizzle Kit

Workflow

1. Understand Requirements

Ask the user:

  • What is the table name? (use singular form, e.g., "user", "post")
  • What fields are needed?
  • What data types for each field?
  • Are there relationships to other tables?
  • What constraints? (unique, not null, default values)

2. Create Schema File

Create a new file in lib/server/db/schema/:

// lib/server/db/schema/[table-name]s.ts
import {
  pgTable,
  text,
  timestamp,
  uuid,
  boolean,
  integer,
  varchar,
} from "drizzle-orm/pg-core"
import { createInsertSchema, createSelectSchema } from "drizzle-zod"
import { relations } from "drizzle-orm"

// Define the table
export const [tableName]s = pgTable("[table_name]", {
  id: uuid("id").primaryKey().defaultRandom(),

  // Add your fields here
  // Examples:
  // name: text("name").notNull(),
  // email: varchar("email", { length: 255 }).notNull().unique(),
  // age: integer("age"),
  // isActive: boolean("isActive").default(true),

  // Timestamps (always include)
  createdAt: timestamp("createdAt").notNull().defaultNow(),
  updatedAt: timestamp("updatedAt").notNull().defaultNow(),
})

// Define relations (if any)
export const [tableName]sRelations = relations([tableName]s, ({ one, many }) => ({
  // Example: many-to-one
  // user: one(users, {
  //   fields: [tableName]s.userId],
  //   references: [users.id],
  // }),

  // Example: one-to-many
  // posts: many(posts),
}))

// Generate Zod schemas for validation
export const insert[TableName]Schema = createInsertSchema([tableName]s)
export const select[TableName]Schema = createSelectSchema([tableName]s)

// Export TypeScript types
export type [TableName] = typeof [tableName]s.$inferSelect
export type New[TableName] = typeof [tableName]s.$inferInsert

3. Common Field Types

// Text fields
text("field_name")                          // Unlimited text
varchar("field_name", { length: 255 })      // Variable length (max 255)

// Numbers
integer("field_name")                       // Integer
serial("field_name")                        // Auto-increment
real("field_name")                          // Floating point

// Booleans
boolean("field_name")

// Dates
timestamp("field_name")                     // Date + time
date("field_name")                          // Date only

// UUIDs
uuid("field_name")

// JSON
json("field_name")                          // JSON field
jsonb("field_name")                         // Binary JSON (faster)

4. Common Constraints

// Not null
.notNull()

// Unique
.unique()

// Default value
.default(value)
.defaultNow()                               // For timestamps
.defaultRandom()                            // For UUIDs

// Primary key
.primaryKey()

// Foreign key
.references(() => users.id, { onDelete: "cascade" })

5. Foreign Key Example

import { users } from "./users"

export const posts = pgTable("post", {
  id: uuid("id").primaryKey().defaultRandom(),
  title: text("title").notNull(),
  content: text("content").notNull(),

  // Foreign key to users table
  userId: uuid("userId")
    .notNull()
    .references(() => users.id, { onDelete: "cascade" }),

  createdAt: timestamp("createdAt").notNull().defaultNow(),
  updatedAt: timestamp("updatedAt").notNull().defaultNow(),
})

// Define the relation
export const postsRelations = relations(posts, ({ one }) => ({
  user: one(users, {
    fields: [posts.userId],
    references: [users.id],
  }),
}))

6. Export from Index

Add export to lib/server/db/schema/index.ts:

export * from "./users"
export * from "./posts"
export * from "./[new-table]"  // Add this line

7. Push Schema to Database

Run the migration:

# Push schema changes to database (development)
npm run db:push

# Or generate migration file (production)
npm run db:generate
npm run db:migrate

8. Example Queries

Show the user how to query the new table:

import { db } from "@/lib/server/db"
import { [tableName]s } from "@/lib/server/db/schema"
import { eq, and, or, gt } from "drizzle-orm"

// Find all
const all = await db.query.[tableName]s.findMany()

// Find one
const one = await db.query.[tableName]s.findFirst({
  where: eq([tableName]s.id, id),
})

// With relations
const withRelations = await db.query.[tableName]s.findFirst({
  where: eq([tableName]s.id, id),
  with: {
    relatedTable: true,
  },
})

// Insert
const [created] = await db
  .insert([tableName]s)
  .values({
    // field: value,
  })
  .returning()

// Update
const [updated] = await db
  .update([tableName]s)
  .set({
    // field: value,
    updatedAt: new Date(),
  })
  .where(eq([tableName]s.id, id))
  .returning()

// Delete
await db
  .delete([tableName]s)
  .where(eq([tableName]s.id, id))

Validation with Zod

The generated Zod schemas can be used for validation:

import { insert[TableName]Schema } from "@/lib/server/db/schema"

// In a server action
export async function create[TableName](data: unknown) {
  try {
    // Validate with Zod
    const validated = insert[TableName]Schema.parse(data)

    // Insert into database
    const [created] = await db
      .insert([tableName]s)
      .values(validated)
      .returning()

    return { success: true, data: created }
  } catch (error) {
    return { success: false, error: "Validation failed" }
  }
}

Custom Zod Validation

You can extend the generated schemas:

import { z } from "zod"

export const customInsertSchema = insert[TableName]Schema.extend({
  email: z.string().email(),
  age: z.number().min(0).max(150),
  password: z.string().min(8),
})

Complete Example: Blog Posts Table

// lib/server/db/schema/posts.ts
import { pgTable, text, timestamp, uuid, boolean } from "drizzle-orm/pg-core"
import { createInsertSchema, createSelectSchema } from "drizzle-zod"
import { relations } from "drizzle-orm"
import { users } from "./users"

export const posts = pgTable("post", {
  id: uuid("id").primaryKey().defaultRandom(),
  title: text("title").notNull(),
  content: text("content").notNull(),
  slug: text("slug").notNull().unique(),
  published: boolean("published").default(false),

  // Foreign key
  authorId: uuid("authorId")
    .notNull()
    .references(() => users.id, { onDelete: "cascade" }),

  createdAt: timestamp("createdAt").notNull().defaultNow(),
  updatedAt: timestamp("updatedAt").notNull().defaultNow(),
})

// Relations
export const postsRelations = relations(posts, ({ one }) => ({
  author: one(users, {
    fields: [posts.authorId],
    references: [users.id],
  }),
}))

// Zod schemas
export const insertPostSchema = createInsertSchema(posts)
export const selectPostSchema = createSelectSchema(posts)

// TypeScript types
export type Post = typeof posts.$inferSelect
export type NewPost = typeof posts.$inferInsert

Checklist

Before completing, ensure:

  • Schema file created in lib/server/db/schema/
  • Table name is singular (e.g., "user", not "users")
  • All fields have appropriate types
  • Constraints applied (notNull, unique, etc.)
  • Foreign keys defined correctly
  • Relations defined (if applicable)
  • Zod schemas generated
  • TypeScript types exported
  • Exported from schema/index.ts
  • Migration run (npm run db:push)
  • Example queries provided

Now help the user create their database table!