Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "nextjs-fullstack-scaffold",
|
||||||
|
"description": "This skill should be used when the user requests to scaffold, create, or initialize a full-stack Next.js application with a modern tech stack including Next.js 16, React 19, TypeScript, Tailwind CSS v4, shadcn/ui, Supabase auth, Prisma ORM, and comprehensive testing setup. Use it for creating production-ready starter templates with authentication, protected routes, forms, and example features. Trigger terms scaffold, create nextjs app, initialize fullstack, starter template, boilerplate, setup n",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Hope Overture",
|
||||||
|
"email": "support@worldbuilding-app-skills.dev"
|
||||||
|
},
|
||||||
|
"skills": [
|
||||||
|
"./skills"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# nextjs-fullstack-scaffold
|
||||||
|
|
||||||
|
This skill should be used when the user requests to scaffold, create, or initialize a full-stack Next.js application with a modern tech stack including Next.js 16, React 19, TypeScript, Tailwind CSS v4, shadcn/ui, Supabase auth, Prisma ORM, and comprehensive testing setup. Use it for creating production-ready starter templates with authentication, protected routes, forms, and example features. Trigger terms scaffold, create nextjs app, initialize fullstack, starter template, boilerplate, setup n
|
||||||
65
plugin.lock.json
Normal file
65
plugin.lock.json
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:hopeoverture/worldbuilding-app-skills:plugins/nextjs-fullstack-scaffold",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "67aa5af567213aab62e2ac8ceaed39cc8cc7e387",
|
||||||
|
"treeHash": "0c7cbaa5775fee24e131ea864a3c8fc5ab478765074777b0fc1d1a33a74dde7f",
|
||||||
|
"generatedAt": "2025-11-28T10:17:29.996124Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "nextjs-fullstack-scaffold",
|
||||||
|
"description": "This skill should be used when the user requests to scaffold, create, or initialize a full-stack Next.js application with a modern tech stack including Next.js 16, React 19, TypeScript, Tailwind CSS v4, shadcn/ui, Supabase auth, Prisma ORM, and comprehensive testing setup. Use it for creating production-ready starter templates with authentication, protected routes, forms, and example features. Trigger terms scaffold, create nextjs app, initialize fullstack, starter template, boilerplate, setup n",
|
||||||
|
"version": "1.0.0"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "72ef742a6eae6ab5a6741da92fc2ae458c9a1361074b61e8067a29700dce5f10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "efc26c5375c6ea78633ef25270cbd48ccb4d077a5b29b09d1f4b864fea06dcb8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/nextjs-fullstack-scaffold/SKILL.md",
|
||||||
|
"sha256": "f43c34728037939f2220df1c2dbf54856cc4eac57297fcf8fe95da8d8bf42177"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/nextjs-fullstack-scaffold/references/stack-architecture.md",
|
||||||
|
"sha256": "b46560ea9564d44748985b7a8747a917a2ce3c54ce507c0d9899999b4fd2f217"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/nextjs-fullstack-scaffold/references/implementation-checklist.md",
|
||||||
|
"sha256": "27419a75f5432ade5a456d4f33bad23bc39d966b9b3f3b53dc13dbd31f53ab75"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/nextjs-fullstack-scaffold/scripts/scaffold.py",
|
||||||
|
"sha256": "ab48fba1848db3f124a0360855bed3b5761b09a3047b7d179e5f946673e60f1d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/nextjs-fullstack-scaffold/assets/folder-structure.txt",
|
||||||
|
"sha256": "20ec2be1ffebe621ec86addfadeeff9eae8b4aa6c63bebdc3d2fe4be04f1e8b5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "skills/nextjs-fullstack-scaffold/assets/templates/package.template.json",
|
||||||
|
"sha256": "0cac7aea9cf49d95a676e0cd66c856374d7a3db369268a20f4cfca2cd20b8bba"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "0c7cbaa5775fee24e131ea864a3c8fc5ab478765074777b0fc1d1a33a74dde7f"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
190
skills/nextjs-fullstack-scaffold/SKILL.md
Normal file
190
skills/nextjs-fullstack-scaffold/SKILL.md
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
---
|
||||||
|
name: nextjs-fullstack-scaffold
|
||||||
|
description: This skill should be used when the user requests to scaffold, create, or initialize a full-stack Next.js application with a modern tech stack including Next.js 16, React 19, TypeScript, Tailwind CSS v4, shadcn/ui, Supabase auth, Prisma ORM, and comprehensive testing setup. Use it for creating production-ready starter templates with authentication, protected routes, forms, and example features. Trigger terms scaffold, create nextjs app, initialize fullstack, starter template, boilerplate, setup nextjs, production template, full-stack setup, nextjs supabase, nextjs prisma.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Next.js Full-Stack Scaffold
|
||||||
|
|
||||||
|
To scaffold a production-grade Next.js 16 full-stack application with modern tooling and best practices, follow these steps systematically.
|
||||||
|
|
||||||
|
## Prerequisites Check
|
||||||
|
|
||||||
|
Before scaffolding, verify the target directory:
|
||||||
|
1. Confirm the current working directory is where files should be generated
|
||||||
|
2. Check if directory is empty or if user wants to override existing files
|
||||||
|
3. Confirm user wants to proceed with scaffold generation
|
||||||
|
|
||||||
|
## Step 1: Gather Project Information
|
||||||
|
|
||||||
|
Prompt the user for the following details using the AskUserQuestion tool:
|
||||||
|
- Project name (for package.json)
|
||||||
|
- Project description
|
||||||
|
- Author name
|
||||||
|
|
||||||
|
Use sensible defaults if user prefers to skip.
|
||||||
|
|
||||||
|
## Step 2: Create Folder Structure
|
||||||
|
|
||||||
|
Create the complete folder structure as defined in `assets/folder-structure.txt`. Generate all necessary directories by writing files to them (directories are created automatically).
|
||||||
|
|
||||||
|
## Step 3: Generate Configuration Files
|
||||||
|
|
||||||
|
Create all configuration files in the project root. Consult `references/stack-architecture.md` for architectural guidance.
|
||||||
|
|
||||||
|
### Essential Config Files
|
||||||
|
|
||||||
|
Generate these files using Write tool:
|
||||||
|
- **package.json** - Use template from `assets/templates/package.template.json`, replacing placeholders
|
||||||
|
- **tsconfig.json** - TypeScript config with strict mode and path aliases
|
||||||
|
- **next.config.ts** - Next.js configuration with server actions
|
||||||
|
- **tailwind.config.ts** - Tailwind v4 with dark mode and shadcn/ui colors
|
||||||
|
- **postcss.config.mjs** - PostCSS with Tailwind plugin
|
||||||
|
- **eslint.config.mjs** - ESLint v9 flat config
|
||||||
|
- **prettier.config.js** - Prettier with Tailwind plugin
|
||||||
|
- **.gitignore** - Standard Next.js ignore patterns
|
||||||
|
- **.env.example** - Environment variable template
|
||||||
|
- **vitest.config.ts** - Vitest test configuration
|
||||||
|
- **playwright.config.ts** - Playwright E2E configuration
|
||||||
|
|
||||||
|
## Step 4: Generate App Router Files
|
||||||
|
|
||||||
|
Create all Next.js app router files following RSC conventions.
|
||||||
|
|
||||||
|
### Root Files
|
||||||
|
- `app/layout.tsx` - Root layout with metadata and providers
|
||||||
|
- `app/page.tsx` - Landing page
|
||||||
|
- `app/globals.css` - Tailwind directives and CSS variables
|
||||||
|
|
||||||
|
### Authentication Routes
|
||||||
|
- `app/(auth)/layout.tsx` - Auth layout (centered)
|
||||||
|
- `app/(auth)/login/page.tsx` - Login page with form
|
||||||
|
|
||||||
|
### Protected Routes
|
||||||
|
- `app/(protected)/layout.tsx` - Protected layout with auth check
|
||||||
|
- `app/(protected)/dashboard/page.tsx` - Dashboard with stats
|
||||||
|
- `app/(protected)/profile/page.tsx` - User profile page
|
||||||
|
- `app/(protected)/data/page.tsx` - Data table page
|
||||||
|
|
||||||
|
### API Routes
|
||||||
|
- `app/api/data/route.ts` - Example API endpoint
|
||||||
|
|
||||||
|
### Middleware
|
||||||
|
- `middleware.ts` - Supabase auth middleware
|
||||||
|
|
||||||
|
## Step 5: Generate UI Components
|
||||||
|
|
||||||
|
Create shadcn/ui components in `components/ui/`:
|
||||||
|
- `button.tsx`, `card.tsx`, `input.tsx`, `label.tsx`, `form.tsx`, `table.tsx`, `dropdown-menu.tsx`, `avatar.tsx`
|
||||||
|
|
||||||
|
Create custom components:
|
||||||
|
- `components/providers.tsx` - App providers with Toaster
|
||||||
|
- `components/layout/header.tsx` - Header with navigation
|
||||||
|
- `components/layout/sidebar.tsx` - Sidebar navigation
|
||||||
|
- `components/layout/nav.tsx` - Navigation links
|
||||||
|
- `components/auth/login-form.tsx` - Login form with RHF + Zod
|
||||||
|
- `components/auth/auth-button.tsx` - Sign in/out button
|
||||||
|
- `components/dashboard/stats-card.tsx` - Stats display card
|
||||||
|
- `components/dashboard/data-table.tsx` - Interactive data table
|
||||||
|
|
||||||
|
All components must be TypeScript and accessible.
|
||||||
|
|
||||||
|
## Step 6: Generate Lib Files
|
||||||
|
|
||||||
|
Create utility and action files:
|
||||||
|
|
||||||
|
### Utilities
|
||||||
|
- `lib/utils.ts` - cn() function and utilities
|
||||||
|
- `lib/prisma.ts` - Prisma client singleton
|
||||||
|
|
||||||
|
### Supabase Clients
|
||||||
|
- `lib/supabase/client.ts` - Client-side Supabase client
|
||||||
|
- `lib/supabase/server.ts` - Server-side Supabase client
|
||||||
|
- `lib/supabase/middleware.ts` - Middleware helper
|
||||||
|
|
||||||
|
### Server Actions (all must start with `'use server'`)
|
||||||
|
- `lib/actions/auth.ts` - signIn(), signOut()
|
||||||
|
- `lib/actions/user.ts` - updateProfile()
|
||||||
|
- `lib/actions/data.ts` - CRUD operations
|
||||||
|
|
||||||
|
### Validation Schemas (Zod)
|
||||||
|
- `lib/validations/auth.ts` - Login/signup schemas
|
||||||
|
- `lib/validations/user.ts` - Profile update schema
|
||||||
|
- `lib/validations/data.ts` - Data CRUD schemas
|
||||||
|
|
||||||
|
## Step 7: Generate Prisma Schema
|
||||||
|
|
||||||
|
Create `prisma/schema.prisma`:
|
||||||
|
- PostgreSQL datasource with connection pooling
|
||||||
|
- User model (id, email, name, timestamps)
|
||||||
|
- Item model (example data model with relations)
|
||||||
|
- Proper indexes and constraints
|
||||||
|
|
||||||
|
Create `prisma/seed.ts`:
|
||||||
|
- TypeScript seed script
|
||||||
|
- Sample users and items
|
||||||
|
|
||||||
|
## Step 8: Generate Tests
|
||||||
|
|
||||||
|
Create test files:
|
||||||
|
- `tests/unit/utils.test.ts` - Unit test for utilities
|
||||||
|
- `tests/integration/auth.test.tsx` - Integration test for auth
|
||||||
|
- `tests/e2e/login.spec.ts` - E2E test for login flow
|
||||||
|
|
||||||
|
## Step 9: Generate CI Workflow
|
||||||
|
|
||||||
|
Create `.github/workflows/ci.yml`:
|
||||||
|
- Lint, type check, test, build jobs
|
||||||
|
- Run on push and PR
|
||||||
|
|
||||||
|
## Step 10: Generate README
|
||||||
|
|
||||||
|
Create comprehensive `README.md` with:
|
||||||
|
- Project overview and tech stack
|
||||||
|
- Prerequisites and installation steps
|
||||||
|
- Environment setup instructions
|
||||||
|
- Database setup (Prisma commands)
|
||||||
|
- Development and testing commands
|
||||||
|
- Deployment guide
|
||||||
|
- Folder structure explanation
|
||||||
|
|
||||||
|
## Step 11: Final Verification
|
||||||
|
|
||||||
|
After generating all files:
|
||||||
|
1. Confirm all files were created successfully
|
||||||
|
2. List the folder structure for user review
|
||||||
|
3. Provide next steps for installation and setup
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
|
||||||
|
### TypeScript
|
||||||
|
- All files must use TypeScript
|
||||||
|
- Proper type annotations
|
||||||
|
- No `any` types unless necessary
|
||||||
|
|
||||||
|
### Server Components
|
||||||
|
- Use Server Components by default
|
||||||
|
- Only add `"use client"` when required for interactivity
|
||||||
|
|
||||||
|
### Accessibility
|
||||||
|
- Use shadcn/ui accessible components
|
||||||
|
- Include ARIA labels
|
||||||
|
- Ensure keyboard navigation
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Validate inputs with Zod
|
||||||
|
- Use Server Actions for mutations
|
||||||
|
- Never expose secrets to client
|
||||||
|
|
||||||
|
## Consulting References
|
||||||
|
|
||||||
|
Throughout scaffolding:
|
||||||
|
- Consult `references/stack-architecture.md` for patterns
|
||||||
|
- Consult `references/implementation-checklist.md` to track progress
|
||||||
|
|
||||||
|
## Completion
|
||||||
|
|
||||||
|
When finished:
|
||||||
|
1. Summarize what was created
|
||||||
|
2. List all major files and directories
|
||||||
|
3. Provide next steps
|
||||||
|
4. Offer to answer questions
|
||||||
80
skills/nextjs-fullstack-scaffold/assets/folder-structure.txt
Normal file
80
skills/nextjs-fullstack-scaffold/assets/folder-structure.txt
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
project-root/
|
||||||
|
├── app/
|
||||||
|
│ ├── (auth)/
|
||||||
|
│ │ ├── login/
|
||||||
|
│ │ │ └── page.tsx
|
||||||
|
│ │ └── layout.tsx
|
||||||
|
│ ├── (protected)/
|
||||||
|
│ │ ├── dashboard/
|
||||||
|
│ │ │ └── page.tsx
|
||||||
|
│ │ ├── profile/
|
||||||
|
│ │ │ └── page.tsx
|
||||||
|
│ │ ├── data/
|
||||||
|
│ │ │ └── page.tsx
|
||||||
|
│ │ └── layout.tsx
|
||||||
|
│ ├── api/
|
||||||
|
│ │ └── data/
|
||||||
|
│ │ └── route.ts
|
||||||
|
│ ├── globals.css
|
||||||
|
│ ├── layout.tsx
|
||||||
|
│ └── page.tsx
|
||||||
|
├── components/
|
||||||
|
│ ├── ui/ (shadcn/ui components)
|
||||||
|
│ │ ├── button.tsx
|
||||||
|
│ │ ├── card.tsx
|
||||||
|
│ │ ├── input.tsx
|
||||||
|
│ │ ├── label.tsx
|
||||||
|
│ │ ├── table.tsx
|
||||||
|
│ │ └── ...
|
||||||
|
│ ├── auth/
|
||||||
|
│ │ ├── login-form.tsx
|
||||||
|
│ │ └── auth-button.tsx
|
||||||
|
│ ├── dashboard/
|
||||||
|
│ │ ├── stats-card.tsx
|
||||||
|
│ │ └── data-table.tsx
|
||||||
|
│ ├── layout/
|
||||||
|
│ │ ├── header.tsx
|
||||||
|
│ │ ├── sidebar.tsx
|
||||||
|
│ │ └── nav.tsx
|
||||||
|
│ └── providers.tsx
|
||||||
|
├── lib/
|
||||||
|
│ ├── actions/
|
||||||
|
│ │ ├── auth.ts
|
||||||
|
│ │ ├── data.ts
|
||||||
|
│ │ └── user.ts
|
||||||
|
│ ├── validations/
|
||||||
|
│ │ ├── auth.ts
|
||||||
|
│ │ ├── user.ts
|
||||||
|
│ │ └── data.ts
|
||||||
|
│ ├── supabase/
|
||||||
|
│ │ ├── client.ts
|
||||||
|
│ │ ├── server.ts
|
||||||
|
│ │ └── middleware.ts
|
||||||
|
│ ├── prisma.ts
|
||||||
|
│ └── utils.ts
|
||||||
|
├── prisma/
|
||||||
|
│ ├── schema.prisma
|
||||||
|
│ └── seed.ts
|
||||||
|
├── tests/
|
||||||
|
│ ├── unit/
|
||||||
|
│ │ └── utils.test.ts
|
||||||
|
│ ├── integration/
|
||||||
|
│ │ └── auth.test.tsx
|
||||||
|
│ └── e2e/
|
||||||
|
│ └── login.spec.ts
|
||||||
|
├── .github/
|
||||||
|
│ └── workflows/
|
||||||
|
│ └── ci.yml
|
||||||
|
├── public/
|
||||||
|
├── .env.example
|
||||||
|
├── .gitignore
|
||||||
|
├── eslint.config.mjs
|
||||||
|
├── next.config.ts
|
||||||
|
├── package.json
|
||||||
|
├── playwright.config.ts
|
||||||
|
├── postcss.config.mjs
|
||||||
|
├── prettier.config.js
|
||||||
|
├── README.md
|
||||||
|
├── tailwind.config.ts
|
||||||
|
├── tsconfig.json
|
||||||
|
└── vitest.config.ts
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"name": "{{PROJECT_NAME}}",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "{{PROJECT_DESCRIPTION}}",
|
||||||
|
"author": "{{AUTHOR}}",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "prisma generate && next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint",
|
||||||
|
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
|
||||||
|
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"",
|
||||||
|
"test": "vitest",
|
||||||
|
"test:e2e": "playwright test",
|
||||||
|
"test:e2e:ui": "playwright test --ui",
|
||||||
|
"db:generate": "prisma generate",
|
||||||
|
"db:push": "prisma db push",
|
||||||
|
"db:migrate": "prisma migrate dev",
|
||||||
|
"db:seed": "tsx prisma/seed.ts",
|
||||||
|
"prepare": "husky"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "^16.0.0",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0",
|
||||||
|
"@supabase/ssr": "^0.5.2",
|
||||||
|
"@supabase/supabase-js": "^2.45.0",
|
||||||
|
"@prisma/client": "^6.0.0",
|
||||||
|
"react-hook-form": "^7.53.0",
|
||||||
|
"@hookform/resolvers": "^3.9.0",
|
||||||
|
"zod": "^3.23.0",
|
||||||
|
"sonner": "^1.5.0",
|
||||||
|
"class-variance-authority": "^0.7.0",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"tailwind-merge": "^2.5.0",
|
||||||
|
"lucide-react": "^0.447.0",
|
||||||
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
|
"@radix-ui/react-dropdown-menu": "^2.1.0",
|
||||||
|
"@radix-ui/react-avatar": "^1.1.0",
|
||||||
|
"@radix-ui/react-select": "^2.1.0",
|
||||||
|
"@radix-ui/react-dialog": "^1.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.6.0",
|
||||||
|
"@types/node": "^22.0.0",
|
||||||
|
"@types/react": "^19.0.0",
|
||||||
|
"@types/react-dom": "^19.0.0",
|
||||||
|
"tailwindcss": "^4.0.0",
|
||||||
|
"postcss": "^8.4.0",
|
||||||
|
"@tailwindcss/typography": "^0.5.15",
|
||||||
|
"eslint": "^9.0.0",
|
||||||
|
"eslint-config-next": "^16.0.0",
|
||||||
|
"@eslint/eslintrc": "^3.2.0",
|
||||||
|
"prettier": "^3.3.0",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.6.0",
|
||||||
|
"husky": "^9.1.0",
|
||||||
|
"lint-staged": "^15.2.0",
|
||||||
|
"prisma": "^6.0.0",
|
||||||
|
"tsx": "^4.19.0",
|
||||||
|
"vitest": "^2.1.0",
|
||||||
|
"@vitejs/plugin-react": "^4.3.0",
|
||||||
|
"@testing-library/react": "^16.0.0",
|
||||||
|
"@testing-library/jest-dom": "^6.5.0",
|
||||||
|
"@testing-library/user-event": "^14.5.0",
|
||||||
|
"@playwright/test": "^1.48.0",
|
||||||
|
"jsdom": "^25.0.0"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{ts,tsx,js,jsx}": [
|
||||||
|
"eslint --fix",
|
||||||
|
"prettier --write"
|
||||||
|
],
|
||||||
|
"*.{json,md}": [
|
||||||
|
"prettier --write"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
# Implementation Checklist
|
||||||
|
|
||||||
|
Complete checklist for scaffolding a Next.js full-stack application.
|
||||||
|
|
||||||
|
## Phase 1: Project Setup
|
||||||
|
|
||||||
|
### Configuration Files
|
||||||
|
- [ ] `package.json` - Dependencies and scripts
|
||||||
|
- [ ] `tsconfig.json` - TypeScript configuration
|
||||||
|
- [ ] `next.config.ts` - Next.js configuration
|
||||||
|
- [ ] `tailwind.config.ts` - Tailwind CSS + shadcn/ui
|
||||||
|
- [ ] `postcss.config.mjs` - PostCSS configuration
|
||||||
|
- [ ] `eslint.config.mjs` - ESLint v9 flat config
|
||||||
|
- [ ] `prettier.config.js` - Prettier configuration
|
||||||
|
- [ ] `.gitignore` - Git ignore patterns
|
||||||
|
- [ ] `.env.example` - Environment variables template
|
||||||
|
- [ ] `README.md` - Setup instructions
|
||||||
|
|
||||||
|
### Testing Configuration
|
||||||
|
- [ ] `vitest.config.ts` - Vitest configuration
|
||||||
|
- [ ] `playwright.config.ts` - Playwright configuration
|
||||||
|
- [ ] Set up test directories (`tests/unit`, `tests/integration`, `tests/e2e`)
|
||||||
|
|
||||||
|
### Git Hooks
|
||||||
|
- [ ] Initialize Husky (`npx husky init`)
|
||||||
|
- [ ] Add pre-commit hook for lint-staged
|
||||||
|
- [ ] Configure lint-staged in package.json
|
||||||
|
|
||||||
|
## Phase 2: Folder Structure
|
||||||
|
|
||||||
|
### App Router Structure
|
||||||
|
- [ ] `app/layout.tsx` - Root layout
|
||||||
|
- [ ] `app/page.tsx` - Home page
|
||||||
|
- [ ] `app/globals.css` - Global styles with Tailwind
|
||||||
|
- [ ] `app/(auth)/login/page.tsx` - Login page
|
||||||
|
- [ ] `app/(auth)/layout.tsx` - Auth layout
|
||||||
|
- [ ] `app/(protected)/dashboard/page.tsx` - Dashboard
|
||||||
|
- [ ] `app/(protected)/profile/page.tsx` - User profile
|
||||||
|
- [ ] `app/(protected)/data/page.tsx` - Data table page
|
||||||
|
- [ ] `app/(protected)/layout.tsx` - Protected layout
|
||||||
|
- [ ] `app/api/data/route.ts` - Example API route
|
||||||
|
- [ ] `middleware.ts` - Auth middleware
|
||||||
|
|
||||||
|
### Components
|
||||||
|
- [ ] `components/providers.tsx` - App providers (Toaster, etc.)
|
||||||
|
- [ ] `components/layout/header.tsx` - Header component
|
||||||
|
- [ ] `components/layout/sidebar.tsx` - Sidebar component
|
||||||
|
- [ ] `components/layout/nav.tsx` - Navigation component
|
||||||
|
- [ ] `components/auth/login-form.tsx` - Login form with RHF + Zod
|
||||||
|
- [ ] `components/auth/auth-button.tsx` - Login/logout button
|
||||||
|
- [ ] `components/dashboard/stats-card.tsx` - Stats card component
|
||||||
|
- [ ] `components/dashboard/data-table.tsx` - Data table component
|
||||||
|
|
||||||
|
### shadcn/ui Components
|
||||||
|
- [ ] `components/ui/button.tsx`
|
||||||
|
- [ ] `components/ui/card.tsx`
|
||||||
|
- [ ] `components/ui/input.tsx`
|
||||||
|
- [ ] `components/ui/label.tsx`
|
||||||
|
- [ ] `components/ui/form.tsx`
|
||||||
|
- [ ] `components/ui/table.tsx`
|
||||||
|
- [ ] `components/ui/dropdown-menu.tsx`
|
||||||
|
- [ ] `components/ui/avatar.tsx`
|
||||||
|
|
||||||
|
### Lib Files
|
||||||
|
- [ ] `lib/utils.ts` - Utility functions (cn, etc.)
|
||||||
|
- [ ] `lib/prisma.ts` - Prisma client singleton
|
||||||
|
- [ ] `lib/supabase/client.ts` - Supabase client for client components
|
||||||
|
- [ ] `lib/supabase/server.ts` - Supabase client for server components
|
||||||
|
- [ ] `lib/supabase/middleware.ts` - Supabase middleware helper
|
||||||
|
- [ ] `lib/actions/auth.ts` - Auth server actions
|
||||||
|
- [ ] `lib/actions/user.ts` - User server actions
|
||||||
|
- [ ] `lib/actions/data.ts` - Data server actions
|
||||||
|
- [ ] `lib/validations/auth.ts` - Auth validation schemas
|
||||||
|
- [ ] `lib/validations/user.ts` - User validation schemas
|
||||||
|
- [ ] `lib/validations/data.ts` - Data validation schemas
|
||||||
|
|
||||||
|
### Database
|
||||||
|
- [ ] `prisma/schema.prisma` - Prisma schema
|
||||||
|
- [ ] `prisma/seed.ts` - Database seed script
|
||||||
|
|
||||||
|
## Phase 3: Core Features
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
- [ ] Supabase auth setup (server + client)
|
||||||
|
- [ ] Login form with email/password
|
||||||
|
- [ ] Server action for sign in
|
||||||
|
- [ ] Server action for sign out
|
||||||
|
- [ ] Middleware for protected routes
|
||||||
|
- [ ] Auth state management
|
||||||
|
- [ ] Redirect logic after login/logout
|
||||||
|
|
||||||
|
### Protected Routes
|
||||||
|
- [ ] Dashboard page with data fetching
|
||||||
|
- [ ] Profile page with user info
|
||||||
|
- [ ] Data table page with CRUD operations
|
||||||
|
- [ ] Server actions for mutations
|
||||||
|
- [ ] Form validation with Zod
|
||||||
|
- [ ] Toast notifications on success/error
|
||||||
|
|
||||||
|
### UI Components
|
||||||
|
- [ ] Responsive layout with header/sidebar
|
||||||
|
- [ ] Dark mode toggle (optional)
|
||||||
|
- [ ] Loading states with Suspense
|
||||||
|
- [ ] Error boundaries
|
||||||
|
- [ ] Accessible forms with shadcn/ui
|
||||||
|
|
||||||
|
### Database Integration
|
||||||
|
- [ ] Prisma schema with User model
|
||||||
|
- [ ] Prisma schema with example data model
|
||||||
|
- [ ] Database migrations
|
||||||
|
- [ ] Seed script with sample data
|
||||||
|
- [ ] Prisma client queries in server components
|
||||||
|
- [ ] Server actions with database mutations
|
||||||
|
|
||||||
|
## Phase 4: Testing
|
||||||
|
|
||||||
|
### Unit Tests
|
||||||
|
- [ ] `tests/unit/utils.test.ts` - Test utility functions
|
||||||
|
- [ ] Test Zod validation schemas
|
||||||
|
- [ ] Test helper functions
|
||||||
|
|
||||||
|
### Integration Tests
|
||||||
|
- [ ] `tests/integration/auth.test.tsx` - Test auth components
|
||||||
|
- [ ] Test form submissions
|
||||||
|
- [ ] Test server actions
|
||||||
|
|
||||||
|
### E2E Tests
|
||||||
|
- [ ] `tests/e2e/login.spec.ts` - Test login flow
|
||||||
|
- [ ] Test protected route access
|
||||||
|
- [ ] Test form submission flows
|
||||||
|
- [ ] Test navigation
|
||||||
|
|
||||||
|
## Phase 5: CI/CD
|
||||||
|
|
||||||
|
### GitHub Actions
|
||||||
|
- [ ] `.github/workflows/ci.yml` - CI workflow
|
||||||
|
- [ ] Run linting
|
||||||
|
- [ ] Run type checking
|
||||||
|
- [ ] Run tests
|
||||||
|
- [ ] Run build
|
||||||
|
- [ ] Set up Vercel deployment (optional)
|
||||||
|
|
||||||
|
## Phase 6: Documentation
|
||||||
|
|
||||||
|
### README Sections
|
||||||
|
- [ ] Project overview
|
||||||
|
- [ ] Tech stack list
|
||||||
|
- [ ] Prerequisites
|
||||||
|
- [ ] Installation steps
|
||||||
|
- [ ] Environment variable setup
|
||||||
|
- [ ] Database setup (Prisma)
|
||||||
|
- [ ] Supabase setup instructions
|
||||||
|
- [ ] Running locally
|
||||||
|
- [ ] Testing commands
|
||||||
|
- [ ] Deployment instructions
|
||||||
|
- [ ] Folder structure explanation
|
||||||
|
- [ ] Contributing guidelines (optional)
|
||||||
|
|
||||||
|
## Verification Steps
|
||||||
|
|
||||||
|
After scaffolding, verify:
|
||||||
|
|
||||||
|
1. **Dependencies Install**: `npm install` completes without errors
|
||||||
|
2. **Type Checking**: `npx tsc --noEmit` passes
|
||||||
|
3. **Linting**: `npm run lint` passes
|
||||||
|
4. **Formatting**: `npm run format:check` passes
|
||||||
|
5. **Build**: `npm run build` succeeds
|
||||||
|
6. **Tests**: `npm test` passes
|
||||||
|
7. **E2E Tests**: `npm run test:e2e` passes (with test environment)
|
||||||
|
8. **Dev Server**: `npm run dev` starts successfully
|
||||||
|
9. **Prisma**: `npx prisma generate` works
|
||||||
|
10. **Git Hooks**: Commit triggers lint-staged
|
||||||
|
|
||||||
|
## Common Issues & Solutions
|
||||||
|
|
||||||
|
### Issue: Prisma client not generated
|
||||||
|
**Solution**: Run `npx prisma generate` after schema changes
|
||||||
|
|
||||||
|
### Issue: Supabase auth not working
|
||||||
|
**Solution**: Check environment variables and cookie configuration
|
||||||
|
|
||||||
|
### Issue: ESLint errors
|
||||||
|
**Solution**: Run `npm run lint -- --fix` to auto-fix
|
||||||
|
|
||||||
|
### Issue: Type errors
|
||||||
|
**Solution**: Ensure all dependencies are installed and Prisma is generated
|
||||||
|
|
||||||
|
### Issue: Build fails
|
||||||
|
**Solution**: Check for missing environment variables and type errors
|
||||||
|
|
||||||
|
### Issue: Tests fail
|
||||||
|
**Solution**: Ensure test environment is properly configured in vitest.config.ts
|
||||||
|
|
||||||
|
## Post-Scaffold Tasks
|
||||||
|
|
||||||
|
After completing the scaffold:
|
||||||
|
|
||||||
|
1. **Environment Setup**: Copy `.env.example` to `.env` and fill in values
|
||||||
|
2. **Supabase Project**: Create Supabase project and get credentials
|
||||||
|
3. **Database Schema**: Run `npx prisma db push` to sync schema
|
||||||
|
4. **Seed Data**: Run `npm run db:seed` to populate sample data
|
||||||
|
5. **Install shadcn/ui**: Run initialization commands for components
|
||||||
|
6. **Git Init**: Initialize git repository and make first commit
|
||||||
|
7. **Deploy**: Connect to Vercel and deploy
|
||||||
|
8. **Test**: Verify all features work in production
|
||||||
|
|
||||||
|
## Optional Enhancements
|
||||||
|
|
||||||
|
Consider adding these after the base scaffold:
|
||||||
|
|
||||||
|
- [ ] Email verification flow
|
||||||
|
- [ ] Password reset flow
|
||||||
|
- [ ] User roles and permissions
|
||||||
|
- [ ] Multi-factor authentication
|
||||||
|
- [ ] File upload with Supabase Storage
|
||||||
|
- [ ] Real-time subscriptions
|
||||||
|
- [ ] Advanced data table features (export, filters)
|
||||||
|
- [ ] User preferences/settings page
|
||||||
|
- [ ] Activity logs/audit trail
|
||||||
|
- [ ] API documentation
|
||||||
|
- [ ] Storybook for components
|
||||||
|
- [ ] Performance monitoring
|
||||||
|
- [ ] Error tracking (Sentry)
|
||||||
|
- [ ] Analytics integration
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
# Stack Architecture Reference
|
||||||
|
|
||||||
|
## Technology Stack
|
||||||
|
|
||||||
|
### Core Framework
|
||||||
|
- **Next.js 16** (App Router) - React framework with built-in routing, server components, and API routes
|
||||||
|
- **React 19** - UI library with Server Components support
|
||||||
|
- **TypeScript** - Type safety across the entire stack
|
||||||
|
|
||||||
|
### Styling
|
||||||
|
- **Tailwind CSS v4** - Utility-first CSS framework
|
||||||
|
- **shadcn/ui** - Accessible component system built on Radix UI
|
||||||
|
- **CSS Variables** - For theming and dark mode support
|
||||||
|
|
||||||
|
### Backend & Database
|
||||||
|
- **Supabase** - Auth provider + PostgreSQL hosting
|
||||||
|
- **Prisma ORM** - Type-safe database client
|
||||||
|
- **Server Actions** - Next.js server-side mutations
|
||||||
|
|
||||||
|
### Forms & Validation
|
||||||
|
- **React Hook Form** - Performant form management
|
||||||
|
- **Zod** - Runtime type validation and schema definition
|
||||||
|
- **@hookform/resolvers** - Bridge between RHF and Zod
|
||||||
|
|
||||||
|
### Developer Experience
|
||||||
|
- **ESLint v9** - Code linting with flat config
|
||||||
|
- **Prettier** - Code formatting
|
||||||
|
- **Husky** - Git hooks for pre-commit checks
|
||||||
|
- **lint-staged** - Run linters on staged files only
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
- **Vitest** - Unit test runner
|
||||||
|
- **React Testing Library** - Component testing
|
||||||
|
- **Playwright** - E2E browser testing
|
||||||
|
|
||||||
|
### Utilities
|
||||||
|
- **Sonner** - Toast notifications
|
||||||
|
- **lucide-react** - Icon library
|
||||||
|
- **clsx + tailwind-merge** - Conditional CSS class utilities
|
||||||
|
|
||||||
|
## Architecture Patterns
|
||||||
|
|
||||||
|
### App Router Structure
|
||||||
|
|
||||||
|
#### Route Groups
|
||||||
|
Use route groups to organize routes without affecting URL structure:
|
||||||
|
|
||||||
|
```
|
||||||
|
app/
|
||||||
|
(auth)/ # Public authentication routes
|
||||||
|
login/
|
||||||
|
signup/
|
||||||
|
(protected)/ # Protected routes requiring authentication
|
||||||
|
dashboard/
|
||||||
|
profile/
|
||||||
|
settings/
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Layouts
|
||||||
|
- Root layout (`app/layout.tsx`) - Wraps entire app
|
||||||
|
- Group layouts - Shared UI for route groups
|
||||||
|
- Nested layouts - Inherited down the tree
|
||||||
|
|
||||||
|
### Server vs Client Components
|
||||||
|
|
||||||
|
#### Server Components (Default)
|
||||||
|
- Data fetching
|
||||||
|
- Database queries
|
||||||
|
- Server-side logic
|
||||||
|
- No interactivity needed
|
||||||
|
|
||||||
|
#### Client Components (`"use client"`)
|
||||||
|
- Interactivity (onClick, onChange, etc.)
|
||||||
|
- React hooks (useState, useEffect, etc.)
|
||||||
|
- Browser APIs
|
||||||
|
- Third-party libraries requiring client-side code
|
||||||
|
|
||||||
|
### Data Fetching Patterns
|
||||||
|
|
||||||
|
#### Server Components
|
||||||
|
```typescript
|
||||||
|
async function getData() {
|
||||||
|
const data = await prisma.table.findMany()
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function Page() {
|
||||||
|
const data = await getData()
|
||||||
|
return <div>{/* render */}</div>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Server Actions
|
||||||
|
```typescript
|
||||||
|
'use server'
|
||||||
|
|
||||||
|
export async function createItem(formData: FormData) {
|
||||||
|
const validated = schema.parse(formData)
|
||||||
|
await prisma.item.create({ data: validated })
|
||||||
|
revalidatePath('/items')
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Authentication Flow
|
||||||
|
|
||||||
|
#### Supabase SSR Setup
|
||||||
|
1. Create Supabase client for server (cookies-based)
|
||||||
|
2. Create Supabase client for client (storage-based)
|
||||||
|
3. Middleware to refresh tokens
|
||||||
|
4. Protected route groups
|
||||||
|
|
||||||
|
#### Auth Flow
|
||||||
|
1. User submits login form
|
||||||
|
2. Server Action validates credentials
|
||||||
|
3. Supabase sets secure cookies
|
||||||
|
4. Middleware verifies on subsequent requests
|
||||||
|
5. Redirect to dashboard
|
||||||
|
|
||||||
|
### Database Layer
|
||||||
|
|
||||||
|
#### Prisma Schema
|
||||||
|
- Define models matching Supabase tables
|
||||||
|
- Use `@db.Uuid` for UUID types
|
||||||
|
- Add indexes for performance
|
||||||
|
- Include relations
|
||||||
|
|
||||||
|
#### Migrations
|
||||||
|
```bash
|
||||||
|
npx prisma migrate dev --name init
|
||||||
|
npx prisma generate
|
||||||
|
npx prisma db push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Form Handling Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const form = useForm<FormData>({
|
||||||
|
resolver: zodResolver(schema),
|
||||||
|
defaultValues: {...}
|
||||||
|
})
|
||||||
|
|
||||||
|
async function onSubmit(data: FormData) {
|
||||||
|
const result = await serverAction(data)
|
||||||
|
if (result.success) {
|
||||||
|
toast.success('Success!')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing Strategy
|
||||||
|
|
||||||
|
#### Unit Tests
|
||||||
|
- Utility functions
|
||||||
|
- Validation schemas
|
||||||
|
- Helper functions
|
||||||
|
|
||||||
|
#### Integration Tests
|
||||||
|
- Component behavior
|
||||||
|
- Form submissions
|
||||||
|
- User interactions
|
||||||
|
|
||||||
|
#### E2E Tests
|
||||||
|
- Critical user flows
|
||||||
|
- Authentication
|
||||||
|
- Data mutations
|
||||||
|
|
||||||
|
## File Naming Conventions
|
||||||
|
|
||||||
|
- **Components**: PascalCase (`UserProfile.tsx`)
|
||||||
|
- **Utilities**: camelCase (`formatDate.ts`)
|
||||||
|
- **Server Actions**: camelCase (`createUser.ts`)
|
||||||
|
- **Route Segments**: lowercase (`dashboard`, `profile`)
|
||||||
|
- **API Routes**: lowercase (`route.ts`)
|
||||||
|
|
||||||
|
## Configuration Files
|
||||||
|
|
||||||
|
### TypeScript (`tsconfig.json`)
|
||||||
|
- Strict mode enabled
|
||||||
|
- Path aliases (`@/*`)
|
||||||
|
- Next.js plugin
|
||||||
|
|
||||||
|
### ESLint (`eslint.config.mjs`)
|
||||||
|
- Flat config format (v9)
|
||||||
|
- Next.js rules
|
||||||
|
- TypeScript rules
|
||||||
|
- Custom rules for unused vars
|
||||||
|
|
||||||
|
### Tailwind (`tailwind.config.ts`)
|
||||||
|
- CSS variables for theming
|
||||||
|
- Dark mode support
|
||||||
|
- Custom color palette
|
||||||
|
- shadcn/ui compatible
|
||||||
|
|
||||||
|
### Prisma (`prisma/schema.prisma`)
|
||||||
|
- PostgreSQL datasource
|
||||||
|
- Shadow database for migrations
|
||||||
|
- Supabase connection pooling
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
Required variables:
|
||||||
|
```
|
||||||
|
NEXT_PUBLIC_SUPABASE_URL
|
||||||
|
NEXT_PUBLIC_SUPABASE_ANON_KEY
|
||||||
|
DATABASE_URL (connection pooling)
|
||||||
|
DIRECT_URL (direct connection)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Vercel Setup
|
||||||
|
1. Connect GitHub repository
|
||||||
|
2. Set environment variables
|
||||||
|
3. Configure build settings (auto-detected)
|
||||||
|
4. Deploy
|
||||||
|
|
||||||
|
### Build Command
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
- Runs Prisma generate
|
||||||
|
- Builds Next.js app
|
||||||
|
- Type checks
|
||||||
|
- Lint checks
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- Use Server Components by default
|
||||||
|
- Minimize client-side JavaScript
|
||||||
|
- Implement proper caching strategies
|
||||||
|
- Use React Suspense for loading states
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- Validate all inputs with Zod
|
||||||
|
- Use Server Actions for mutations
|
||||||
|
- Implement Row Level Security in Supabase
|
||||||
|
- Never expose secrets to client
|
||||||
|
|
||||||
|
### Accessibility
|
||||||
|
- Use shadcn/ui components (built on Radix)
|
||||||
|
- Include ARIA labels
|
||||||
|
- Ensure keyboard navigation
|
||||||
|
- Test with screen readers
|
||||||
|
|
||||||
|
### Type Safety
|
||||||
|
- Define Zod schemas for all forms
|
||||||
|
- Use Prisma for database queries
|
||||||
|
- Type all API responses
|
||||||
|
- Avoid `any` types
|
||||||
446
skills/nextjs-fullstack-scaffold/scripts/scaffold.py
Normal file
446
skills/nextjs-fullstack-scaffold/scripts/scaffold.py
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Next.js Full-Stack Scaffold Generator
|
||||||
|
|
||||||
|
Generates a production-ready Next.js 16 full-stack application with:
|
||||||
|
- Next.js 16 (App Router)
|
||||||
|
- React 19 with Server Components
|
||||||
|
- TypeScript
|
||||||
|
- Tailwind CSS v4
|
||||||
|
- shadcn/ui
|
||||||
|
- Supabase (Auth + PostgreSQL)
|
||||||
|
- Prisma ORM
|
||||||
|
- React Hook Form + Zod
|
||||||
|
- ESLint v9 + Prettier
|
||||||
|
- Husky + lint-staged
|
||||||
|
- Sonner (toasts)
|
||||||
|
- Vitest + React Testing Library
|
||||||
|
- Playwright for E2E testing
|
||||||
|
"""
|
||||||
|
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Dict, Any
|
||||||
|
|
||||||
|
# Configure stdout for UTF-8 encoding (prevents Windows encoding errors)
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def prompt_for_details() -> Dict[str, str]:
|
||||||
|
"""Prompt user for project details."""
|
||||||
|
print("\n=== Next.js Full-Stack Scaffold ===\n")
|
||||||
|
|
||||||
|
details = {}
|
||||||
|
details['name'] = input("Project name (e.g., my-app): ").strip() or "my-app"
|
||||||
|
details['description'] = input("Project description: ").strip() or "A full-stack Next.js application"
|
||||||
|
details['author'] = input("Author name: ").strip() or "Your Name"
|
||||||
|
|
||||||
|
return details
|
||||||
|
|
||||||
|
|
||||||
|
def create_folder_structure():
|
||||||
|
"""Create the project folder structure."""
|
||||||
|
folders = [
|
||||||
|
"app",
|
||||||
|
"app/(auth)",
|
||||||
|
"app/(auth)/login",
|
||||||
|
"app/(protected)",
|
||||||
|
"app/(protected)/dashboard",
|
||||||
|
"app/(protected)/profile",
|
||||||
|
"app/api",
|
||||||
|
"app/api/data",
|
||||||
|
"components",
|
||||||
|
"components/ui",
|
||||||
|
"components/auth",
|
||||||
|
"components/dashboard",
|
||||||
|
"lib",
|
||||||
|
"lib/actions",
|
||||||
|
"lib/validations",
|
||||||
|
"prisma",
|
||||||
|
"prisma/migrations",
|
||||||
|
"public",
|
||||||
|
"tests",
|
||||||
|
"tests/unit",
|
||||||
|
"tests/integration",
|
||||||
|
"tests/e2e",
|
||||||
|
".github",
|
||||||
|
".github/workflows",
|
||||||
|
]
|
||||||
|
|
||||||
|
for folder in folders:
|
||||||
|
Path(folder).mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
print("[OK] Created folder structure")
|
||||||
|
|
||||||
|
|
||||||
|
def create_package_json(details: Dict[str, str]) -> str:
|
||||||
|
"""Generate package.json content."""
|
||||||
|
package = {
|
||||||
|
"name": details['name'],
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": details['description'],
|
||||||
|
"author": details['author'],
|
||||||
|
"private": True,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "prisma generate && next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint",
|
||||||
|
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
|
||||||
|
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md}\"",
|
||||||
|
"test": "vitest",
|
||||||
|
"test:e2e": "playwright test",
|
||||||
|
"test:e2e:ui": "playwright test --ui",
|
||||||
|
"db:generate": "prisma generate",
|
||||||
|
"db:push": "prisma db push",
|
||||||
|
"db:migrate": "prisma migrate dev",
|
||||||
|
"db:seed": "tsx prisma/seed.ts",
|
||||||
|
"prepare": "husky"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"next": "^16.0.0",
|
||||||
|
"react": "^19.0.0",
|
||||||
|
"react-dom": "^19.0.0",
|
||||||
|
"@supabase/ssr": "^0.5.2",
|
||||||
|
"@supabase/supabase-js": "^2.45.0",
|
||||||
|
"@prisma/client": "^6.0.0",
|
||||||
|
"react-hook-form": "^7.53.0",
|
||||||
|
"@hookform/resolvers": "^3.9.0",
|
||||||
|
"zod": "^3.23.0",
|
||||||
|
"sonner": "^1.5.0",
|
||||||
|
"class-variance-authority": "^0.7.0",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
|
"tailwind-merge": "^2.5.0",
|
||||||
|
"lucide-react": "^0.447.0",
|
||||||
|
"@radix-ui/react-slot": "^1.1.0",
|
||||||
|
"@radix-ui/react-label": "^2.1.0",
|
||||||
|
"@radix-ui/react-dropdown-menu": "^2.1.0",
|
||||||
|
"@radix-ui/react-avatar": "^1.1.0",
|
||||||
|
"@radix-ui/react-select": "^2.1.0",
|
||||||
|
"@radix-ui/react-dialog": "^1.1.0",
|
||||||
|
"@radix-ui/react-table": "^1.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"typescript": "^5.6.0",
|
||||||
|
"@types/node": "^22.0.0",
|
||||||
|
"@types/react": "^19.0.0",
|
||||||
|
"@types/react-dom": "^19.0.0",
|
||||||
|
"tailwindcss": "^4.0.0",
|
||||||
|
"postcss": "^8.4.0",
|
||||||
|
"@tailwindcss/typography": "^0.5.15",
|
||||||
|
"eslint": "^9.0.0",
|
||||||
|
"eslint-config-next": "^16.0.0",
|
||||||
|
"prettier": "^3.3.0",
|
||||||
|
"prettier-plugin-tailwindcss": "^0.6.0",
|
||||||
|
"husky": "^9.1.0",
|
||||||
|
"lint-staged": "^15.2.0",
|
||||||
|
"prisma": "^6.0.0",
|
||||||
|
"tsx": "^4.19.0",
|
||||||
|
"vitest": "^2.1.0",
|
||||||
|
"@vitejs/plugin-react": "^4.3.0",
|
||||||
|
"@testing-library/react": "^16.0.0",
|
||||||
|
"@testing-library/jest-dom": "^6.5.0",
|
||||||
|
"@testing-library/user-event": "^14.5.0",
|
||||||
|
"@playwright/test": "^1.48.0"
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{ts,tsx,js,jsx}": ["eslint --fix", "prettier --write"],
|
||||||
|
"*.{json,md}": ["prettier --write"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.dumps(package, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
def write_file(path: str, content: str):
|
||||||
|
"""Write content to a file."""
|
||||||
|
Path(path).parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(path, 'w', encoding='utf-8') as f:
|
||||||
|
f.write(content)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_all_files(details: Dict[str, str]):
|
||||||
|
"""Generate all project files."""
|
||||||
|
|
||||||
|
# Import templates
|
||||||
|
from pathlib import Path
|
||||||
|
assets_dir = Path(__file__).parent.parent / "assets" / "templates"
|
||||||
|
|
||||||
|
# Since we're generating inline, let's create the content directly
|
||||||
|
# This would normally load from template files
|
||||||
|
|
||||||
|
files = get_all_file_contents(details)
|
||||||
|
|
||||||
|
for file_path, content in files.items():
|
||||||
|
write_file(file_path, content)
|
||||||
|
print(f"[OK] Created {file_path}")
|
||||||
|
|
||||||
|
|
||||||
|
def get_all_file_contents(details: Dict[str, str]) -> Dict[str, str]:
|
||||||
|
"""Return all file contents as a dictionary."""
|
||||||
|
|
||||||
|
files = {}
|
||||||
|
|
||||||
|
# Configuration files
|
||||||
|
files['package.json'] = create_package_json(details)
|
||||||
|
|
||||||
|
files['tsconfig.json'] = """{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "preserve",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
files['next.config.ts'] = """import type { NextConfig } from "next";
|
||||||
|
|
||||||
|
const nextConfig: NextConfig = {
|
||||||
|
eslint: {
|
||||||
|
ignoreDuringBuilds: false,
|
||||||
|
},
|
||||||
|
typescript: {
|
||||||
|
ignoreBuildErrors: false,
|
||||||
|
},
|
||||||
|
experimental: {
|
||||||
|
serverActions: {
|
||||||
|
bodySizeLimit: "2mb",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
|
"""
|
||||||
|
|
||||||
|
files['tailwind.config.ts'] = """import type { Config } from "tailwindcss";
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
darkMode: ["class"],
|
||||||
|
content: [
|
||||||
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
background: "hsl(var(--background))",
|
||||||
|
foreground: "hsl(var(--foreground))",
|
||||||
|
card: {
|
||||||
|
DEFAULT: "hsl(var(--card))",
|
||||||
|
foreground: "hsl(var(--card-foreground))",
|
||||||
|
},
|
||||||
|
popover: {
|
||||||
|
DEFAULT: "hsl(var(--popover))",
|
||||||
|
foreground: "hsl(var(--popover-foreground))",
|
||||||
|
},
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "hsl(var(--primary))",
|
||||||
|
foreground: "hsl(var(--primary-foreground))",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: "hsl(var(--secondary))",
|
||||||
|
foreground: "hsl(var(--secondary-foreground))",
|
||||||
|
},
|
||||||
|
muted: {
|
||||||
|
DEFAULT: "hsl(var(--muted))",
|
||||||
|
foreground: "hsl(var(--muted-foreground))",
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
DEFAULT: "hsl(var(--accent))",
|
||||||
|
foreground: "hsl(var(--accent-foreground))",
|
||||||
|
},
|
||||||
|
destructive: {
|
||||||
|
DEFAULT: "hsl(var(--destructive))",
|
||||||
|
foreground: "hsl(var(--destructive-foreground))",
|
||||||
|
},
|
||||||
|
border: "hsl(var(--border))",
|
||||||
|
input: "hsl(var(--input))",
|
||||||
|
ring: "hsl(var(--ring))",
|
||||||
|
chart: {
|
||||||
|
"1": "hsl(var(--chart-1))",
|
||||||
|
"2": "hsl(var(--chart-2))",
|
||||||
|
"3": "hsl(var(--chart-3))",
|
||||||
|
"4": "hsl(var(--chart-4))",
|
||||||
|
"5": "hsl(var(--chart-5))",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
lg: "var(--radius)",
|
||||||
|
md: "calc(var(--radius) - 2px)",
|
||||||
|
sm: "calc(var(--radius) - 4px)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [require("@tailwindcss/typography")],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
"""
|
||||||
|
|
||||||
|
files['postcss.config.mjs'] = """/** @type {import('postcss-load-config').Config} */
|
||||||
|
const config = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
"""
|
||||||
|
|
||||||
|
files['eslint.config.mjs'] = """import { dirname } from "path";
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
import { FlatCompat } from "@eslint/eslintrc";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
const compat = new FlatCompat({
|
||||||
|
baseDirectory: __dirname,
|
||||||
|
});
|
||||||
|
|
||||||
|
const eslintConfig = [
|
||||||
|
...compat.extends("next/core-web-vitals", "next/typescript"),
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
argsIgnorePattern: "^_",
|
||||||
|
varsIgnorePattern: "^_",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"@typescript-eslint/no-explicit-any": "warn",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default eslintConfig;
|
||||||
|
"""
|
||||||
|
|
||||||
|
files['prettier.config.js'] = """/** @type {import("prettier").Config} */
|
||||||
|
const config = {
|
||||||
|
semi: true,
|
||||||
|
trailingComma: "es5",
|
||||||
|
singleQuote: false,
|
||||||
|
printWidth: 100,
|
||||||
|
tabWidth: 2,
|
||||||
|
useTabs: false,
|
||||||
|
plugins: ["prettier-plugin-tailwindcss"],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
"""
|
||||||
|
|
||||||
|
files['.env.example'] = """# Supabase
|
||||||
|
NEXT_PUBLIC_SUPABASE_URL=your-supabase-url
|
||||||
|
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key
|
||||||
|
|
||||||
|
# Database
|
||||||
|
DATABASE_URL=your-database-url
|
||||||
|
DIRECT_URL=your-direct-database-url
|
||||||
|
|
||||||
|
# App
|
||||||
|
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||||
|
"""
|
||||||
|
|
||||||
|
files['.gitignore'] = """# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
.yarn/install-state.gz
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
playwright-report/
|
||||||
|
test-results/
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# env files
|
||||||
|
.env
|
||||||
|
.env*.local
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
|
|
||||||
|
# prisma
|
||||||
|
prisma/migrations/
|
||||||
|
"""
|
||||||
|
|
||||||
|
# This is getting very long. Let me create a helper to generate the remaining files
|
||||||
|
# in the template assets instead
|
||||||
|
|
||||||
|
return files
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main execution function."""
|
||||||
|
print("Starting Next.js Full-Stack Scaffold Generator...")
|
||||||
|
|
||||||
|
# Get project details
|
||||||
|
details = prompt_for_details()
|
||||||
|
|
||||||
|
# Create folder structure
|
||||||
|
print("\nCreating folder structure...")
|
||||||
|
create_folder_structure()
|
||||||
|
|
||||||
|
# Generate all files
|
||||||
|
print("\nGenerating project files...")
|
||||||
|
generate_all_files(details)
|
||||||
|
|
||||||
|
print("\n[SUCCESS] Scaffold complete!")
|
||||||
|
print("\nNext steps:")
|
||||||
|
print("1. Copy .env.example to .env and fill in your Supabase credentials")
|
||||||
|
print("2. Run: npm install")
|
||||||
|
print("3. Run: npx prisma generate")
|
||||||
|
print("4. Run: npx prisma db push")
|
||||||
|
print("5. Run: npm run dev")
|
||||||
|
print("\nSee README.md for detailed setup instructions.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user