Skip to content

Instantly share code, notes, and snippets.

@blefnk
Last active March 22, 2025 05:47
Show Gist options
  • Save blefnk/0bd43e6b1b37ee58cf769f04109e151d to your computer and use it in GitHub Desktop.
Save blefnk/0bd43e6b1b37ee58cf769f04109e151d to your computer and use it in GitHub Desktop.
Next.js 15 Project Bootstrapper with Bun, Drizzle ORM, and shadcn/ui (Windows, MacOS, Linux)

Next.js 15 Project Bootstrapper with Bun, Drizzle ORM, and shadcn/ui (Windows, MacOS, Linux)

A fullstack setup script for bootstrapping a modern fullstack Next.js application using Bun. This script automates the entire initialization process with production-ready configurations and best practices.

Features

  • Next.js with App Router and TypeScript
  • Bun package manager and script runner for improved performance
  • Tailwind CSS with automatic migrator from v3 to v4
  • Dual linting/formatting with ESLint and Biome
  • Drizzle ORM configured for PostgreSQL databases (optional)
  • shadcn/ui component library with custom path aliases
  • Environment templates with authentication setup as starting point
  • Code quality npm scripts for development, linting, and type checking
  • VS Code project integration

Windows PowerShell Usage

Save the script as setup-nextjs.ps1 and run it from PowerShell with:

.\setup-nextjs.ps1

macOS/Linux Usage

Save the script as setup-nextjs.sh, make it executable, and run:

chmod +x setup-nextjs.sh
./setup-nextjs.sh

Or simply copy and paste commands as needed into your terminal.

Prerequisites

  • Bun installed (https://bun.sh)
  • Node.js installed
  • PostgreSQL database (for Drizzle ORM) (optional)
  • VS Code (optional, for the final code . command)

This zero-to-production bootstrapper creates a fully configured development environment that follows modern best practices, saving minutes of manual setup and configuration.

# nextjs
bun x --bun create-next-app@latest my-app --use-bun --typescript --tailwind --eslint --app --src-dir --turbopack --import-alias "~/*"
# cd
cd my-app
# env
echo 'DATABASE_URL=""
BETTER_AUTH_SECRET=""
BETTER_AUTH_URL="http://localhost:3000"' > .env.example
cp .env.example .env
# eslint
bun add -D eslint @eslint/js typescript typescript-eslint
rm eslint.config.mjs
echo '// @ts-check
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
export default tseslint.config(
eslint.configs.recommended,
tseslint.configs.recommended,
tseslint.configs.stylistic,
{ ignores: [ "node_modules", ".vercel", ".next", ".git" ] },
);' > eslint.config.js
# biome
bun add --dev --exact @biomejs/biome
bunx biome init
bun x --bun json -I -f biome.json -e 'this.files.ignore = ["node_modules", ".vercel", ".next", ".git"]; this.formatter = { enabled: true, indentStyle: "space", indentWidth: 2, lineWidth: 80 }'
# drizzle
bun add drizzle-orm pg dotenv && bun add -D drizzle-kit tsx @types/pg
echo 'import "dotenv/config";
import { defineConfig } from "drizzle-kit";
export default defineConfig({
out: "./drizzle",
schema: "./src/db/schema.ts",
dialect: "postgresql",
dbCredentials: {
url: process.env.DATABASE_URL ?? "",
},
});' > drizzle.config.ts
# scripts
bun x --bun json -I -f package.json -e 'this.type="module"; this.scripts.ui="bun x --bun shadcn@canary add"; this.scripts.lint="eslint ."; this.scripts.format="bunx biome check --write ."; this.scripts.typecheck="tsc --noEmit"; this.scripts.check="bun typecheck && bun lint && bun format"; this.scripts.db="drizzle-kit"; delete this.scripts.start'
# shadcn
bun x --bun @tailwindcss/upgrade --force
bun x --bun shadcn@canary init -d
bun x --bun json -I -f components.json -e 'this.aliases.components = "~/ui"; this.aliases.ui = "~/ui"'
# postcss config
rm postcss.config.mjs
echo 'export default {
plugins: {
"@tailwindcss/postcss": {},
},
};' > postcss.config.js
# next config
rm next.config.ts
echo 'import type { NextConfig } from "next";
const nextConfig = {
eslint: { ignoreDuringBuilds: true },
} satisfies NextConfig;
export default nextConfig;' > next.config.ts
# final touches
bun update --latest
bun check
bun run build
# components
mkdir src/ui/components
bun ui button card form input label separator skeleton sonner textarea
echo 'import { Button } from "~/ui/button";
export default function Header() {
return <Button>Login</Button>;
}' > src/ui/components/header.tsx
# ide
code .
@blefnk
Copy link
Author

blefnk commented Feb 26, 2025

My very first gist is live! Follow my profile to catch the next cool ones! 🦾

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment