refactor/ migrate from OpenAI to OpenRouter integration
Major improvements to AI integration and developer experience: ## OpenRouter Migration - Replaced @ai-sdk/openai with @openrouter/ai-sdk-provider - Updated chat API route to use OpenRouter for access to 100+ AI models - Changed environment variables from OPENAI_* to OPENROUTER_* - Updated default model from gpt-5-mini to openai/gpt-5-mini - Benefits: Users can now access multiple AI providers (OpenAI, Anthropic, etc.) through a single unified API ## Documentation Overhaul - Expanded CLAUDE.md from 3 lines to comprehensive 225-line guide - Added complete project structure, tech stack overview, and AI integration guidelines - Documented all environment variables, scripts, and common tasks - Added critical rules for AI assistants working with the codebase - Enhanced checkpoint command with detailed step-by-step instructions ## README Updates - Updated feature list to highlight OpenRouter integration - Revised setup instructions for OpenRouter API key acquisition - Updated environment variable examples and deployment configuration - Changed all OpenAI references to OpenRouter throughout documentation ## Create Command Updates - Bumped create-agentic-app version from 1.0.0 to 1.0.1 - Synchronized all template files with main project documentation - Updated template env.example and package.json with OpenRouter configuration ## Dependency Updates - Added @openrouter/ai-sdk-provider@^1.2.0 - Updated @ai-sdk/openai from ^2.0.53 to ^2.0.60 - Updated @ai-sdk/react from ^2.0.78 to ^2.0.86 - Updated ai from ^5.0.78 to ^5.0.86 - Updated better-auth from ^1.3.29 to ^1.3.34 - Updated drizzle-kit from ^0.31.5 to ^0.31.6 - Updated eslint from ^9.38.0 to ^9.39.0 - Various type definition updates Breaking Changes: - Projects must update environment variables from OPENAI_* to OPENROUTER_* - API keys must be obtained from openrouter.ai instead of platform.openai.com - Model names now follow OpenRouter format (e.g., "openai/gpt-5-mini") 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,2 +1,32 @@
|
|||||||
Please commit all changes and provide a suitable comment for the commit.
|
Please create a comprehensive checkpoint commit with the following steps:
|
||||||
Run git init if git has not been instantiated for the project as yet.
|
|
||||||
|
1. **Initialize Git if needed**: Run `git init` if git has not been instantiated for the project yet.
|
||||||
|
|
||||||
|
2. **Analyze all changes**:
|
||||||
|
- Run `git status` to see all tracked and untracked files
|
||||||
|
- Run `git diff` to see detailed changes in tracked files
|
||||||
|
- Run `git log -5 --oneline` to understand the commit message style of this repository
|
||||||
|
|
||||||
|
3. **Stage everything**:
|
||||||
|
- Add ALL tracked changes (modified and deleted files)
|
||||||
|
- Add ALL untracked files (new files)
|
||||||
|
- Use `git add -A` or `git add .` to stage everything
|
||||||
|
|
||||||
|
4. **Create a detailed commit message**:
|
||||||
|
- **First line**: Write a clear, concise summary (50-72 chars) describing the primary change
|
||||||
|
- Use imperative mood (e.g., "Add feature" not "Added feature")
|
||||||
|
- Examples: "feat: add user authentication", "fix: resolve database connection issue", "refactor: improve API route structure"
|
||||||
|
- **Body**: Provide a detailed description including:
|
||||||
|
- What changes were made (list of key modifications)
|
||||||
|
- Why these changes were made (purpose/motivation)
|
||||||
|
- Any important technical details or decisions
|
||||||
|
- Breaking changes or migration notes if applicable
|
||||||
|
- **Footer**: Include co-author attribution as shown in the Git Safety Protocol
|
||||||
|
|
||||||
|
5. **Execute the commit**: Create the commit with the properly formatted message following this repository's conventions.
|
||||||
|
|
||||||
|
IMPORTANT:
|
||||||
|
- Do NOT skip any files - include everything
|
||||||
|
- Make the commit message descriptive enough that someone reviewing the git log can understand what was accomplished
|
||||||
|
- Follow the project's existing commit message conventions (check git log first)
|
||||||
|
- Include the Claude Code co-author attribution in the commit message
|
||||||
|
|||||||
228
CLAUDE.md
228
CLAUDE.md
@@ -1,3 +1,225 @@
|
|||||||
- Always run the LINT and TYPESCHECK scripts after completing your changes. This is to check for any issues.
|
# Agentic Coding Boilerplate - AI Assistant Guidelines
|
||||||
- NEVER start the dev server yourself. If you need something from the terminal, ask the user to provide it to you.
|
|
||||||
- Avoid using custom colors unless very specifically instructed to do so. Stick to standard tailwind and shadcn colors, styles and tokens.
|
## Project Overview
|
||||||
|
|
||||||
|
This is a Next.js 15 boilerplate for building AI-powered applications with authentication, database, and modern UI components.
|
||||||
|
|
||||||
|
### Tech Stack
|
||||||
|
|
||||||
|
- **Framework**: Next.js 15 with App Router, React 19, TypeScript
|
||||||
|
- **AI Integration**: Vercel AI SDK 5 + OpenRouter (access to 100+ AI models)
|
||||||
|
- **Authentication**: BetterAuth with Google OAuth
|
||||||
|
- **Database**: PostgreSQL with Drizzle ORM
|
||||||
|
- **UI**: shadcn/ui components with Tailwind CSS 4
|
||||||
|
- **Styling**: Tailwind CSS with dark mode support (next-themes)
|
||||||
|
|
||||||
|
## AI Integration with OpenRouter
|
||||||
|
|
||||||
|
### Key Points
|
||||||
|
|
||||||
|
- This project uses **OpenRouter** as the AI provider, NOT direct OpenAI
|
||||||
|
- OpenRouter provides access to 100+ AI models through a single unified API
|
||||||
|
- Default model: `openai/gpt-5-mini` (configurable via `OPENROUTER_MODEL` env var)
|
||||||
|
- Users browse models at: https://openrouter.ai/models
|
||||||
|
- Users get API keys from: https://openrouter.ai/settings/keys
|
||||||
|
|
||||||
|
### AI Implementation Files
|
||||||
|
|
||||||
|
- `src/app/api/chat/route.ts` - Chat API endpoint using OpenRouter
|
||||||
|
- Package: `@openrouter/ai-sdk-provider` (not `@ai-sdk/openai`)
|
||||||
|
- Import: `import { openrouter } from "@openrouter/ai-sdk-provider"`
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── app/ # Next.js App Router
|
||||||
|
│ ├── api/
|
||||||
|
│ │ ├── auth/[...all]/ # Better Auth catch-all route
|
||||||
|
│ │ ├── chat/route.ts # AI chat endpoint (OpenRouter)
|
||||||
|
│ │ └── diagnostics/ # System diagnostics
|
||||||
|
│ ├── chat/page.tsx # AI chat interface (protected)
|
||||||
|
│ ├── dashboard/page.tsx # User dashboard (protected)
|
||||||
|
│ ├── profile/page.tsx # User profile (protected)
|
||||||
|
│ ├── page.tsx # Home/landing page
|
||||||
|
│ └── layout.tsx # Root layout
|
||||||
|
├── components/
|
||||||
|
│ ├── auth/ # Authentication components
|
||||||
|
│ │ ├── sign-in-button.tsx
|
||||||
|
│ │ ├── sign-out-button.tsx
|
||||||
|
│ │ └── user-profile.tsx
|
||||||
|
│ ├── ui/ # shadcn/ui components
|
||||||
|
│ │ ├── button.tsx
|
||||||
|
│ │ ├── card.tsx
|
||||||
|
│ │ ├── dialog.tsx
|
||||||
|
│ │ ├── dropdown-menu.tsx
|
||||||
|
│ │ ├── avatar.tsx
|
||||||
|
│ │ ├── badge.tsx
|
||||||
|
│ │ ├── separator.tsx
|
||||||
|
│ │ ├── mode-toggle.tsx # Dark/light mode toggle
|
||||||
|
│ │ └── github-stars.tsx
|
||||||
|
│ ├── site-header.tsx # Main navigation header
|
||||||
|
│ ├── site-footer.tsx # Footer component
|
||||||
|
│ ├── theme-provider.tsx # Dark mode provider
|
||||||
|
│ ├── setup-checklist.tsx # Setup guide component
|
||||||
|
│ └── starter-prompt-modal.tsx # Starter prompts modal
|
||||||
|
└── lib/
|
||||||
|
├── auth.ts # Better Auth server config
|
||||||
|
├── auth-client.ts # Better Auth client hooks
|
||||||
|
├── db.ts # Database connection
|
||||||
|
├── schema.ts # Drizzle schema (users, sessions, etc.)
|
||||||
|
└── utils.ts # Utility functions (cn, etc.)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
Required environment variables (see `env.example`):
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Database
|
||||||
|
POSTGRES_URL=postgresql://user:password@localhost:5432/db_name
|
||||||
|
|
||||||
|
# Better Auth
|
||||||
|
BETTER_AUTH_SECRET=32-char-random-string
|
||||||
|
|
||||||
|
# Google OAuth
|
||||||
|
GOOGLE_CLIENT_ID=your-google-client-id
|
||||||
|
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||||||
|
|
||||||
|
# AI via OpenRouter
|
||||||
|
OPENROUTER_API_KEY=sk-or-v1-your-key
|
||||||
|
OPENROUTER_MODEL=openai/gpt-5-mini # or any model from openrouter.ai/models
|
||||||
|
|
||||||
|
# App
|
||||||
|
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev # Start dev server (DON'T run this yourself - ask user)
|
||||||
|
npm run build # Build for production (runs db:migrate first)
|
||||||
|
npm run start # Start production server
|
||||||
|
npm run lint # Run ESLint (ALWAYS run after changes)
|
||||||
|
npm run typecheck # TypeScript type checking (ALWAYS run after changes)
|
||||||
|
npm run db:generate # Generate database migrations
|
||||||
|
npm run db:migrate # Run database migrations
|
||||||
|
npm run db:push # Push schema changes to database
|
||||||
|
npm run db:studio # Open Drizzle Studio (database GUI)
|
||||||
|
npm run db:dev # Push schema for development
|
||||||
|
npm run db:reset # Reset database (drop all tables)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation Files
|
||||||
|
|
||||||
|
The project includes technical documentation in `docs/`:
|
||||||
|
|
||||||
|
- `docs/technical/ai/streaming.md` - AI streaming implementation guide
|
||||||
|
- `docs/technical/ai/structured-data.md` - Structured data extraction
|
||||||
|
- `docs/technical/react-markdown.md` - Markdown rendering guide
|
||||||
|
- `docs/technical/betterauth/polar.md` - Polar payment integration
|
||||||
|
- `docs/business/starter-prompt.md` - Business context for AI prompts
|
||||||
|
|
||||||
|
## Guidelines for AI Assistants
|
||||||
|
|
||||||
|
### CRITICAL RULES
|
||||||
|
|
||||||
|
1. **ALWAYS run lint and typecheck** after completing changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run lint && npm run typecheck
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **NEVER start the dev server yourself**
|
||||||
|
|
||||||
|
- If you need dev server output, ask the user to provide it
|
||||||
|
- Don't run `npm run dev` or `pnpm dev`
|
||||||
|
|
||||||
|
3. **Use OpenRouter, NOT OpenAI directly**
|
||||||
|
|
||||||
|
- Import from `@openrouter/ai-sdk-provider`
|
||||||
|
- Use `openrouter()` function, not `openai()`
|
||||||
|
- Model names follow OpenRouter format: `provider/model-name`
|
||||||
|
|
||||||
|
4. **Styling Guidelines**
|
||||||
|
|
||||||
|
- Stick to standard Tailwind CSS utility classes
|
||||||
|
- Use shadcn/ui color tokens (e.g., `bg-background`, `text-foreground`)
|
||||||
|
- Avoid custom colors unless explicitly requested
|
||||||
|
- Support dark mode with appropriate Tailwind classes
|
||||||
|
|
||||||
|
5. **Authentication**
|
||||||
|
|
||||||
|
- Server-side: Import from `@/lib/auth` (Better Auth instance)
|
||||||
|
- Client-side: Import hooks from `@/lib/auth-client`
|
||||||
|
- Protected routes should check session in Server Components
|
||||||
|
- Use existing auth components from `src/components/auth/`
|
||||||
|
|
||||||
|
6. **Database Operations**
|
||||||
|
|
||||||
|
- Use Drizzle ORM (imported from `@/lib/db`)
|
||||||
|
- Schema is defined in `@/lib/schema`
|
||||||
|
- Always run migrations after schema changes
|
||||||
|
- PostgreSQL is the database (not SQLite, MySQL, etc.)
|
||||||
|
|
||||||
|
7. **Component Creation**
|
||||||
|
|
||||||
|
- Use existing shadcn/ui components when possible
|
||||||
|
- Follow the established patterns in `src/components/ui/`
|
||||||
|
- Support both light and dark modes
|
||||||
|
- Use TypeScript with proper types
|
||||||
|
|
||||||
|
8. **API Routes**
|
||||||
|
- Follow Next.js 15 App Router conventions
|
||||||
|
- Use Route Handlers (route.ts files)
|
||||||
|
- Return Response objects
|
||||||
|
- Handle errors appropriately
|
||||||
|
|
||||||
|
### Best Practices
|
||||||
|
|
||||||
|
- Read existing code patterns before creating new features
|
||||||
|
- Maintain consistency with established file structure
|
||||||
|
- Use the documentation files when implementing related features
|
||||||
|
- Test changes with lint and typecheck before considering complete
|
||||||
|
- When modifying AI functionality, refer to `docs/technical/ai/` guides
|
||||||
|
|
||||||
|
### Common Tasks
|
||||||
|
|
||||||
|
**Adding a new page:**
|
||||||
|
|
||||||
|
1. Create in `src/app/[route]/page.tsx`
|
||||||
|
2. Use Server Components by default
|
||||||
|
3. Add to navigation if needed
|
||||||
|
|
||||||
|
**Adding a new API route:**
|
||||||
|
|
||||||
|
1. Create in `src/app/api/[route]/route.ts`
|
||||||
|
2. Export HTTP method handlers (GET, POST, etc.)
|
||||||
|
3. Use proper TypeScript types
|
||||||
|
|
||||||
|
**Adding authentication to a page:**
|
||||||
|
|
||||||
|
1. Import auth instance: `import { auth } from "@/lib/auth"`
|
||||||
|
2. Get session: `const session = await auth.api.getSession({ headers: await headers() })`
|
||||||
|
3. Check session and redirect if needed
|
||||||
|
|
||||||
|
**Working with the database:**
|
||||||
|
|
||||||
|
1. Update schema in `src/lib/schema.ts`
|
||||||
|
2. Generate migration: `npm run db:generate`
|
||||||
|
3. Apply migration: `npm run db:migrate`
|
||||||
|
4. Import `db` from `@/lib/db` to query
|
||||||
|
|
||||||
|
**Modifying AI chat:**
|
||||||
|
|
||||||
|
1. Backend: `src/app/api/chat/route.ts`
|
||||||
|
2. Frontend: `src/app/chat/page.tsx`
|
||||||
|
3. Reference streaming docs: `docs/technical/ai/streaming.md`
|
||||||
|
4. Remember to use OpenRouter, not direct OpenAI
|
||||||
|
|
||||||
|
## Package Manager
|
||||||
|
|
||||||
|
This project uses **pnpm** (see `pnpm-lock.yaml`). When running commands:
|
||||||
|
|
||||||
|
- Use `pnpm` instead of `npm` when possible
|
||||||
|
- Scripts defined in package.json work with `pnpm run [script]`
|
||||||
|
|||||||
29
README.md
29
README.md
@@ -6,7 +6,7 @@ A complete agentic coding boilerplate with authentication, PostgreSQL database,
|
|||||||
|
|
||||||
- **🔐 Authentication**: Better Auth with Google OAuth integration
|
- **🔐 Authentication**: Better Auth with Google OAuth integration
|
||||||
- **🗃️ Database**: Drizzle ORM with PostgreSQL
|
- **🗃️ Database**: Drizzle ORM with PostgreSQL
|
||||||
- **🤖 AI Integration**: Vercel AI SDK with OpenAI support
|
- **🤖 AI Integration**: Vercel AI SDK with OpenRouter (access to 100+ AI models)
|
||||||
- **🎨 UI Components**: shadcn/ui with Tailwind CSS
|
- **🎨 UI Components**: shadcn/ui with Tailwind CSS
|
||||||
- **⚡ Modern Stack**: Next.js 15, React 19, TypeScript
|
- **⚡ Modern Stack**: Next.js 15, React 19, TypeScript
|
||||||
- **📱 Responsive**: Mobile-first design approach
|
- **📱 Responsive**: Mobile-first design approach
|
||||||
@@ -105,9 +105,11 @@ BETTER_AUTH_SECRET="your-random-32-character-secret-key-here"
|
|||||||
GOOGLE_CLIENT_ID="your-google-client-id"
|
GOOGLE_CLIENT_ID="your-google-client-id"
|
||||||
GOOGLE_CLIENT_SECRET="your-google-client-secret"
|
GOOGLE_CLIENT_SECRET="your-google-client-secret"
|
||||||
|
|
||||||
# AI Integration (Optional - for chat functionality)
|
# AI Integration via OpenRouter (Optional - for chat functionality)
|
||||||
OPENAI_API_KEY="sk-your-openai-api-key-here"
|
# Get your API key from: https://openrouter.ai/settings/keys
|
||||||
OPENAI_MODEL="gpt-5-mini"
|
# View available models at: https://openrouter.ai/models
|
||||||
|
OPENROUTER_API_KEY="sk-or-v1-your-openrouter-api-key-here"
|
||||||
|
OPENROUTER_MODEL="openai/gpt-5-mini"
|
||||||
|
|
||||||
# App URL (for production deployments)
|
# App URL (for production deployments)
|
||||||
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
||||||
@@ -152,13 +154,14 @@ Your application will be available at [http://localhost:3000](http://localhost:3
|
|||||||
- `https://yourdomain.com/api/auth/callback/google` (production)
|
- `https://yourdomain.com/api/auth/callback/google` (production)
|
||||||
6. Copy the **Client ID** and **Client Secret** to your `.env` file
|
6. Copy the **Client ID** and **Client Secret** to your `.env` file
|
||||||
|
|
||||||
### OpenAI API Key
|
### OpenRouter API Key
|
||||||
|
|
||||||
1. Go to <a href="https://platform.openai.com/dashboard" target="_blank">OpenAI Platform</a>
|
1. Go to <a href="https://openrouter.ai/" target="_blank">OpenRouter</a>
|
||||||
2. Navigate to **API Keys** in the sidebar
|
2. Sign up or log in to your account
|
||||||
3. Click **Create new secret key**
|
3. Navigate to **Settings** → **Keys** or visit <a href="https://openrouter.ai/settings/keys" target="_blank">Keys Settings</a>
|
||||||
4. Give it a name and copy the key
|
4. Click **Create Key** and give it a name
|
||||||
5. Add it to your `.env` file as `OPENAI_API_KEY`
|
5. Copy the API key and add it to your `.env` file as `OPENROUTER_API_KEY`
|
||||||
|
6. Browse available models at <a href="https://openrouter.ai/models" target="_blank">OpenRouter Models</a>
|
||||||
|
|
||||||
## 🗂️ Project Structure
|
## 🗂️ Project Structure
|
||||||
|
|
||||||
@@ -201,7 +204,7 @@ npm run db:reset # Reset database (drop all tables)
|
|||||||
|
|
||||||
- **Home (`/`)**: Landing page with setup instructions and features overview
|
- **Home (`/`)**: Landing page with setup instructions and features overview
|
||||||
- **Dashboard (`/dashboard`)**: Protected user dashboard with profile information
|
- **Dashboard (`/dashboard`)**: Protected user dashboard with profile information
|
||||||
- **Chat (`/chat`)**: AI-powered chat interface using OpenAI (requires authentication)
|
- **Chat (`/chat`)**: AI-powered chat interface using OpenRouter (requires authentication)
|
||||||
|
|
||||||
## 🚀 Deployment
|
## 🚀 Deployment
|
||||||
|
|
||||||
@@ -230,8 +233,8 @@ Ensure these are set in your production environment:
|
|||||||
- `BETTER_AUTH_SECRET` - Secure random 32+ character string
|
- `BETTER_AUTH_SECRET` - Secure random 32+ character string
|
||||||
- `GOOGLE_CLIENT_ID` - Google OAuth Client ID
|
- `GOOGLE_CLIENT_ID` - Google OAuth Client ID
|
||||||
- `GOOGLE_CLIENT_SECRET` - Google OAuth Client Secret
|
- `GOOGLE_CLIENT_SECRET` - Google OAuth Client Secret
|
||||||
- `OPENAI_API_KEY` - OpenAI API key (optional)
|
- `OPENROUTER_API_KEY` - OpenRouter API key (optional, for AI chat functionality)
|
||||||
- `OPENAI_MODEL` - OpenAI model name (optional, defaults to gpt-5-mini)
|
- `OPENROUTER_MODEL` - Model name from OpenRouter (optional, defaults to openai/gpt-5-mini)
|
||||||
- `NEXT_PUBLIC_APP_URL` - Your production domain
|
- `NEXT_PUBLIC_APP_URL` - Your production domain
|
||||||
|
|
||||||
## 🎥 Tutorial Video
|
## 🎥 Tutorial Video
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "create-agentic-app",
|
"name": "create-agentic-app",
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"description": "Scaffold a new agentic AI application with Next.js, Better Auth, and AI SDK",
|
"description": "Scaffold a new agentic AI application with Next.js, Better Auth, and AI SDK",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|||||||
@@ -1,3 +1,225 @@
|
|||||||
- Always run the LINT and TYPESCHECK scripts after completing your changes. This is to check for any issues.
|
# Agentic Coding Boilerplate - AI Assistant Guidelines
|
||||||
- NEVER start the dev server yourself. If you need something from the terminal, ask the user to provide it to you.
|
|
||||||
- Avoid using custom colors unless very specifically instructed to do so. Stick to standard tailwind and shadcn colors, styles and tokens.
|
## Project Overview
|
||||||
|
|
||||||
|
This is a Next.js 15 boilerplate for building AI-powered applications with authentication, database, and modern UI components.
|
||||||
|
|
||||||
|
### Tech Stack
|
||||||
|
|
||||||
|
- **Framework**: Next.js 15 with App Router, React 19, TypeScript
|
||||||
|
- **AI Integration**: Vercel AI SDK 5 + OpenRouter (access to 100+ AI models)
|
||||||
|
- **Authentication**: BetterAuth with Google OAuth
|
||||||
|
- **Database**: PostgreSQL with Drizzle ORM
|
||||||
|
- **UI**: shadcn/ui components with Tailwind CSS 4
|
||||||
|
- **Styling**: Tailwind CSS with dark mode support (next-themes)
|
||||||
|
|
||||||
|
## AI Integration with OpenRouter
|
||||||
|
|
||||||
|
### Key Points
|
||||||
|
|
||||||
|
- This project uses **OpenRouter** as the AI provider, NOT direct OpenAI
|
||||||
|
- OpenRouter provides access to 100+ AI models through a single unified API
|
||||||
|
- Default model: `openai/gpt-5-mini` (configurable via `OPENROUTER_MODEL` env var)
|
||||||
|
- Users browse models at: https://openrouter.ai/models
|
||||||
|
- Users get API keys from: https://openrouter.ai/settings/keys
|
||||||
|
|
||||||
|
### AI Implementation Files
|
||||||
|
|
||||||
|
- `src/app/api/chat/route.ts` - Chat API endpoint using OpenRouter
|
||||||
|
- Package: `@openrouter/ai-sdk-provider` (not `@ai-sdk/openai`)
|
||||||
|
- Import: `import { openrouter } from "@openrouter/ai-sdk-provider"`
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
src/
|
||||||
|
├── app/ # Next.js App Router
|
||||||
|
│ ├── api/
|
||||||
|
│ │ ├── auth/[...all]/ # Better Auth catch-all route
|
||||||
|
│ │ ├── chat/route.ts # AI chat endpoint (OpenRouter)
|
||||||
|
│ │ └── diagnostics/ # System diagnostics
|
||||||
|
│ ├── chat/page.tsx # AI chat interface (protected)
|
||||||
|
│ ├── dashboard/page.tsx # User dashboard (protected)
|
||||||
|
│ ├── profile/page.tsx # User profile (protected)
|
||||||
|
│ ├── page.tsx # Home/landing page
|
||||||
|
│ └── layout.tsx # Root layout
|
||||||
|
├── components/
|
||||||
|
│ ├── auth/ # Authentication components
|
||||||
|
│ │ ├── sign-in-button.tsx
|
||||||
|
│ │ ├── sign-out-button.tsx
|
||||||
|
│ │ └── user-profile.tsx
|
||||||
|
│ ├── ui/ # shadcn/ui components
|
||||||
|
│ │ ├── button.tsx
|
||||||
|
│ │ ├── card.tsx
|
||||||
|
│ │ ├── dialog.tsx
|
||||||
|
│ │ ├── dropdown-menu.tsx
|
||||||
|
│ │ ├── avatar.tsx
|
||||||
|
│ │ ├── badge.tsx
|
||||||
|
│ │ ├── separator.tsx
|
||||||
|
│ │ ├── mode-toggle.tsx # Dark/light mode toggle
|
||||||
|
│ │ └── github-stars.tsx
|
||||||
|
│ ├── site-header.tsx # Main navigation header
|
||||||
|
│ ├── site-footer.tsx # Footer component
|
||||||
|
│ ├── theme-provider.tsx # Dark mode provider
|
||||||
|
│ ├── setup-checklist.tsx # Setup guide component
|
||||||
|
│ └── starter-prompt-modal.tsx # Starter prompts modal
|
||||||
|
└── lib/
|
||||||
|
├── auth.ts # Better Auth server config
|
||||||
|
├── auth-client.ts # Better Auth client hooks
|
||||||
|
├── db.ts # Database connection
|
||||||
|
├── schema.ts # Drizzle schema (users, sessions, etc.)
|
||||||
|
└── utils.ts # Utility functions (cn, etc.)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
Required environment variables (see `env.example`):
|
||||||
|
|
||||||
|
```env
|
||||||
|
# Database
|
||||||
|
POSTGRES_URL=postgresql://user:password@localhost:5432/db_name
|
||||||
|
|
||||||
|
# Better Auth
|
||||||
|
BETTER_AUTH_SECRET=32-char-random-string
|
||||||
|
|
||||||
|
# Google OAuth
|
||||||
|
GOOGLE_CLIENT_ID=your-google-client-id
|
||||||
|
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||||||
|
|
||||||
|
# AI via OpenRouter
|
||||||
|
OPENROUTER_API_KEY=sk-or-v1-your-key
|
||||||
|
OPENROUTER_MODEL=openai/gpt-5-mini # or any model from openrouter.ai/models
|
||||||
|
|
||||||
|
# App
|
||||||
|
NEXT_PUBLIC_APP_URL=http://localhost:3000
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Scripts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev # Start dev server (DON'T run this yourself - ask user)
|
||||||
|
npm run build # Build for production (runs db:migrate first)
|
||||||
|
npm run start # Start production server
|
||||||
|
npm run lint # Run ESLint (ALWAYS run after changes)
|
||||||
|
npm run typecheck # TypeScript type checking (ALWAYS run after changes)
|
||||||
|
npm run db:generate # Generate database migrations
|
||||||
|
npm run db:migrate # Run database migrations
|
||||||
|
npm run db:push # Push schema changes to database
|
||||||
|
npm run db:studio # Open Drizzle Studio (database GUI)
|
||||||
|
npm run db:dev # Push schema for development
|
||||||
|
npm run db:reset # Reset database (drop all tables)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Documentation Files
|
||||||
|
|
||||||
|
The project includes technical documentation in `docs/`:
|
||||||
|
|
||||||
|
- `docs/technical/ai/streaming.md` - AI streaming implementation guide
|
||||||
|
- `docs/technical/ai/structured-data.md` - Structured data extraction
|
||||||
|
- `docs/technical/react-markdown.md` - Markdown rendering guide
|
||||||
|
- `docs/technical/betterauth/polar.md` - Polar payment integration
|
||||||
|
- `docs/business/starter-prompt.md` - Business context for AI prompts
|
||||||
|
|
||||||
|
## Guidelines for AI Assistants
|
||||||
|
|
||||||
|
### CRITICAL RULES
|
||||||
|
|
||||||
|
1. **ALWAYS run lint and typecheck** after completing changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run lint && npm run typecheck
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **NEVER start the dev server yourself**
|
||||||
|
|
||||||
|
- If you need dev server output, ask the user to provide it
|
||||||
|
- Don't run `npm run dev` or `pnpm dev`
|
||||||
|
|
||||||
|
3. **Use OpenRouter, NOT OpenAI directly**
|
||||||
|
|
||||||
|
- Import from `@openrouter/ai-sdk-provider`
|
||||||
|
- Use `openrouter()` function, not `openai()`
|
||||||
|
- Model names follow OpenRouter format: `provider/model-name`
|
||||||
|
|
||||||
|
4. **Styling Guidelines**
|
||||||
|
|
||||||
|
- Stick to standard Tailwind CSS utility classes
|
||||||
|
- Use shadcn/ui color tokens (e.g., `bg-background`, `text-foreground`)
|
||||||
|
- Avoid custom colors unless explicitly requested
|
||||||
|
- Support dark mode with appropriate Tailwind classes
|
||||||
|
|
||||||
|
5. **Authentication**
|
||||||
|
|
||||||
|
- Server-side: Import from `@/lib/auth` (Better Auth instance)
|
||||||
|
- Client-side: Import hooks from `@/lib/auth-client`
|
||||||
|
- Protected routes should check session in Server Components
|
||||||
|
- Use existing auth components from `src/components/auth/`
|
||||||
|
|
||||||
|
6. **Database Operations**
|
||||||
|
|
||||||
|
- Use Drizzle ORM (imported from `@/lib/db`)
|
||||||
|
- Schema is defined in `@/lib/schema`
|
||||||
|
- Always run migrations after schema changes
|
||||||
|
- PostgreSQL is the database (not SQLite, MySQL, etc.)
|
||||||
|
|
||||||
|
7. **Component Creation**
|
||||||
|
|
||||||
|
- Use existing shadcn/ui components when possible
|
||||||
|
- Follow the established patterns in `src/components/ui/`
|
||||||
|
- Support both light and dark modes
|
||||||
|
- Use TypeScript with proper types
|
||||||
|
|
||||||
|
8. **API Routes**
|
||||||
|
- Follow Next.js 15 App Router conventions
|
||||||
|
- Use Route Handlers (route.ts files)
|
||||||
|
- Return Response objects
|
||||||
|
- Handle errors appropriately
|
||||||
|
|
||||||
|
### Best Practices
|
||||||
|
|
||||||
|
- Read existing code patterns before creating new features
|
||||||
|
- Maintain consistency with established file structure
|
||||||
|
- Use the documentation files when implementing related features
|
||||||
|
- Test changes with lint and typecheck before considering complete
|
||||||
|
- When modifying AI functionality, refer to `docs/technical/ai/` guides
|
||||||
|
|
||||||
|
### Common Tasks
|
||||||
|
|
||||||
|
**Adding a new page:**
|
||||||
|
|
||||||
|
1. Create in `src/app/[route]/page.tsx`
|
||||||
|
2. Use Server Components by default
|
||||||
|
3. Add to navigation if needed
|
||||||
|
|
||||||
|
**Adding a new API route:**
|
||||||
|
|
||||||
|
1. Create in `src/app/api/[route]/route.ts`
|
||||||
|
2. Export HTTP method handlers (GET, POST, etc.)
|
||||||
|
3. Use proper TypeScript types
|
||||||
|
|
||||||
|
**Adding authentication to a page:**
|
||||||
|
|
||||||
|
1. Import auth instance: `import { auth } from "@/lib/auth"`
|
||||||
|
2. Get session: `const session = await auth.api.getSession({ headers: await headers() })`
|
||||||
|
3. Check session and redirect if needed
|
||||||
|
|
||||||
|
**Working with the database:**
|
||||||
|
|
||||||
|
1. Update schema in `src/lib/schema.ts`
|
||||||
|
2. Generate migration: `npm run db:generate`
|
||||||
|
3. Apply migration: `npm run db:migrate`
|
||||||
|
4. Import `db` from `@/lib/db` to query
|
||||||
|
|
||||||
|
**Modifying AI chat:**
|
||||||
|
|
||||||
|
1. Backend: `src/app/api/chat/route.ts`
|
||||||
|
2. Frontend: `src/app/chat/page.tsx`
|
||||||
|
3. Reference streaming docs: `docs/technical/ai/streaming.md`
|
||||||
|
4. Remember to use OpenRouter, not direct OpenAI
|
||||||
|
|
||||||
|
## Package Manager
|
||||||
|
|
||||||
|
This project uses **pnpm** (see `pnpm-lock.yaml`). When running commands:
|
||||||
|
|
||||||
|
- Use `pnpm` instead of `npm` when possible
|
||||||
|
- Scripts defined in package.json work with `pnpm run [script]`
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ A complete agentic coding boilerplate with authentication, PostgreSQL database,
|
|||||||
|
|
||||||
- **🔐 Authentication**: Better Auth with Google OAuth integration
|
- **🔐 Authentication**: Better Auth with Google OAuth integration
|
||||||
- **🗃️ Database**: Drizzle ORM with PostgreSQL
|
- **🗃️ Database**: Drizzle ORM with PostgreSQL
|
||||||
- **🤖 AI Integration**: Vercel AI SDK with OpenAI support
|
- **🤖 AI Integration**: Vercel AI SDK with OpenRouter (access to 100+ AI models)
|
||||||
- **🎨 UI Components**: shadcn/ui with Tailwind CSS
|
- **🎨 UI Components**: shadcn/ui with Tailwind CSS
|
||||||
- **⚡ Modern Stack**: Next.js 15, React 19, TypeScript
|
- **⚡ Modern Stack**: Next.js 15, React 19, TypeScript
|
||||||
- **📱 Responsive**: Mobile-first design approach
|
- **📱 Responsive**: Mobile-first design approach
|
||||||
@@ -105,9 +105,11 @@ BETTER_AUTH_SECRET="your-random-32-character-secret-key-here"
|
|||||||
GOOGLE_CLIENT_ID="your-google-client-id"
|
GOOGLE_CLIENT_ID="your-google-client-id"
|
||||||
GOOGLE_CLIENT_SECRET="your-google-client-secret"
|
GOOGLE_CLIENT_SECRET="your-google-client-secret"
|
||||||
|
|
||||||
# AI Integration (Optional - for chat functionality)
|
# AI Integration via OpenRouter (Optional - for chat functionality)
|
||||||
OPENAI_API_KEY="sk-your-openai-api-key-here"
|
# Get your API key from: https://openrouter.ai/settings/keys
|
||||||
OPENAI_MODEL="gpt-5-mini"
|
# View available models at: https://openrouter.ai/models
|
||||||
|
OPENROUTER_API_KEY="sk-or-v1-your-openrouter-api-key-here"
|
||||||
|
OPENROUTER_MODEL="openai/gpt-5-mini"
|
||||||
|
|
||||||
# App URL (for production deployments)
|
# App URL (for production deployments)
|
||||||
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
NEXT_PUBLIC_APP_URL="http://localhost:3000"
|
||||||
@@ -152,13 +154,14 @@ Your application will be available at [http://localhost:3000](http://localhost:3
|
|||||||
- `https://yourdomain.com/api/auth/callback/google` (production)
|
- `https://yourdomain.com/api/auth/callback/google` (production)
|
||||||
6. Copy the **Client ID** and **Client Secret** to your `.env` file
|
6. Copy the **Client ID** and **Client Secret** to your `.env` file
|
||||||
|
|
||||||
### OpenAI API Key
|
### OpenRouter API Key
|
||||||
|
|
||||||
1. Go to <a href="https://platform.openai.com/dashboard" target="_blank">OpenAI Platform</a>
|
1. Go to <a href="https://openrouter.ai/" target="_blank">OpenRouter</a>
|
||||||
2. Navigate to **API Keys** in the sidebar
|
2. Sign up or log in to your account
|
||||||
3. Click **Create new secret key**
|
3. Navigate to **Settings** → **Keys** or visit <a href="https://openrouter.ai/settings/keys" target="_blank">Keys Settings</a>
|
||||||
4. Give it a name and copy the key
|
4. Click **Create Key** and give it a name
|
||||||
5. Add it to your `.env` file as `OPENAI_API_KEY`
|
5. Copy the API key and add it to your `.env` file as `OPENROUTER_API_KEY`
|
||||||
|
6. Browse available models at <a href="https://openrouter.ai/models" target="_blank">OpenRouter Models</a>
|
||||||
|
|
||||||
## 🗂️ Project Structure
|
## 🗂️ Project Structure
|
||||||
|
|
||||||
@@ -201,7 +204,7 @@ npm run db:reset # Reset database (drop all tables)
|
|||||||
|
|
||||||
- **Home (`/`)**: Landing page with setup instructions and features overview
|
- **Home (`/`)**: Landing page with setup instructions and features overview
|
||||||
- **Dashboard (`/dashboard`)**: Protected user dashboard with profile information
|
- **Dashboard (`/dashboard`)**: Protected user dashboard with profile information
|
||||||
- **Chat (`/chat`)**: AI-powered chat interface using OpenAI (requires authentication)
|
- **Chat (`/chat`)**: AI-powered chat interface using OpenRouter (requires authentication)
|
||||||
|
|
||||||
## 🚀 Deployment
|
## 🚀 Deployment
|
||||||
|
|
||||||
@@ -230,8 +233,8 @@ Ensure these are set in your production environment:
|
|||||||
- `BETTER_AUTH_SECRET` - Secure random 32+ character string
|
- `BETTER_AUTH_SECRET` - Secure random 32+ character string
|
||||||
- `GOOGLE_CLIENT_ID` - Google OAuth Client ID
|
- `GOOGLE_CLIENT_ID` - Google OAuth Client ID
|
||||||
- `GOOGLE_CLIENT_SECRET` - Google OAuth Client Secret
|
- `GOOGLE_CLIENT_SECRET` - Google OAuth Client Secret
|
||||||
- `OPENAI_API_KEY` - OpenAI API key (optional)
|
- `OPENROUTER_API_KEY` - OpenRouter API key (optional, for AI chat functionality)
|
||||||
- `OPENAI_MODEL` - OpenAI model name (optional, defaults to gpt-5-mini)
|
- `OPENROUTER_MODEL` - Model name from OpenRouter (optional, defaults to openai/gpt-5-mini)
|
||||||
- `NEXT_PUBLIC_APP_URL` - Your production domain
|
- `NEXT_PUBLIC_APP_URL` - Your production domain
|
||||||
|
|
||||||
## 🎥 Tutorial Video
|
## 🎥 Tutorial Video
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ BETTER_AUTH_SECRET=qtD4Ssa0t5jY7ewALgai97sKhAtn7Ysc
|
|||||||
GOOGLE_CLIENT_ID=
|
GOOGLE_CLIENT_ID=
|
||||||
GOOGLE_CLIENT_SECRET=
|
GOOGLE_CLIENT_SECRET=
|
||||||
|
|
||||||
# AI Integration (Optional - for chat functionality)
|
# AI Integration via OpenRouter (Optional - for chat functionality)
|
||||||
OPENAI_API_KEY=
|
# Get your API key from: https://openrouter.ai/settings/keys
|
||||||
OPENAI_MODEL="gpt-5-mini"
|
# View available models at: https://openrouter.ai/models
|
||||||
|
OPENROUTER_API_KEY=
|
||||||
|
OPENROUTER_MODEL="openai/gpt-5-mini"
|
||||||
|
|
||||||
# Optional - for vector search only
|
# Optional - for vector search only
|
||||||
OPENAI_EMBEDDING_MODEL="text-embedding-3-large"
|
OPENAI_EMBEDDING_MODEL="text-embedding-3-large"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "agentic-coding-starter-kit",
|
"name": "agentic-coding-starter-kit",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev --turbopack",
|
"dev": "next dev --turbopack",
|
||||||
"build": "pnpm run db:migrate && next build",
|
"build": "pnpm run db:migrate && next build",
|
||||||
@@ -15,14 +15,15 @@
|
|||||||
"db:reset": "drizzle-kit drop && drizzle-kit push"
|
"db:reset": "drizzle-kit drop && drizzle-kit push"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/openai": "^2.0.53",
|
"@ai-sdk/openai": "^2.0.60",
|
||||||
"@ai-sdk/react": "^2.0.78",
|
"@ai-sdk/react": "^2.0.86",
|
||||||
|
"@openrouter/ai-sdk-provider": "^1.2.0",
|
||||||
"@radix-ui/react-avatar": "^1.1.10",
|
"@radix-ui/react-avatar": "^1.1.10",
|
||||||
"@radix-ui/react-dialog": "^1.1.15",
|
"@radix-ui/react-dialog": "^1.1.15",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
"ai": "^5.0.78",
|
"ai": "^5.0.86",
|
||||||
"better-auth": "^1.3.29",
|
"better-auth": "^1.3.34",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"drizzle-orm": "^0.44.7",
|
"drizzle-orm": "^0.44.7",
|
||||||
@@ -40,12 +41,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@tailwindcss/postcss": "^4.1.16",
|
"@tailwindcss/postcss": "^4.1.16",
|
||||||
"@types/node": "^20.19.23",
|
"@types/node": "^20.19.24",
|
||||||
"@types/pg": "^8.15.5",
|
"@types/pg": "^8.15.6",
|
||||||
"@types/react": "^19.2.2",
|
"@types/react": "^19.2.2",
|
||||||
"@types/react-dom": "^19.2.2",
|
"@types/react-dom": "^19.2.2",
|
||||||
"drizzle-kit": "^0.31.5",
|
"drizzle-kit": "^0.31.6",
|
||||||
"eslint": "^9.38.0",
|
"eslint": "^9.39.0",
|
||||||
"eslint-config-next": "15.4.6",
|
"eslint-config-next": "15.4.6",
|
||||||
"shadcn": "^3.5.0",
|
"shadcn": "^3.5.0",
|
||||||
"tailwindcss": "^4.1.16",
|
"tailwindcss": "^4.1.16",
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { openai } from "@ai-sdk/openai";
|
import { openrouter } from "@openrouter/ai-sdk-provider";
|
||||||
import { streamText, UIMessage, convertToModelMessages } from "ai";
|
import { streamText, UIMessage, convertToModelMessages } from "ai";
|
||||||
|
|
||||||
export async function POST(req: Request) {
|
export async function POST(req: Request) {
|
||||||
const { messages }: { messages: UIMessage[] } = await req.json();
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
||||||
|
|
||||||
const result = streamText({
|
const result = streamText({
|
||||||
model: openai(process.env.OPENAI_MODEL || "gpt-5-mini"),
|
model: openrouter(process.env.OPENROUTER_MODEL || "openai/gpt-5-mini"),
|
||||||
messages: convertToModelMessages(messages),
|
messages: convertToModelMessages(messages),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ BETTER_AUTH_SECRET=qtD4Ssa0t5jY7ewALgai97sKhAtn7Ysc
|
|||||||
GOOGLE_CLIENT_ID=
|
GOOGLE_CLIENT_ID=
|
||||||
GOOGLE_CLIENT_SECRET=
|
GOOGLE_CLIENT_SECRET=
|
||||||
|
|
||||||
# AI Integration (Optional - for chat functionality)
|
# AI Integration via OpenRouter (Optional - for chat functionality)
|
||||||
OPENAI_API_KEY=
|
# Get your API key from: https://openrouter.ai/settings/keys
|
||||||
OPENAI_MODEL="gpt-5-mini"
|
# View available models at: https://openrouter.ai/models
|
||||||
|
OPENROUTER_API_KEY=
|
||||||
|
OPENROUTER_MODEL="openai/gpt-5-mini"
|
||||||
|
|
||||||
# Optional - for vector search only
|
# Optional - for vector search only
|
||||||
OPENAI_EMBEDDING_MODEL="text-embedding-3-large"
|
OPENAI_EMBEDDING_MODEL="text-embedding-3-large"
|
||||||
|
|||||||
19
package.json
19
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "agentic-coding-starter-kit",
|
"name": "agentic-coding-starter-kit",
|
||||||
"version": "0.1.0",
|
"version": "0.1.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev --turbopack",
|
"dev": "next dev --turbopack",
|
||||||
@@ -17,14 +17,15 @@
|
|||||||
"sync-template": "node create-agentic-app/scripts/sync-templates.js"
|
"sync-template": "node create-agentic-app/scripts/sync-templates.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ai-sdk/openai": "^2.0.53",
|
"@ai-sdk/openai": "^2.0.60",
|
||||||
"@ai-sdk/react": "^2.0.78",
|
"@ai-sdk/react": "^2.0.86",
|
||||||
|
"@openrouter/ai-sdk-provider": "^1.2.0",
|
||||||
"@radix-ui/react-avatar": "^1.1.10",
|
"@radix-ui/react-avatar": "^1.1.10",
|
||||||
"@radix-ui/react-dialog": "^1.1.15",
|
"@radix-ui/react-dialog": "^1.1.15",
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
"ai": "^5.0.78",
|
"ai": "^5.0.86",
|
||||||
"better-auth": "^1.3.29",
|
"better-auth": "^1.3.34",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"drizzle-orm": "^0.44.7",
|
"drizzle-orm": "^0.44.7",
|
||||||
@@ -42,12 +43,12 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/eslintrc": "^3.3.1",
|
"@eslint/eslintrc": "^3.3.1",
|
||||||
"@tailwindcss/postcss": "^4.1.16",
|
"@tailwindcss/postcss": "^4.1.16",
|
||||||
"@types/node": "^20.19.23",
|
"@types/node": "^20.19.24",
|
||||||
"@types/pg": "^8.15.5",
|
"@types/pg": "^8.15.6",
|
||||||
"@types/react": "^19.2.2",
|
"@types/react": "^19.2.2",
|
||||||
"@types/react-dom": "^19.2.2",
|
"@types/react-dom": "^19.2.2",
|
||||||
"drizzle-kit": "^0.31.5",
|
"drizzle-kit": "^0.31.6",
|
||||||
"eslint": "^9.38.0",
|
"eslint": "^9.39.0",
|
||||||
"eslint-config-next": "15.4.6",
|
"eslint-config-next": "15.4.6",
|
||||||
"shadcn": "^3.5.0",
|
"shadcn": "^3.5.0",
|
||||||
"tailwindcss": "^4.1.16",
|
"tailwindcss": "^4.1.16",
|
||||||
|
|||||||
643
pnpm-lock.yaml
generated
643
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,11 @@
|
|||||||
import { openai } from "@ai-sdk/openai";
|
import { openrouter } from "@openrouter/ai-sdk-provider";
|
||||||
import { streamText, UIMessage, convertToModelMessages } from "ai";
|
import { streamText, UIMessage, convertToModelMessages } from "ai";
|
||||||
|
|
||||||
export async function POST(req: Request) {
|
export async function POST(req: Request) {
|
||||||
const { messages }: { messages: UIMessage[] } = await req.json();
|
const { messages }: { messages: UIMessage[] } = await req.json();
|
||||||
|
|
||||||
const result = streamText({
|
const result = streamText({
|
||||||
model: openai(process.env.OPENAI_MODEL || "gpt-5-mini"),
|
model: openrouter(process.env.OPENROUTER_MODEL || "openai/gpt-5-mini"),
|
||||||
messages: convertToModelMessages(messages),
|
messages: convertToModelMessages(messages),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user