Full-Stack Next.js Starter with Supabase, TypeScript, TanStack Query – SupaNext

A full-stack Next.js starter template with Supabase integration, TypeScript configuration, unit tests, and CI/CD workflows already configured.

SupaNext Starter Kit is a Next.js starter template that combines Next.js 16 App Router with Supabase authentication and database.

It includes TanStack Query for client-side data fetching, Vitest and React Testing Library for unit tests, and MSW for request mocking during tests.

The starter also configures Tailwind CSS, shadcn/ui components, ESLint, Prettier, Husky git hooks, and lint-staged to enforce code quality standards before commits.

Features

โšก๏ธ Next.js App Router: Uses the latest Next.js version with App Router architecture for server and client rendering.

๐Ÿ’š Supabase with supabase-ssr: Integrates Supabase authentication and database with session handling that works in server components, client components, pages router, and middleware.

โ›‘ TypeScript: Provides static type checking across all components and utilities.

๐ŸŽจ Tailwind CSS: Uses utility-first CSS framework for rapid UI development.

๐Ÿ”Œ shadcn/ui Components: Includes accessible, customizable UI components that you copy directly into your project.

๐Ÿงช Vitest and React Testing Library: Sets up unit testing infrastructure for all application code.

๐ŸŽ›๏ธ MSW: Mocks network requests during tests without modifying application code.

๐Ÿช TanStack Query: Handles client-side data fetching, caching, and synchronization.

โšชโšซ Dark Mode: Switches between light and dark themes using next-themes.

๐Ÿ”‹ Additional Tools: Includes Next Bundle Analyzer, Vercel Analytics, and Vercel Geist Font.

Use Cases

  • SaaS Application Foundation: Build a multi-tenant SaaS product that requires user authentication, database operations, and real-time subscriptions through Supabase.
  • Content Management Dashboard: Create an admin panel that manages content, users, and permissions with server-side rendering and client-side interactivity.
  • E-commerce Platform: Develop a product catalog with authentication, shopping cart functionality, and order management backed by Supabase database.
  • Internal Business Tools: Build company dashboards, project management systems, or data visualization tools that need secure authentication and real-time updates.

How to Use It

1. Create a Supabase project through the Supabase dashboard at database.new. Note the project URL and anon key from the API settings page.

pnpm create next-app -e https://github.com/michaeltroya/supa-next-starter

2. Navigate into the newly created directory:

cd name-of-new-app

3. Rename the .env.local.example file to .env.local in your project root. Add your Supabase credentials to this file:

# Update these with your Supabase details from your project settings > API
# https://app.supabase.com/project/_/settings/api
NEXT_PUBLIC_SUPABASE_URL=your-project-url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key

4. Start the local development server. The application runs at http://localhost:3000. The supabase-ssr package automatically handles authentication state across all Next.js rendering contexts.

pnpm run dev

5. Import components and files using the @ prefix instead of relative paths:

import { Button } from '@/components/ui/Button'
import logo from '@/public/logo.png'

6. Create test files adjacent to your components with the .test.tsx extension. The template includes Vitest and React Testing Library:

import { render, screen } from '@testing-library/react'
import { describe, it, expect } from 'vitest'
import { YourComponent } from './YourComponent'
describe('YourComponent', () => {
  it('renders correctly', () => {
    render(<YourComponent />)
    expect(screen.getByText('Expected Text')).toBeInTheDocument()
  })
})

Run tests in watch mode:

pnpm test

Open the Vitest UI for interactive test debugging:

pnpm test:ui

7. Mocking API Requests in Tests. MSW v2 intercepts network requests during tests. Define handlers in your test setup:

import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
const server = setupServer(
  http.get('/api/data', () => {
    return HttpResponse.json({ data: 'mocked response' })
  })
)
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

The mocking layer runs only in test environments without affecting production code.

8. TanStack Query handles client-side data fetching and caching. Wrap your application with QueryClientProvider in the root layout:

'use client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useState } from 'react'
export function Providers({ children }: { children: React.ReactNode }) {
  const [queryClient] = useState(() => new QueryClient())
  return (
    <QueryClientProvider client={queryClient}>
      {children}
    </QueryClientProvider>
  )
}

Use hooks in client components to fetch data:

'use client'
import { useQuery } from '@tanstack/react-query'
export function DataComponent() {
  const { data, isLoading, error } = useQuery({
    queryKey: ['items'],
    queryFn: async () => {
      const response = await fetch('/api/items')
      return response.json()
    }
  })
  if (isLoading) return <div>Loading...</div>
  if (error) return <div>Error loading data</div>
  return <div>{JSON.stringify(data)}</div>
}

9. The template uses pnpm by default. To switch to npm or Yarn, delete the pnpm-lock.yaml file and install dependencies with your preferred manager:

rm pnpm-lock.yaml
npm install

Update the scripts in .github/workflows, .husky hooks, and package.json to use npm or yarn commands instead of pnpm.

Available Scripts

pnpm dev: Starts development server on http://localhost:3000 with hot reload enabled.

pnpm build: Creates an optimized production build with static optimization and code splitting.

pnpm start: Runs the production build after running pnpm build.

pnpm type-check: Validates TypeScript types without emitting files.

pnpm lint: Runs ESLint on all files in the src directory.

pnpm format-check: Checks if files match Prettier formatting rules without modifying them.

pnpm format: Formats all files according to Prettier configuration.

pnpm test: Runs Vitest in watch mode for continuous testing.

pnpm test:ci: Runs tests once in CI mode without watch functionality.

pnpm test:ui: Opens the Vitest UI interface for visual test debugging.

pnpm analyze: Builds the project and launches Next.js Bundle Analyzer to inspect bundle sizes.

Related Resources

  • Next.js: React framework for building full-stack web applications with server and client rendering.
  • Supabase: Open source Firebase alternative that provides authentication, database, storage, and real-time subscriptions.
  • TanStack Query: Data synchronization library for managing server state in React applications.
  • shadcn/ui: Collection of accessible, customizable React components built with Radix UI and Tailwind CSS.

FAQs

Q: Can I use this template with Supabase local development?
A: Yes. Follow the Supabase local development guide to run Supabase locally alongside your Next.js development server. You need Docker installed to run the local Supabase stack.

Q: How do I add authentication to a page?
A: Create a server component that checks the session using the Supabase client. The supabase-ssr package provides helpers for reading sessions in server components, route handlers, and middleware. Redirect users to the login page if no session exists.

Q: How do I deploy this to Vercel?
A: Connect your GitHub repository to Vercel through the Vercel dashboard. Add the same environment variables from your .env.local file to the Vercel project settings. Vercel automatically detects Next.js and uses the correct build settings.

Q: Can I remove features I don’t need?
A: Yes. Uninstall packages you don’t need and remove their configurations. For example, remove Vitest by deleting vitest.config.ts, uninstalling dependencies, and removing test scripts from package.json.

michaeltroya

michaeltroya

Leave a Reply

Your email address will not be published. Required fields are marked *