Run the development server
mainUse Turborepo to start both the API and the Web frontend simultaneously in development mode.
- API: Running at
http://localhost:3004 - Web: Running at
http://localhost:3000
turbo devrepository·main·Indexed 21 days ago
https://github.com/sullyo/webapp-starterA modern full-stack SaaS template built with Turborepo, featuring a Hono and Bun API backend and a Next.js frontend. It integrates Supabase for database management via Drizzle ORM and Clerk for authentication and webhooks. The template includes a streaming chat interface using the Vercel AI SDK v2, a post management system, and end-to-end type safety via Hono RPC.
Use Turborepo to start both the API and the Web frontend simultaneously in development mode.
http://localhost:3004http://localhost:3000turbo devTo sync user data (like user.created, user.updated, and user.deleted) from Clerk to your local API, you must expose your local server to the internet using ngrok and configure a webhook endpoint in the Clerk Dashboard.
ngrok and obtain a forwarding URL (e.g., https://your-url.ngrok-free.app).https://your-url.ngrok-free.app/api/webhooks. Select the desired events.DATABASE_URL="your_database_url"
CLERK_WEBHOOK_SECRET="your_signing_secret"pnpm clerk:listenTo set up the project locally, follow these steps:
pnpm to install all workspace dependencies..env files in apps/api, apps/web, and packages/db as specified in the environment setup guide.pnpm install
# Install Bun (macOS/Linux/WSL)
curl -fsSL https://bun.sh/install | bash
# Install Bun (via npm)
npm install -g bun
# Install Bun (via Homebrew)
brew install oven-sh/bun/bunTo deploy the Bun API backend to Render:
render.yaml file, configure the following manually:apps/apipnpm installpnpm startapps/api/.env in the Render dashboard.The recommended way to deploy this Next.js application is via the Vercel Platform. You can follow the official Next.js deployment documentation for detailed steps on connecting your repository and configuring your project for production.
https://nextjs.org/docs/app/building-your-application/deployingThe project requires specific environment variables in three different locations to function correctly.
apps/api/.env)Required for database connection and Clerk authentication/webhooks.
DATABASE_URLCLERK_SECRET_KEYNEXT_PUBLIC_CLERK_PUBLISHABLE_KEYCLERK_SIGNING_SECRETapps/web/.env)Required for Clerk authentication and connecting to the API.
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYCLERK_SECRET_KEYNEXT_PUBLIC_API_URLpackages/db/.env)Required for running migrations and pushing schema changes.
DATABASE_URL# apps/api/.env
DATABASE_URL=your_database_url
CLERK_SECRET_KEY=your_clerk_secret_key
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
CLERK_SIGNING_SECRET=your_clerk_webhook_secret
# apps/web/.env
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key
CLERK_SECRET_KEY=your_clerk_secret_key
NEXT_PUBLIC_API_URL=your_api_url
# packages/db/.env
DATABASE_URL=your_database_urlTo start the Next.js development server, use your preferred package manager to run the dev script. Once running, the application will be available at http://localhost:3000. You can modify app/page.tsx to see real-time updates via Fast Refresh.
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devClerk is used for user authentication. To enable full functionality:
.env files.When setting up webhooks in the Clerk Dashboard, the endpoint URL must follow this pattern to reach the API service:
https://<your-ngrok-url>/api/webhooks (for local development)
https://<your-production-url>/api/webhooks (for production)
To deploy the Next.js frontend:
apps/web directory.apps/web/.env in the Vercel dashboard.The project uses Drizzle ORM and supports any PostgreSQL database (Supabase is recommended).
pnpm db:push to push your current schema to the database for local testing.pnpm db:generate to generate the schema files.pnpm db:migrate to apply the generated schema to the database.pnpm db:push
pnpm db:generate
pnpm db:migrateThe chats.api.ts module provides a set of TanStack React Query hooks for interacting with the chat API. These hooks handle data fetching, mutations, and automatic cache invalidation to keep the UI in sync with the backend.
useGetChats(): Fetches a list of all chats. Uses query key ['chats'].useGetChat(params: GetChatParams): Fetches a specific chat by ID. Uses query key ['chat', { id: params.param.id }]. Only runs if params.param.id is present.useGetChatMessages(params: GetChatMessagesParams & { disable?: boolean }): Fetches messages for a specific chat. Uses query key ['chat-messages', { chatId: params.param.id }]. Only runs if params.param.id is present and disable is not true.useGetChatMessage(params: GetChatMessageParams): Fetches a specific message. Uses query key ['chat-message', { chatId: params.param.chatId, messageId: params.param.messageId }].useCreateChat(): Creates a new chat. Invalidates ['chats'] on success.useUpdateChat(id: string): Updates an existing chat. Invalidates ['chats'] and ['chat', { id }] on success.useDeleteChat(id: string): Deletes a chat. Invalidates ['chats'] on success.useCreateChatMessage(chatId: string): Sends a new message in a chat. Invalidates ['chat-messages', { chatId }] on success.useUpdateChatMessage(chatId: string, messageId: string): Updates a message. Invalidates ['chat-messages', { chatId }] and ['chat-message', { chatId, messageId }] on success.useDeleteChatMessage(chatId: string, messageId: string): Deletes a message. Invalidates ['chat-messages', { chatId }] on success.import { useGetChats, useCreateChat } from '@/api/chats.api';
// Example: Fetching chats
const { data: chats, isLoading } = useGetChats();
// Example: Creating a chat
const createChatMutation = useCreateChat();
const handleCreate = (params: CreateChatParams) => {
createChatMutation.mutate(params);
};