A modern, production-ready starter template for building full-stack web applications with Next.js, React, Supabase authentication, HeroUI components, Tailwind CSS, and TypeScript.
- Next.js 16 - React framework with App Router
- React 19 - UI library
- TypeScript - Type safety
- Supabase - Authentication & backend
- HeroUI - Beautiful React component library
- Tailwind CSS v4 - Utility-first CSS framework
- 🔐 Authentication - Supabase OAuth (Google) with protected routes
- 🎨 Modern UI - HeroUI components with Tailwind CSS styling
- 📱 Responsive Design - Mobile-first, fully responsive layouts
- 🛡️ Type Safety - Full TypeScript support throughout
- 🔒 Route Protection - Route groups and middleware-based authentication guards
- 👤 User Profile - Profile management with email verification status
- 🎯 App Router - Next.js 16 App Router with server components
- 🌙 Theme Toggle - Light and dark theme support with persistent user preference
- 📦 Monorepo Ready - Structured for monorepo architecture
- 🚀 Demo Mode - Works without Supabase configuration for easy exploration
- Node.js 18+ and npm/yarn/pnpm
- A Supabase project (create one here)
git clone https://github.com/element-software/next-tailwind-react-supabase-heroui
cd next-tailwind-react-supabase-herouinpm install
# or
yarn install
# or
pnpm installCreate a .env.local file in the root directory:
# Authentication (optional - app works without Supabase in demo mode)
# Set NEXT_PUBLIC_ENABLE_AUTH=false to disable authentication
NEXT_PUBLIC_ENABLE_AUTH=true
# Supabase Configuration (required only if authentication is enabled)
NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_DEFAULT_KEY=your_supabase_anon_key
SUPABASE_SECRET_KEY=your_supabase_service_role_key
# Google OAuth (required only if authentication is enabled)
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
# Google Analytics (optional)
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=your_google_analytics_idNote: This template can run without Supabase credentials! If you don't configure Supabase, the app will run in demo mode where authentication is disabled and all routes are accessible. This is perfect for exploring the template before setting up your backend.
If you want to enable authentication:
- Create a Supabase project at supabase.com
- Go to your Supabase project dashboard
- Navigate to Authentication > Providers
- Enable Google provider and add your OAuth credentials
- Add your callback URL:
http://localhost:3000/auth/callback(for development) - Copy your Supabase URL and keys to
.env.local
Demo Mode: If you skip Supabase setup, the app will run in demo mode where:
- All routes are accessible without authentication
- Login page shows a configuration message
- Profile page displays demo data
- Perfect for exploring the template structure
npm run dev
# or
yarn dev
# or
pnpm devOpen http://localhost:3000 in your browser.
├── app/ # Next.js App Router
│ ├── (authenticated)/ # Authenticated route group (requires auth)
│ │ ├── api/ # Protected API routes
│ │ │ └── auth/ # Auth-related API endpoints
│ │ │ └── route.ts # GET /api/auth - Get current user
│ │ ├── auth/ # Authenticated user pages
│ │ │ └── profile/ # User profile page
│ │ ├── protected/ # Protected pages (example)
│ │ ├── layout.tsx # Authenticated layout wrapper
│ │ └── template.tsx # Authenticated template
│ ├── (public)/ # Public route group (no auth required)
│ │ ├── api/ # Public API routes
│ │ │ └── healthcheck/ # Health check endpoint
│ │ │ └── route.ts # GET /api/healthcheck
│ │ ├── about/ # About page
│ │ └── layout.tsx # Public layout wrapper
│ ├── auth/ # Authentication routes
│ │ ├── login/ # Login page
│ │ ├── callback/ # OAuth callback handler
│ │ └── auth-code-error/ # Auth error page
│ ├── layout.tsx # Root layout
│ ├── page.tsx # Home page
│ ├── template.tsx # Root template (HeroUIProvider)
│ ├── globals.css # Global styles
│ └── hero.ts # HeroUI theme configuration
├── lib/ # Shared utilities and components
│ ├── components/ # Reusable components
│ │ ├── auth/ # Authentication components
│ │ │ └── LoginForm.tsx # Login form component
│ │ ├── pages/ # Page-specific components
│ │ │ └── home.tsx # Home page component
│ │ ├── shared/ # Shared UI components
│ │ │ ├── header.tsx # Header component
│ │ │ ├── footer.tsx # Footer component
│ │ │ ├── ThemeToggle.tsx # Theme toggle button
│ │ │ ├── ThemeScript.tsx # Theme initialization script
│ │ │ └── AnalyticsWrapper.tsx # Analytics wrapper
│ │ └── access/ # Access control components
│ │ └── AccessBlocked.tsx # Access denied component
│ └── supabase/ # Supabase client utilities
│ ├── config.ts # Supabase configuration checker
│ ├── client.ts # Client-side Supabase client
│ ├── server.ts # Server-side Supabase client
│ └── middleware.ts # Middleware utilities
├── middleware.ts # Next.js middleware for route protection
├── types/ # TypeScript type definitions
│ └── user.ts # User profile types
└── public/ # Static assets
-
(authenticated): Routes in this group require authentication. The layout automatically checks for a valid user session.- API Routes:
app/(authenticated)/api/*- Protected API endpoints that require authentication - Pages: All pages in this group are protected and require login
- API Routes:
-
(public): Routes in this group are publicly accessible without authentication.- API Routes:
app/(public)/api/*- Public API endpoints (e.g., health checks) - Pages: Public pages like about, landing pages, etc.
- API Routes:
-
auth: Authentication-related routes (login, callback, error pages)
npm run dev- Start development servernpm run build- Build for productionnpm run start- Start production servernpm run lint- Run ESLintnpm run check-types- Type check with TypeScript
When Supabase is configured (NEXT_PUBLIC_ENABLE_AUTH=true and credentials are set):
- User clicks "Login" and is redirected to Google OAuth
- After authentication, user is redirected to
/auth/callback - Supabase exchanges the code for a session
- User is redirected to their intended destination or
/auth/setup - Middleware protects routes and redirects unauthenticated users to login
Demo Mode: When Supabase is not configured, authentication is disabled and all routes are accessible. The login page will show a message indicating that authentication needs to be configured.
This template uses:
- Tailwind CSS v4 for utility-first styling
- HeroUI components for consistent UI elements
- Theme classes (
theme-text,theme-background, etc.) for theming - Theme toggle in the header to switch between light and dark modes
- Persistent theme - User's theme preference is saved in localStorage
Routes are protected via two mechanisms:
-
Route Groups:
- Routes in
app/(authenticated)/are automatically protected by the authenticated layout - Routes in
app/(public)/are publicly accessible
- Routes in
-
Middleware (
middleware.ts):- Protects specific paths defined in the middleware configuration
- Redirects unauthenticated users to
/auth/login - Works in conjunction with route groups for comprehensive protection
Protected API Routes:
app/(authenticated)/api/*- All API routes in this group require authentication- Example:
/api/auth- Returns current authenticated user
Public API Routes:
app/(public)/api/*- Public API endpoints accessible without authentication- Example:
/api/healthcheck- Health check endpoint
The template uses Next.js Server Components by default. Client components are marked with "use client" directive.
TypeScript types are defined in the types/ directory. User profile types are in types/user.ts.
- Push your code to GitHub
- Import your repository on Vercel
- Add your environment variables
- Deploy!
The app can be deployed to any platform that supports Next.js:
- Netlify
- AWS Amplify
- Railway
- Render
Make sure to set all required environment variables in your deployment platform.
- Next.js Documentation
- Supabase Documentation
- HeroUI Documentation
- Tailwind CSS Documentation
- TypeScript Documentation
This is a starter template. Feel free to use it for your projects.
Contributions, issues, and feature requests are welcome!
Built with ❤️ using Next.js, React, Supabase, HeroUI, and Tailwind CSS.