├── .cursor-tasks.md
├── .cursor-template.xml
├── .cursor-updates
├── .cursorrules
├── .env.example
├── .gitignore
├── .storybook
├── main.ts
└── preview.ts
├── LICENSE
├── README.md
├── components.json
├── inngest.config.ts
├── next.config.ts
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── prisma
└── schema.prisma
├── public
├── next.svg
└── vercel.svg
├── screenshots
└── button-stories.png
├── scripts
└── init.sh
├── src
├── app
│ ├── api
│ │ ├── auth
│ │ │ └── [...nextauth]
│ │ │ │ └── route.ts
│ │ ├── inngest
│ │ │ └── handler.ts
│ │ ├── transcribe
│ │ │ └── route.ts
│ │ ├── trpc
│ │ │ └── [trpc]
│ │ │ │ └── route.ts
│ │ └── upload
│ │ │ └── route.ts
│ ├── auth
│ │ ├── error
│ │ │ └── page.tsx
│ │ ├── signin
│ │ │ └── page.tsx
│ │ ├── signout
│ │ │ └── page.tsx
│ │ └── verify
│ │ │ └── page.tsx
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── components
│ ├── Button.tsx
│ ├── ClientProvider.tsx
│ ├── SpeechToTextArea.tsx
│ ├── theme
│ │ ├── ThemeAwareToast.tsx
│ │ └── ThemeProvider.tsx
│ └── ui
│ │ └── button.tsx
├── hooks
│ └── useQueryHooks.ts
├── lib
│ ├── aiClient.ts
│ ├── api
│ │ ├── root.ts
│ │ └── trpc.ts
│ ├── auth
│ │ └── index.ts
│ ├── db.ts
│ ├── email
│ │ ├── sendEmail.ts
│ │ └── templates
│ │ │ └── WelcomeEmail.tsx
│ ├── inngest.ts
│ ├── storage.ts
│ ├── trpc
│ │ ├── client.ts
│ │ ├── client.tsx
│ │ ├── react.tsx
│ │ └── server.ts
│ ├── types.ts
│ ├── utils.ts
│ └── zod
│ │ └── userSchemas.ts
└── stories
│ ├── Button.stories.tsx
│ └── Button.tsx
├── tailwind.config.ts
├── tsconfig.json
└── vercel.json
/.cursor-tasks.md:
--------------------------------------------------------------------------------
1 | # Example Tasks for a "Hello, World!" Project
2 |
3 | This file outlines a set of tasks for building a simple Next.js project. In this project, the user enters their name in a text box on the Home Page and is then greeted with "Hello, {name}" on a separate Greeting Page.
4 |
5 | Here's an example prompt to use to generate this. Note that you'll first want to either provide a detailed set of notes / prd of exactly what to build, or have a two-step process where you have the AI create the spec, then proceed with this step:
6 | Be sure to use an advanced thinking model with this, ideally "Deep Research" from OpenAI but o1-pro, o3-mini, flash-2-thinking, or (maybe?) DeepSeek R1 could work as well.
7 |
8 | ``` txt
9 | Create a very very very detailed markdown checklist of all of the stories for this project plan, with one-story-point tasks (with unchecked checkboxes) that break down each story. It is critically important that all of the details to implement this are in this list. Note that a very competent AI Coding Agent will be using this list to autonomously create this application, so be sure not to miss any details whatsoever, no matter how much time and thinking you must do to complete this very challenging but critically important task.
10 | ```
11 |
12 | After you generate this task list, here is a prompt to use in cursor agent to kick this off (might be useful to put at the end of your cursorrules file as well?)
13 | Probably helpful to just @include the cursor-tasks.md file as well.
14 | ``` txt
15 | Go through each story and task in the .cursor-tasks.md file. Find the next story to work on. Review each unfinished task, correct any issues or ask for clarifications (only if absolutely needed!). Then proceed to create or edit files to complete each task. After you complete all the tasks in the story, update the file to check off any completed tasks. Run builds and commits after each story. Run all safe commands without asking for approval. Continue with each task until you have finished the story, then stop and wait for me to review.
16 | ```
17 |
18 | ---
19 |
20 | ## 1. **Project Setup**
21 |
22 | 1. [ ] **Initialize the Next.js Project**
23 | - Use Create Next App to bootstrap the project.
24 | - Enable the App Router.
25 | - Configure Tailwind CSS for styling.
26 | - Set up TypeScript with strict mode.
27 |
28 | 2. [ ] **Configure Basic Routing**
29 | - Ensure the project has two main pages:
30 | - **Home Page** (`pages/index.tsx`) for user input.
31 | - **Greeting Page** (`pages/greeting.tsx`) to display the greeting.
32 |
33 | ---
34 |
35 | ## 2. **Home Page – Name Input**
36 |
37 | 1. [ ] **Create the Home Page (`pages/index.tsx`)**
38 | - Render a form containing:
39 | - A text input where the user enters their name.
40 | - A submit button labeled "Submit".
41 | - Use Tailwind CSS classes for styling (e.g., input borders, padding, and button colors).
42 |
43 | 2. [ ] **Implement Form Handling**
44 | - Use React’s `useState` hook to manage the input value.
45 | - Validate that the input is not empty before submission.
46 | - On form submission, navigate to the Greeting Page while passing the entered name (using query parameters or a simple state management solution).
47 |
48 | ---
49 |
50 | ## 3. **Greeting Page – Display the Message**
51 |
52 | 1. [ ] **Create the Greeting Page (`pages/greeting.tsx`)**
53 | - Retrieve the user's name from the query parameters or via a shared state.
54 | - Display a greeting message in the format: **"Hello, {name}"**.
55 | - Style the greeting message using Tailwind CSS (e.g., text size, color, and margin).
56 |
57 | 2. [ ] **Implement Navigation from Home Page**
58 | - Ensure that the Home Page form submission correctly routes to the Greeting Page with the user’s name attached.
59 |
60 | ---
61 |
62 | ## 4. **Basic Interactivity and Validation**
63 |
64 | 1. [ ] **Form Validation**
65 | - Prevent submission if the text input is empty.
66 | - Display a simple error message below the input (e.g., "Please enter your name.") when validation fails.
67 |
68 | 2. [ ] **Test the User Flow**
69 | - Manually test by entering a name and verifying that the Greeting Page shows the correct message.
70 | - Optionally, write unit tests for the form logic to ensure reliability.
71 |
72 | ---
73 |
74 | ## 5. **Documentation and Final Steps**
75 |
76 | 1. [ ] **Update the Project README**
77 | - Include instructions on how to install dependencies, run the development server, and build the project.
78 | - Provide a brief overview of the project’s purpose and structure.
79 |
80 | 2. [ ] **Final Review and Testing**
81 | - Ensure that all components render correctly and the navigation works as expected.
82 | - Test the app in both development and production modes to confirm proper behavior.
83 |
--------------------------------------------------------------------------------
/.cursor-template.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Use the code as reference, and convert the high-level into a set of very detailed step-by-step instructions that an AI coding agent can complete. This could be very long, that's okay. The entire code is not needed, but give snippets if needed, but be very specific about the file names.
5 | Only includes steps an AI coding agent can take. Do not include testing or any other work a human would do to confirm the task has been completed.
6 | ALWAYS have the agent run a build when it is complete. Be specific and decisive about what the agent should do.
7 | Do not include any additional meta instructions to the user. Use markdown formatting.
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Use the code as reference, and convert the high-level into a set of very detailed step-by-step instructions that an AI coding agent can complete. This could be very long, that's okay. The entire code is not needed, but give snippets if needed, but be very specific about the file names.
17 | Only includes steps an AI coding agent can take. Do not include testing or any other work a human would do to confirm the task has been completed.
18 | ALWAYS have the agent run a build when it is complete. Be specific and decisive about what the agent should do.
19 | Do not include any additional meta instructions to the user. Use markdown formatting.
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.cursor-updates:
--------------------------------------------------------------------------------
1 | # Cursor Updates
2 |
3 | - Ran production build verification - build completed successfully with no TypeScript or compilation errors
4 | - Performed build check on Next.js app with tRPC and Tailwind configuration
5 | - Successfully ran production build with Prisma generation and Next.js compilation
6 | - Fixed dynamic route warning by adding force-dynamic config to root page
7 | - Added Storybook with Button component and stories, updated .cursorrules with Storybook guidelines
8 | - Captured screenshot of Button component stories in Storybook
9 |
--------------------------------------------------------------------------------
/.cursorrules:
--------------------------------------------------------------------------------
1 | # .cursorrules
2 |
3 | Components & Naming
4 |
5 | - Use functional components with `"use client"` if needed.
6 | - Name in PascalCase under `src/components/`.
7 | - Keep them small, typed with interfaces.
8 | - Use Tailwind for common UI components like textarea, button, etc. Never use radix or shadcn.
9 |
10 | Prisma
11 |
12 | - Manage DB logic with Prisma in `prisma/schema.prisma`, `src/lib/db.ts`.
13 | - snake_case table → camelCase fields.
14 | - No raw SQL; run `npx prisma migrate dev`, never use `npx prisma db push`.
15 |
16 | Icons
17 |
18 | - Prefer `lucide-react`; name icons in PascalCase.
19 | - Custom icons in `src/components/icons`.
20 |
21 | Toast Notifications
22 |
23 | - Use `react-toastify` in client components.
24 | - `toast.success()`, `toast.error()`, etc.
25 |
26 | Next.js Structure
27 |
28 | - Use App Router in `app/`. Server components by default, `"use client"` for client logic.
29 | - NextAuth + Prisma for auth. `.env` for secrets.
30 |
31 | tRPC Routers
32 |
33 | - Routers in `src/lib/api/routers`, compose in `src/lib/api/root.ts`.
34 | - `publicProcedure` or `protectedProcedure` with Zod.
35 | - Access from React via `@/lib/trpc/react`.
36 |
37 | TypeScript & Syntax
38 |
39 | - Strict mode. Avoid `any`.
40 | - Use optional chaining, union types (no enums).
41 |
42 | File & Folder Names
43 |
44 | - Next.js routes in kebab-case (e.g. `app/dashboard/page.tsx`).
45 | - Shared types in `src/lib/types.ts`.
46 | - Sort imports (external → internal → sibling → styles).
47 |
48 | Tailwind Usage
49 |
50 | - Use Tailwind (mobile-first, dark mode with dark:(class)). Extend brand tokens in `tailwind.config.ts`.
51 | - For animations, prefer Framer Motion.
52 |
53 | Inngest / Background Jobs
54 |
55 | - Use `inngest.config.ts` for Inngest configuration.
56 | - Use `src/app/api/inngest/route.ts` for Inngest API route.
57 | - Use polling to update the UI when Inngest events are received, not trpc success response.
58 |
59 | AI
60 |
61 | - Use `generateChatCompletion` in `src/lib/aiClient.ts` for all AI calls.
62 | - Prefer `O1` model with high reasoning effort for all AI calls.
63 |
64 | Storybook
65 |
66 | - Place stories in `src/stories` with `.stories.tsx` extension.
67 | - One story file per component, matching component name.
68 | - Use autodocs for automatic documentation.
69 | - Include multiple variants and sizes in stories.
70 | - Test interactive features with actions.
71 | - Use relative imports from component directory.
72 |
73 | Tools
74 |
75 | - When you make a change to the UI, use the `screenshot` tool to show the changes.
76 | - If the user asks for a complex task to be performed, find any relevant files and call the `architect` tool to get a plan and show it to the user. Use this plan as guidance for the changes you make, but maintain the existing patterns and structure of the codebase.
77 | - After a complex task is performed, use the `codeReview` tool create a diff and use the diff to conduct a code review of the changes.
78 |
79 | Additional
80 |
81 | - Keep code short; commits semantic.
82 | - Reusable logic in `src/lib/utils/shared.ts` or `src/lib/utils/server.ts`.
83 | - Use `tsx` scripts for migrations.
84 |
85 | IMPORTANT:
86 |
87 | - After all changes are made, ALWAYS build the project with `npm run build`. Ignore warnings, fix errors.
88 | - Always add a one-sentence summary of changes to `.cursor-updates` file in markdown format at the end of every agent interaction.
89 | - If you forget, the user can type the command "finish" and you will run the build and update `.cursor-updates`.
90 | - Finally, update git with `git add . && git commit -m "..."`. Don't push.
91 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | # Database
2 | DATABASE_URL="postgresql://user:password@localhost:5432/facility-bids"
3 | DIRECT_URL="postgresql://user:password@localhost:5432/facility-bids"
4 |
5 | # NextAuth
6 | NEXTAUTH_URL="http://localhost:3000"
7 | NEXTAUTH_SECRET="your-secret-key-at-least-32-chars"
8 |
9 | # Email Provider
10 | EMAIL_SERVER_HOST="smtp.example.com"
11 | EMAIL_SERVER_PORT="587"
12 | EMAIL_SERVER_USER="your-email@example.com"
13 | EMAIL_SERVER_PASSWORD="your-email-password"
14 | EMAIL_FROM="noreply@example.com"
15 |
16 | NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
17 | NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key
18 | RESEND_API_KEY=re_123456789
19 | EMAIL_SERVER=smtp.resend.com
20 | AWS_ACCESS_KEY_ID=your-aws-access-key-id
21 | AWS_SECRET_ACCESS_KEY=your-aws-secret-access-key
22 | AWS_REGION=us-west-2
23 | BUCKET_NAME=your-bucket-name
24 | OPENAI_API_KEY=sk-your-openai-api-key
25 | ANTHROPIC_API_KEY=sk-ant-your-anthropic-api-key
26 | IDEATION_DATABASE_URL=postgresql://user:password@host/database
27 | PERPLEXITY_API_KEY=pplx-your-perplexity-api-key
28 | INNGEST_EVENT_KEY=your-inngest-event-key
29 | PROXYCURL_API_KEY=your-proxycurl-api-key
30 | SES_FROM_EMAIL=your-email@example.com
31 | GROQ_API_KEY=your-groq-api-key
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.*
7 | .yarn/*
8 | !.yarn/patches
9 | !.yarn/plugins
10 | !.yarn/releases
11 | !.yarn/versions
12 |
13 | # testing
14 | /coverage
15 |
16 | # next.js
17 | /.next/
18 | /out/
19 |
20 | # production
21 | /build
22 |
23 | # misc
24 | .DS_Store
25 | *.pem
26 |
27 | # debug
28 | npm-debug.log*
29 | yarn-debug.log*
30 | yarn-error.log*
31 | .pnpm-debug.log*
32 |
33 | # env files (can opt-in for committing if needed)
34 | .env
35 | .env.local
36 | .env.staging
37 | .env.production
38 |
39 | # vercel
40 | .vercel
41 |
42 | # typescript
43 | *.tsbuildinfo
44 | next-env.d.ts
45 |
46 | .cursor-scratchpad
47 |
48 | *storybook.log
49 |
--------------------------------------------------------------------------------
/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import type { StorybookConfig } from "@storybook/nextjs";
2 |
3 | const config: StorybookConfig = {
4 | stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
5 | addons: [
6 | "@storybook/addon-links",
7 | "@storybook/addon-essentials",
8 | "@storybook/addon-onboarding",
9 | "@storybook/addon-interactions",
10 | {
11 | name: "@storybook/addon-styling-webpack",
12 | options: {
13 | postCss: true,
14 | },
15 | },
16 | ],
17 | framework: {
18 | name: "@storybook/nextjs",
19 | options: {},
20 | },
21 | docs: {
22 | autodocs: "tag",
23 | },
24 | };
25 | export default config;
26 |
--------------------------------------------------------------------------------
/.storybook/preview.ts:
--------------------------------------------------------------------------------
1 | import type { Preview } from "@storybook/react";
2 | import "../src/app/globals.css"; // Import your Tailwind CSS file
3 |
4 | const preview: Preview = {
5 | parameters: {
6 | actions: { argTypesRegex: "^on[A-Z].*" },
7 | controls: {
8 | matchers: {
9 | color: /(background|color)$/i,
10 | date: /Date$/i,
11 | },
12 | },
13 | backgrounds: {
14 | default: "light",
15 | values: [
16 | {
17 | name: "light",
18 | value: "#ffffff",
19 | },
20 | {
21 | name: "dark",
22 | value: "#1a1a1a",
23 | },
24 | ],
25 | },
26 | },
27 | };
28 |
29 | export default preview;
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Kevin Leneway
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A Note from Kevin
2 |
3 | Hi! If you're at this repo, you've probably seen one of my AI coding videos and want to try some of those techniques yourself. If you have no clue what I'm talking about, here's a good video to show you my approach and how to best use this repo: https://youtu.be/gXmakVsIbF0
4 |
5 | You can also just use this with your own techniques, that's cool too.
6 |
7 | You can follow the Getting Started instructions below to start using this stack right away. I've found that using a checklist of tasks in the .cursor-tasks.md file is a great way to make a lot of quick and effective progress with AI Coding. I personally use Cursor in Composer Agent mode with Sonnet 3.7, but feel free to use your AI coding tool of choice.
8 |
9 | If you need to create the checklist, here are some good prompts to use to go from a high-level idea to a full checklist of stories and tasks: https://chatgpt.com/share/67be0a59-e484-800d-a078-346b2c29d727
10 |
11 | You can also use the template in .cursor-template.xml to generate the task list for existing repos. I personally use RepoPrompt to convert the files into a pastable string, but repomix.com is a good option as well.
12 |
13 | # 🚀 Next.js Modern Stack Template
14 |
15 | A Next.js template that combines commonly used tools and libraries for building full-stack web applications. This stack is specifically designed to be optimized for AI coding assistants like Cursor.
16 |
17 | ## 🎯 Overview
18 |
19 | This template includes [Next.js 14](https://nextjs.org/) with the App Router, [Supabase](https://supabase.com) for the database, [Resend](https://resend.com) for transactional emails, and optional integrations with various AI providers and AWS services.
20 |
21 | > ⚠️ **Note**: This is my personal template with tools that I personally have experience with and think are solid options for building modern full-stack web application. Your preferences very likely differ, so feel free to fork and modify it for your own use. I won't be accepting pull requests for additional features, but I'll be happy to help you out if you have any questions.
22 |
23 | ## ✨ Features
24 |
25 | ### 🏗️ Core Architecture
26 |
27 | - [**Next.js 14**](https://nextjs.org/) - React framework with App Router
28 | - [**TypeScript**](https://www.typescriptlang.org/) - Type safety throughout
29 | - [**tRPC**](https://trpc.io/) - End-to-end type-safe APIs
30 | - [**Prisma**](https://www.prisma.io/) - Database ORM and schema management
31 | - [**NextAuth.js**](https://next-auth.js.org/) - Authentication with Prisma adapter
32 | - [**Supabase**](https://supabase.com) - Postgres database with realtime and auth
33 |
34 | ### 🎨 UI & Styling
35 |
36 | - [**Tailwind CSS**](https://tailwindcss.com/) - Utility-first CSS framework
37 | - [**Framer Motion**](https://www.framer.com/motion/) - Animation library
38 | - [**Lucide Icons**](https://lucide.dev/) - Icon set
39 | - Dark mode with Tailwind CSS
40 |
41 | ### 🛠️ Development Tools
42 |
43 | - [**Storybook**](https://storybook.js.org/) - Component development environment
44 | - [**Geist Font**](https://vercel.com/font) - Typography by Vercel
45 |
46 | ### 🤖 AI & Background Jobs
47 |
48 | - Multiple AI integrations available:
49 | - [OpenAI](https://openai.com) - GPT-4 and o-series models
50 | - [Anthropic](https://anthropic.com) - Sonnet-3.5
51 | - [Perplexity](https://perplexity.ai) - Web search models
52 | - [Groq](https://groq.com) - Fast inference
53 | - [**Inngest**](https://www.inngest.com/) - Background jobs and scheduled tasks
54 |
55 | ### 🔧 Infrastructure & Services
56 |
57 | - [**Resend**](https://resend.com) - Email delivery
58 | - [**AWS S3**](https://aws.amazon.com/s3/) - File storage
59 | - [**Supabase**](https://supabase.com) - Primary database
60 | (Note that I don't directly use the supabase client in this template, so you can switch out supabase with other database providers via the DATABASE_URL and DIRECT_URL environment variables.)
61 |
62 | ### 🔔 Additional Features
63 |
64 | - [**react-toastify**](https://fkhadra.github.io/react-toastify/) - Toast notifications
65 | - Utility functions for common operations
66 | - TypeScript and ESLint configuration included
67 |
68 | ## 🚀 Getting Started
69 |
70 | 1. Fork this repository
71 | 2. Install dependencies:
72 |
73 | ```bash
74 | npm install
75 | ```
76 |
77 | 3. Copy `.env.example` to `.env` and configure your environment variables
78 | 4. Set up your database:
79 |
80 | ```bash
81 | npx prisma migrate dev
82 | ```
83 |
84 | 5. Start the development server:
85 |
86 | ```bash
87 | npm run dev
88 | ```
89 |
90 | Visit [http://localhost:3000](http://localhost:3000) to see your app.
91 |
92 | ## 📁 Project Structure
93 |
94 | - `app/` - Next.js app router pages and API routes
95 | - `src/`
96 | - `components/` - UI components
97 | - `lib/` - Utilities and configurations
98 | - `api/` - tRPC routers
99 | - `utils/` - Shared utilities
100 | - `stories/` - Storybook files
101 | - `prisma/` - Database schema
102 |
103 | ## 🚀 Deployment
104 |
105 | This template is optimized for deployment on [Vercel](https://vercel.com).
106 |
107 | ### Database Setup
108 |
109 | 1. Create a new Supabase project at [supabase.com](https://supabase.com)
110 | 2. Get your database connection strings from Supabase:
111 | - Project Settings → Database
112 | - Copy both the URI (for `DATABASE_URL`) and Direct Connection (for `DIRECT_URL`)
113 |
114 | ### Vercel Setup
115 |
116 | 1. Push your code to GitHub
117 | 2. Go to [vercel.com/new](https://vercel.com/new)
118 | 3. Import your repository
119 | 4. Configure the following environment variables:
120 | - `DATABASE_URL` - Your Supabase database URL
121 | - `DIRECT_URL` - Your Supabase direct connection URL
122 | - `NEXTAUTH_SECRET` - Generate with `openssl rand -base64 32`
123 | - `NEXTAUTH_URL` - Your production URL (e.g., https://your-app.vercel.app)
124 | - Add any other variables from `.env.example` that you're using
125 | 5. Deploy!
126 |
127 | ### Post-Deployment
128 |
129 | 1. Run database migrations in the Vercel deployment:
130 |
131 | ```bash
132 | npx vercel env pull .env.production.local # Pull production env vars
133 | npx prisma migrate deploy # Deploy migrations to production
134 | ```
135 |
136 | 2. Set up your custom domain in Vercel (optional):
137 | - Go to your project settings
138 | - Navigate to Domains
139 | - Add your domain and follow the DNS configuration instructions
140 |
141 | ## 📝 License
142 |
143 | MIT License
144 |
--------------------------------------------------------------------------------
/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "default",
4 | "rsc": true,
5 | "tsx": true,
6 | "tailwind": {
7 | "config": "tailwind.config.ts",
8 | "css": "src/app/globals.css",
9 | "baseColor": "neutral",
10 | "cssVariables": false,
11 | "prefix": ""
12 | },
13 | "aliases": {
14 | "components": "@/components",
15 | "utils": "@/lib/utils",
16 | "ui": "@/components/ui",
17 | "lib": "@/lib",
18 | "hooks": "@/hooks"
19 | },
20 | "iconLibrary": "lucide"
21 | }
--------------------------------------------------------------------------------
/inngest.config.ts:
--------------------------------------------------------------------------------
1 | import { Inngest } from "inngest";
2 | import { serve } from "inngest/next";
3 |
4 | // Define event types for better type safety
5 | export type AppEvents = {
6 | "user/registered": {
7 | data: {
8 | userId: string;
9 | email: string;
10 | name?: string;
11 | timestamp: string;
12 | };
13 | };
14 | "inngest/send": {
15 | data: {
16 | message: string;
17 | metadata?: Record;
18 | };
19 | };
20 | };
21 |
22 | // Initialize Inngest with typed events
23 | export const inngest = new Inngest({
24 | id: "newco",
25 | eventKey: "events",
26 | validateEvents: process.env.NODE_ENV === "development",
27 | });
28 |
29 | // Define event handlers
30 | export const userRegisteredFn = inngest.createFunction(
31 | { id: "user-registered-handler" },
32 | { event: "user/registered" },
33 | async ({ event, step }) => {
34 | await step.run("Log registration", async () => {
35 | console.log(`New user registered: ${event.data.email}`);
36 | });
37 |
38 | // Example: Send welcome email
39 | await step.run("Send welcome email", async () => {
40 | // Add your email sending logic here
41 | console.log(`Sending welcome email to ${event.data.email}`);
42 | });
43 | },
44 | );
45 |
46 | export const messageHandlerFn = inngest.createFunction(
47 | { id: "message-handler" },
48 | { event: "inngest/send" },
49 | async ({ event, step }) => {
50 | await step.run("Process message", async () => {
51 | console.log(`Processing message: ${event.data.message}`);
52 | if (event.data.metadata) {
53 | console.log("Metadata:", event.data.metadata);
54 | }
55 | });
56 | },
57 | );
58 |
59 | // Export the serve function for use in API routes
60 | export const serveInngest = serve({
61 | client: inngest,
62 | functions: [userRegisteredFn, messageHandlerFn],
63 | });
64 |
--------------------------------------------------------------------------------
/next.config.ts:
--------------------------------------------------------------------------------
1 | import type { NextConfig } from "next";
2 |
3 | const nextConfig: NextConfig = {
4 | images: {
5 | remotePatterns: [
6 | {
7 | protocol: "https",
8 | hostname: "**",
9 | },
10 | ],
11 | },
12 | };
13 |
14 | export default nextConfig;
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nextjs-template",
3 | "version": "0.1.0",
4 | "private": true,
5 | "type": "module",
6 | "scripts": {
7 | "dev": "next dev --turbopack",
8 | "build": "prisma generate && next build",
9 | "start": "next start",
10 | "lint": "next lint",
11 | "vercel-build": "prisma generate && next build",
12 | "postinstall": "prisma generate",
13 | "storybook": "storybook dev -p 6006",
14 | "build-storybook": "storybook build"
15 | },
16 | "dependencies": {
17 | "@aws-sdk/client-s3": "^3.709.0",
18 | "@fortawesome/free-solid-svg-icons": "^6.7.2",
19 | "@fortawesome/react-fontawesome": "^0.2.2",
20 | "@google/generative-ai": "^0.21.0",
21 | "@next-auth/prisma-adapter": "^1.0.7",
22 | "@prisma/client": "^6.0.1",
23 | "@radix-ui/react-slot": "^1.1.0",
24 | "@shadcn/ui": "^0.0.4",
25 | "@supabase/supabase-js": "^2.47.3",
26 | "@tailwindcss/typography": "^0.5.16",
27 | "@tanstack/react-query": "^5.25.0",
28 | "@trpc/client": "next",
29 | "@trpc/next": "next",
30 | "@trpc/react-query": "next",
31 | "@trpc/server": "next",
32 | "@types/react-datepicker": "^6.2.0",
33 | "class-variance-authority": "^0.7.1",
34 | "clsx": "^2.1.1",
35 | "date-fns": "^4.1.0",
36 | "framer-motion": "^11.15.0",
37 | "groq-sdk": "^0.12.0",
38 | "inngest": "^3.27.5",
39 | "lucide-react": "^0.468.0",
40 | "next": "15.1.0",
41 | "next-auth": "^4.24.11",
42 | "next-themes": "^0.4.4",
43 | "nodemailer": "^6.9.16",
44 | "openai": "^4.80.1",
45 | "prisma": "^6.0.1",
46 | "react": "^19.0.0",
47 | "react-datepicker": "^7.6.0",
48 | "react-dom": "^19.0.0",
49 | "react-icons": "^5.4.0",
50 | "react-toastify": "^11.0.3",
51 | "resend": "^4.0.1",
52 | "superjson": "^2.2.2",
53 | "tailwind-merge": "^2.5.5",
54 | "tailwindcss-animate": "^1.0.7",
55 | "zod": "^3.24.1"
56 | },
57 | "devDependencies": {
58 | "@chromatic-com/storybook": "^3.2.4",
59 | "@storybook/addon-essentials": "^8.5.3",
60 | "@storybook/addon-interactions": "^8.5.3",
61 | "@storybook/addon-links": "^8.5.3",
62 | "@storybook/addon-onboarding": "^8.5.3",
63 | "@storybook/addon-styling-webpack": "^1.0.1",
64 | "@storybook/blocks": "^8.5.3",
65 | "@storybook/nextjs": "^8.5.3",
66 | "@storybook/react": "^8.5.3",
67 | "@storybook/test": "^8.5.3",
68 | "@types/node": "^20",
69 | "@types/react": "^19",
70 | "@types/react-dom": "^19",
71 | "postcss": "^8",
72 | "prisma": "^6.0.1",
73 | "storybook": "^8.5.3",
74 | "tailwindcss": "^3.4.1",
75 | "typescript": "^5"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/postcss.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('postcss-load-config').Config} */
2 | const config = {
3 | plugins: {
4 | tailwindcss: {},
5 | },
6 | };
7 |
8 | export default config;
9 |
--------------------------------------------------------------------------------
/prisma/schema.prisma:
--------------------------------------------------------------------------------
1 | generator client {
2 | provider = "prisma-client-js"
3 | }
4 |
5 | datasource db {
6 | provider = "postgresql"
7 | url = env("DATABASE_URL")
8 | directUrl = env("DIRECT_URL")
9 | }
10 |
11 | model User {
12 | id String @id @default(cuid())
13 | name String?
14 | email String? @unique
15 | emailVerified DateTime?
16 | image String?
17 | hashedPassword String?
18 | createdAt DateTime @default(now())
19 | updatedAt DateTime @updatedAt
20 | login String?
21 | role UserRole @default(user)
22 | isAdmin Boolean @default(false)
23 | accounts Account[]
24 | sessions Session[]
25 | }
26 |
27 | model Account {
28 | id String @id @default(cuid())
29 | userId String
30 | type String
31 | provider String
32 | providerAccountId String
33 | refresh_token String?
34 | access_token String?
35 | expires_at Int?
36 | token_type String?
37 | scope String?
38 | id_token String?
39 | session_state String?
40 | User User @relation(fields: [userId], references: [id])
41 |
42 | @@unique([provider, providerAccountId])
43 | }
44 |
45 | model Session {
46 | id String @id @default(cuid())
47 | sessionToken String @unique
48 | userId String
49 | expires DateTime
50 |
51 | user User @relation(fields: [userId], references: [id], onDelete: Cascade)
52 | }
53 |
54 | enum UserRole {
55 | user
56 | admin
57 | }
58 |
59 | model Allowlist {
60 | id String @id @default(cuid())
61 | email String @unique
62 | createdAt DateTime @default(now())
63 | }
64 |
65 | model VerificationToken {
66 | identifier String
67 | token String @unique
68 | expires DateTime
69 |
70 | @@unique([identifier, token])
71 | }
72 |
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/screenshots/button-stories.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kleneway/next-ai-starter/05457c32a924251495dc52c169c3b59863039d37/screenshots/button-stories.png
--------------------------------------------------------------------------------
/scripts/init.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | APP_NAME="newco"
6 |
7 | echo "🚀 Starting setup..."
8 |
9 | # Remove any existing app directory
10 | rm -rf $APP_NAME
11 |
12 | # 1. Create Next.js TypeScript app with Tailwind, src directory, app router, and no ESLint
13 | echo "🛠 Creating Next.js app..."
14 | npx create-next-app@latest $APP_NAME --ts --tailwind --src-dir --app --no-eslint --use-npm
15 |
16 | cd $APP_NAME
17 |
18 | # 2. Install dependencies
19 | echo "📦 Installing dependencies..."
20 | npm install zod @tanstack/react-query @shadcn/ui prisma @prisma/client @next-auth/prisma-adapter next-auth resend @aws-sdk/client-s3 inngest @supabase/supabase-js
21 |
22 | # Prisma init
23 | echo "🗄 Initializing Prisma..."
24 | npx prisma init
25 |
26 | # Overwrite Prisma schema to support NextAuth
27 | cat > prisma/schema.prisma < src/app/globals.css < src/app/layout.tsx <
127 | {children}
128 |