next-supabase-starter Tailwind Templates

Next Supabase Starter

šŸš€ A Next.js 15 + Supabase + React Query starter template with Tailwind CSS, shadcn/ui, and built-in authentication & database integration.

Next.js 15 Starter with Supabase, React Query

A modern Next.js 15 starter template with Supabase authentication, React Query for data fetching, and built-in wrappers for queries and authentication. This starter is designed to accelerate development by providing preconfigured hooks, utilities, and best practices.

šŸš€ Features

  • Next.js 15 – The latest Next.js version for optimized performance.
  • Supabase Authentication – Built-in auth system with user session handling.
  • React Query – Efficient data fetching and caching.
  • ShadCN Components – Prebuilt UI components for faster development.
  • Tailwind CSS – Utility-first styling for rapid UI building.
  • Zod Validation – Schema-based form validation for better data handling.
  • Prebuilt Hooks – Hooks for fetching data and mutations in client components.
  • Query & Auth Wrappers – Easily manage authentication state and query handling.

šŸ“¦ Installation

Create a new project using the CLI (if available):

npx create-next-supabase-starter@latest my-project

Or manually clone the repository:

git clone https://github.com/your-username/your-repo.git my-project
cd my-project
pnpm install

šŸ›  Setup

1. Environment Variables

Create a .env.local file and add:

NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key

2. Run Development Server

pnpm dev

Your app should be running at http://localhost:3000.

šŸ“Œ Usage

šŸ— Authentication

The AuthContext ensures user authentication is managed across the app.

"use client";

const AuthContext = createContext<AuthContextType | undefined>(undefined);

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const { data: user, isLoading } = useQuery({
    queryKey: ["user"],
    queryFn: async () => {
      const { data } = await supabase.auth.getUser();
      return data?.user ?? null; // āœ… Ensures it's never undefined
    },
    staleTime: 0,
  });

  return (
    <AuthContext.Provider value={{ user: user ?? null, loading: isLoading }}>
      {children}
    </AuthContext.Provider>
  );
}

export function useAuth() {
  const context = useContext(AuthContext);
  if (!context) {
    throw new Error("useAuth must be used within an AuthProvider");
  }
  return context;
}

šŸ”„ Fetching Data

Use the useClientFetch hook for fetching data efficiently on client components:

import { useClientFetch } from "@/hooks/useClientFetch";

const Posts = () => {
  const { data, isLoading } = useClientFetch("posts", "posts");

  if (isLoading) return <p>Loading...</p>;

  return (
    <ul>
      {data?.map((post) => (
        <li key={post.id}>{post.name}</li>
      ))}
    </ul>
  );
};

Advanced Filtering Example

const FilteredUsers = () => {
  const { data, isLoading } = useClientFetch(
    "filtered-users", // key
    "users", // table name
    5000, // cache time
    (query) => query.eq("role", "admin") // Supabase query filter
  );

  if (isLoading) return <p>Loading...</p>;

  return (
    <ul>
      {data?.map((user) => (
        <li key={user.id}>
          {user.name} ({user.role})
        </li>
      ))}
    </ul>
  );
};

šŸ“® Mutations

Use the useClientMutate hook for inserting, updating, and deleting data on client components:

import { useClientMutate } from "@/hooks/useClientMutate";

const AddPost = () => {
  const mutation = useClientMutate("posts", "insert");

  const handleSubmit = async () => {
    mutation.mutate({ id: Date.now(), name: "New Post" });
  };

  return <button onClick={handleSubmit}>Add Post</button>;
};

Updating Data Example

const UpdatePost = () => {
  const mutation = useClientMutate("posts", "update");

  const handleUpdate = () => {
    mutation.mutate({ id: 1, name: "Updated Post" });
  };

  return <button onClick={handleUpdate}>Update User</button>;
};

Deleting Data Example

const DeleteUser = () => {
  const mutation = useClientMutate("users", "delete");

  const handleDelete = () => {
    mutation.mutate({ id: 1 });
  };

  return <button onClick={handleDelete}>Delete User</button>;
};

šŸ— Folder Structure

šŸ“¦ my-project
ā”œā”€ā”€ šŸ“‚ app                 # Next.js app directory
│   ā”œā”€ā”€ šŸ“‚ (auth)           # Authentication pages
│   │   ā”œā”€ā”€ šŸ“‚ auth         # Authentication utilities
│   │   │   ā”œā”€ā”€ šŸ“‚ confirm  # Confirmation route
│   │   │   │   └── route.ts
│   │   ā”œā”€ā”€ šŸ“‚ error        # Error handling
│   │   ā”œā”€ā”€ šŸ“‚ login        # Login page
│   │   ā”œā”€ā”€ šŸ“‚ register     # Register page
│   │   ā”œā”€ā”€ actions.ts      # Auth actions
│   │   └── layout.tsx      # Auth layout
│   ā”œā”€ā”€ šŸ“‚ (dashboard)      # Dashboard pages
│   ā”œā”€ā”€ favicon.ico         # Favicon
│   ā”œā”€ā”€ globals.css         # Global styles
│   ā”œā”€ā”€ layout.tsx          # Main layout
│   ā”œā”€ā”€ not-found.tsx       # 404 Page
│   └── page.tsx            # Home page
ā”œā”€ā”€ šŸ“‚ components          # Shared UI components
ā”œā”€ā”€ šŸ“‚ hooks               # Custom React Query hooks
ā”œ    └── use-client-fetch.ts
ā”œ    └── use-client-mutation.ts
ā”œā”€ā”€ šŸ“‚ lib                 # Utilities & helpers
ā”œā”€ā”€ šŸ“‚ public              # Static assets
ā”œā”€ā”€ šŸ“‚ supabase            # Supabase integrations clients
│   ā”œā”€ā”€ client.ts          # Supabase client
│   ā”œā”€ā”€ middleware.ts      # Middleware configuration
│   └── server.ts          # Server-side Supabase utilities
ā”œā”€ā”€ šŸ“‚ node_modules        # Dependencies
ā”œā”€ā”€ .env                   # Environment configuration
ā”œā”€ā”€ .env.example           # Example environment variables
ā”œā”€ā”€ .gitignore             # Git ignore file
ā”œā”€ā”€ components.json        # UI component configurations
ā”œā”€ā”€ eslint.config.mjs      # ESLint configuration
ā”œā”€ā”€ middleware.ts          # Global middleware
ā”œā”€ā”€ next-env.d.ts          # Next.js environment types
ā”œā”€ā”€ next.config.ts         # Next.js configuration
ā”œā”€ā”€ package.json           # Project dependencies
ā”œā”€ā”€ pnpm-lock.yaml         # Lock file
ā”œā”€ā”€ postcss.config.mjs     # PostCSS configuration
ā”œā”€ā”€ README.md              # Project documentation
ā”œā”€ā”€ tailwind.config.ts     # Tailwind CSS configuration
└── tsconfig.json          # TypeScript configuration

šŸ›  Technologies I Used

  • Next.js 15
  • Supabase
  • React Query
  • ShadCN Components
  • Tailwind CSS
  • Zod Validation
  • TypeScript

Top categories

Loading Svelte Themes