UNPKG

logicloom-nextjs-starter

Version:

A production-ready Next.js starter template with authentication, i18n, dark mode, and modern patterns

716 lines (554 loc) 20.2 kB
# Logicloom Starter A production-ready Next.js starter template with authentication, i18n (multi-language), dark mode, database, and modern patterns. ## ✨ Features - ✅ Next.js 16 with App Router - ✅ TypeScript - ✅ Tailwind CSS v4 - ✅ Shadcn/ui Components -**SQLite Database** (better-sqlite3) -**Cookie-based Authentication** (HTTP-only cookies) -**Password Hashing** (bcryptjs) - Configurable salt rounds -**Multi-language Support** (i18n) - English, German, Spanish -**Dark Mode / Light Mode** -**Protected Routes Middleware** - Automatic auth checking -**User Dashboard** - Dropdown menu with navigation - ✅ Axios for HTTP requests with credentials - ✅ TanStack Query for data fetching - ✅ Zod validation (client & server) - ✅ Custom hooks - ✅ Session management with refresh tokens -**Toast Notifications** (Sonner) - Color-coded error/success/warning -**Smart Error Handling** - No duplicate error messages -**Auto Redirect** - After login/register - ✅ Responsive design - ✅ SEO ready ## 🚀 Quick Start ### Using npx (Recommended) ```bash # Create a new project npx logicloom-nextjs-starter my-app # Navigate to project cd my-app # Install dependencies npm install # Run development server npm run dev # Visit http://localhost:3000 ``` ### Manual Installation ```bash # Clone the repository git clone https://github.com/logicloom-app/logicloom-starter.git my-app cd my-app # Install dependencies npm install # Run development server npm run dev # Visit http://localhost:3000 ``` That's it! The SQLite database will be created automatically on first run. ## Project Structure ``` nextjs-starter/ ├── src/ │ ├── app/ │ │ ├── (user)/ # User routes group │ │ │ ├── [...not_found]/ # Catch-all 404 route │ │ │ │ └── page.tsx │ │ │ ├── about/ # About page │ │ │ │ └── page.tsx │ │ │ ├── auth/ # Authentication page │ │ │ │ └── page.tsx │ │ │ ├── contact/ # Contact page │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx # User layout │ │ │ └── not-found.tsx # 404 component │ │ ├── api/ │ │ │ └── auth/ # Auth API routes │ │ │ ├── login/ # POST /api/auth/login │ │ │ │ └── route.ts │ │ │ ├── logout/ # POST /api/auth/logout │ │ │ │ └── route.ts │ │ │ ├── me/ # GET /api/auth/me │ │ │ │ └── route.ts │ │ │ ├── refresh/ # POST /api/auth/refresh │ │ │ │ └── route.ts │ │ │ └── register/ # POST /api/auth/register │ │ │ └── route.ts │ │ ├── favicon.ico │ │ ├── globals.css # Global styles + Sonner styles │ │ ├── layout.tsx # Root layout │ │ └── page.tsx # Home page │ ├── components/ │ │ ├── auth/ │ │ │ └── auth-form.tsx # Login/Register form with validation │ │ ├── providers/ │ │ │ ├── query-provider.tsx # TanStack Query provider │ │ │ └── theme-provider.tsx # Next-themes provider │ │ ├── ui/ # Shadcn components │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── dropdown-menu.tsx │ │ │ ├── input.tsx │ │ │ ├── label.tsx │ │ │ ├── sheet.tsx │ │ │ └── sonner.tsx # Toast configuration │ │ ├── footer.tsx # Footer component │ │ ├── language-switcher.tsx │ │ └── navbar.tsx # Navbar with user dropdown │ ├── contexts/ │ │ └── language-context.tsx # i18n context │ ├── hooks/ │ │ └── use-auth.ts # Auth hooks (login/register/logout/user) │ ├── lib/ │ │ ├── api/ │ │ │ └── auth.ts # Auth API functions │ │ ├── validations/ │ │ │ └── auth.ts # Zod schemas │ │ ├── axios.ts # Axios instance with interceptors │ │ ├── constants.ts # API endpoints & keys │ │ ├── db-helpers.ts # Database CRUD helpers │ │ ├── db.ts # SQLite database setup │ │ ├── error-handler.ts # Error handling utilities │ │ ├── storage.ts # Cookie storage helpers │ │ ├── toast-helpers.ts # Toast notification helpers │ │ └── utils.ts # Utility functions │ ├── middleware.ts # Route protection middleware │ └── types/ │ └── auth.ts # TypeScript types ├── bin/ │ └── create.js # NPX CLI tool ├── public/ # Static assets ├── database.sqlite # SQLite database (auto-created) ├── env.example # Environment variables template ├── ENV_SETUP.md # Environment setup guide ├── package.json ├── tsconfig.json ├── tailwind.config.ts ├── next.config.ts └── README.md ``` ## Database This template uses **better-sqlite3** - a fast, simple SQLite database that requires no setup! ### Why SQLite?**Zero configuration** - Just run and it works ✅ **Fast** - Better performance than PostgreSQL for small to medium apps ✅ **Embedded** - No separate database server needed ✅ **Perfect for Next.js** - Works great with serverless ✅ **Easy deployment** - Single file database ### Database Schema ```sql -- Users table CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT UNIQUE NOT NULL, password TEXT NOT NULL, -- bcrypt hashed created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- Sessions table CREATE TABLE sessions ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, token TEXT UNIQUE NOT NULL, expires_at DATETIME NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); ``` ### Database Helpers ```typescript import { userHelpers, sessionHelpers } from "@/lib/db-helpers"; // Create user const userId = userHelpers.create("John", "john@example.com", "password"); // Find user by email const user = userHelpers.findByEmail("john@example.com"); // Verify password const isValid = userHelpers.verifyPassword("password", user.password); // Create session const token = sessionHelpers.create(userId); // Find session const session = sessionHelpers.findByToken(token); ``` ## Authentication ### Cookie-Based Auth (HTTP-only) All tokens are stored in **HTTP-only cookies** for maximum security: ✅ **XSS Protection** - JavaScript cannot access auth tokens ✅ **CSRF Protection** - SameSite=Lax ✅ **Secure** - HTTPS-only in production ✅ **Auto-expiry** - 7 days default ✅ **Dual Cookie System** - Secure tokens + login state flag ✅ **Middleware Protection** - Auto-redirect on protected routes ### Authentication Flow ``` 1. User submits login/register form ↓ 2. Client: Zod validation ↓ 3. Client: Axios POST to API with credentials ↓ 4. Server: Zod validation ↓ 5. Server: Check/Create user in SQLite ↓ 6. Server: Create session token ↓ 7. Server: Set HTTP-only cookies (auth_token + user_logged_in flag) ↓ 8. Client: Cookies stored automatically ↓ 9. Client: Auto-redirect to home page ↓ 10. Future requests: Cookies sent automatically ↓ 11. Middleware: Protects routes & prevents auth page access when logged in ``` ### Protected Routes The middleware automatically: - ✅ Redirects logged-in users away from `/auth` page - ✅ Protects routes like `/dashboard`, `/profile`, `/settings` - ✅ Allows public routes for everyone ```typescript // src/middleware.ts export function middleware(request: NextRequest) { const authToken = request.cookies.get("auth_token"); const isAuthenticated = !!authToken?.value; // Redirect logic based on authentication state if (isAuthenticated && pathname === "/auth") { return NextResponse.redirect(new URL("/", request.url)); } // Add more protected routes as needed } ``` ### Using Authentication ```typescript import { useLogin, useRegister, useLogout, useUser } from "@/hooks/use-auth"; function MyComponent() { const { data: user, isLoading } = useUser(); // Get current user const loginMutation = useLogin(); const registerMutation = useRegister(); const logoutMutation = useLogout(); const handleLogin = async () => { await loginMutation.mutateAsync({ email: "user@example.com", password: "password123", }); // ✅ Token automatically stored in HTTP-only cookie // ✅ User automatically redirected to home page // ✅ Success toast notification shown }; const handleLogout = async () => { await logoutMutation.mutateAsync(); // ✅ Cookies cleared // ✅ User state reset }; if (isLoading) return <div>Loading...</div>; if (user) return <div>Welcome, {user.name}!</div>; return <button onClick={handleLogin}>Login</button>; } ``` ### Navbar with User Menu The navbar automatically shows: - **Not logged in**: Sign In button - **Logged in**: User dropdown with Dashboard link and Logout option ```typescript // Navbar automatically handles authentication state <Navbar /> // Shows user info + dropdown when authenticated // Shows Sign In button when not authenticated ``` ## API Routes ### POST /api/auth/login ```json { "email": "user@example.com", "password": "password123" } ``` **Response:** ```json { "success": true, "message": "Login successful", "user": { "id": "1", "name": "John Doe", "email": "user@example.com" }, "token": "..." // Also set in HTTP-only cookie } ``` ### POST /api/auth/register ```json { "name": "John Doe", "email": "user@example.com", "password": "password123", "confirmPassword": "password123" } ``` ### POST /api/auth/logout No body required. Clears session and cookie. ### GET /api/auth/me Returns current user. Requires authentication cookie. ## 🛠️ Technologies - **Next.js 16** - React framework - **TypeScript** - Type safety - **Tailwind CSS v4** - Styling - **Shadcn/ui** - UI components - **better-sqlite3** - SQLite database - **bcryptjs** - Password hashing - **js-cookie** - Cookie management - **Axios** - HTTP client - **TanStack Query** - Data fetching - **Zod** - Validation - **Sonner** - Toast notifications - **next-themes** - Dark mode support - **lucide-react** - Icons ## Toast Notifications Toast notifications are **color-coded** for better UX: - 🔴 **Error**: Red background with white text - 🟢 **Success**: Green background with white text - 🟡 **Warning**: Yellow background with white text - 🔵 **Info**: Blue background with white text ### Basic Usage ```typescript import { toast } from "sonner"; // Success (Green) toast.success("Success!", { description: "Your action was completed successfully.", }); // Error (Red) - Single error, no duplicates! toast.error("Error!", { description: "Something went wrong.", }); // Warning (Yellow) toast.warning("Warning!", { description: "Please be careful.", }); // Info (Blue) toast.info("Info", { description: "Here's some information.", }); // Loading const loadingToast = toast.loading("Loading..."); // Later dismiss it toast.dismiss(loadingToast); // Promise toast.promise(fetch("/api/data"), { loading: "Loading...", success: "Data loaded!", error: "Failed to load data", }); ``` ### Smart Error Handling The authentication system prevents duplicate error messages: - ✅ Only **one** toast notification per error - ✅ User-friendly messages (no technical HTTP codes) - ✅ Automatic handling by React Query mutations ### Using Toast Helpers ```typescript import { toastHelpers } from "@/lib/toast-helpers"; // Simple success toastHelpers.success("Operation successful!"); // With description toastHelpers.error("Failed to save", "Please try again later."); // Promise with auto-handling toastHelpers.promise(apiCall(), { loading: "Saving...", success: "Saved successfully!", error: "Failed to save", }); ``` ## Development ### Adding New Tables Edit `src/lib/db.ts`: ```typescript db.exec(` CREATE TABLE IF NOT EXISTS posts ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, title TEXT NOT NULL, content TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (user_id) REFERENCES users(id) ); `); ``` ### Adding API Endpoints ```typescript // src/app/api/posts/route.ts import { NextRequest, NextResponse } from "next/server"; import db from "@/lib/db"; export async function GET(request: NextRequest) { const posts = db.prepare("SELECT * FROM posts").all(); return NextResponse.json({ posts }); } ``` ### Adding Validation ```typescript // src/lib/validations/post.ts import { z } from "zod"; export const createPostSchema = z.object({ title: z.string().min(3), content: z.string().min(10), }); ``` ## Deployment ### Vercel (Recommended) ```bash vercel ``` **Important**: SQLite works on Vercel but data is ephemeral. For production, consider: - Vercel Postgres - PlanetScale - Supabase ### Railway ```bash railway up ``` SQLite persists on Railway with volume mounts. ### Docker ```bash docker build -t nextjs-app . docker run -p 3000:3000 -v $(pwd)/database.sqlite:/app/database.sqlite nextjs-app ``` ## Security Features**HTTP-only cookies** - XSS protection (tokens inaccessible to JavaScript) ✅ **Dual cookie system** - Secure tokens + safe login state flag ✅ **SameSite=Lax** - CSRF protection ✅ **bcrypt hashing** - Configurable salt rounds (default: 10) ✅ **Zod validation** - Client & server-side input sanitization ✅ **Session expiry** - Auto logout after 7 days ✅ **Prepared statements** - SQL injection protection ✅ **Middleware protection** - Route-level authentication checking ✅ **Secure cookies in production** - HTTPS-only when `NODE_ENV=production`**No token exposure** - Credentials sent via secure cookies only ✅ **Smart error handling** - No information leakage in error messages ## Database Backup ```bash # Backup cp database.sqlite database.backup.sqlite # Restore cp database.backup.sqlite database.sqlite ``` ## Environment Variables ### Development (Optional) Create `.env.local`: ```env # Application URL NEXT_PUBLIC_APP_URL=http://localhost:3000 # API URL (default: /api) NEXT_PUBLIC_API_URL=/api # Password hashing strength (10-12 recommended) BCRYPT_SALT_ROUNDS=10 # Node environment (auto-detected) NODE_ENV=development ``` ### Production (Required) Set these in your deployment platform: ```env # REQUIRED NODE_ENV=production NEXT_PUBLIC_APP_URL=https://yourdomain.com # OPTIONAL BCRYPT_SALT_ROUNDS=12 # Higher for better security ``` ### Environment Variables Guide For a complete guide with all available options, see `ENV_SETUP.md` or check the `env.example` file. **Available configurations:** - 🔐 Security (bcrypt, JWT secrets) - 📧 Email (SMTP, SendGrid, Resend) - 🔗 OAuth (Google, GitHub) - 💳 Payments (Stripe) - ☁️ Cloud Storage (AWS S3) - 📊 Analytics (Google Analytics) - 🐛 Monitoring (Sentry) ## FAQ ### Why SQLite? SQLite is perfect for: - MVPs and prototypes - Small to medium applications - Low-traffic sites - Development/testing - Serverless environments (with caveats) ### When to upgrade from SQLite? Consider PostgreSQL/MySQL when you need: - High concurrent writes - Multi-server deployment - Advanced features (full-text search, JSON queries) - > 100GB database size ### Can I use PostgreSQL instead? Yes! Install `pg` and update `src/lib/db.ts`: ```typescript import { Pool } from "pg"; const pool = new Pool({ connectionString: process.env.DATABASE_URL, }); export default pool; ``` ## 📦 Installation via npm This package can be installed and used via npx: ```bash npx logicloom-nextjs-starter my-project-name ``` This will create a new Next.js project with all the features pre-configured. ## 📝 What's Included - **Authentication**: Login, Register, Logout with secure cookie-based sessions - **Protected Routes**: Middleware that auto-protects authenticated routes - **User Dashboard**: Dropdown menu with user info and navigation - **Database**: SQLite setup with user and session management - **Internationalization**: Multi-language support (EN, DE, ES) - **Dark Mode**: Toggle between light and dark themes - **UI Components**: Pre-configured Shadcn/ui components - **Form Validation**: Client and server-side validation with Zod - **API Routes**: Pre-built auth endpoints with proper error handling - **Smart Error Handling**: Single toast notifications, no duplicates - **Auto Redirects**: Automatic navigation after login/register - **Toast Notifications**: Color-coded for error/success/warning/info - **Responsive Design**: Mobile-first responsive design - **Environment Config**: Comprehensive environment variables support ## 🎨 Pages Included -**Home page** with hero section and features -**About page** -**Contact page** with form -**Authentication page** with Login/Register toggle -**Dashboard** (protected route example) -**404 Not Found page** -**Navbar** with user dropdown menu -**Footer** with links ### Authentication Features - ✅ Login form with validation - ✅ Register form with password confirmation - ✅ Email validation (format checking) - ✅ Password strength requirements (min 8 chars) - ✅ Real-time field validation on blur - ✅ Show/hide password toggles - ✅ Duplicate email detection with user-friendly error - ✅ Auto-redirect after successful auth - ✅ Toast notifications for all actions - ✅ Loading states during submission - ✅ Form reset on mode toggle ## 🚀 Recent Updates ### v1.0.1 - ✅ Enhanced authentication with middleware protection - ✅ Fixed duplicate error messages - ✅ Added color-coded toast notifications - ✅ Improved user dropdown menu with dashboard link - ✅ Auto-redirect after login/register - ✅ Fixed Next.js 16 theme provider types - ✅ Added comprehensive environment variables support - ✅ Improved cookie-based authentication flow - ✅ Better error handling across the application ## 📄 License MIT --- Built with ❤️ using modern Next.js patterns **Star this repo if you find it helpful! ⭐** ## 🤝 Contributing Contributions are welcome! Please feel free to submit a Pull Request. ## 📞 Support - 🐛 [Report a bug](https://github.com/logicloom-app/logicloom-starter/issues) - 💡 [Request a feature](https://github.com/logicloom-app/logicloom-starter/issues) - 📖 [Read the docs](https://github.com/logicloom-app/logicloom-starter#readme)