Skip to content

About

Boilerplate for a Next.js based platform with basic firebase auth methods, admin interface and example implementation of external data sources. API first.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

NextPortal - Customer/Partner Portal Boilerplate

A comprehensive Next.js boilerplate for building customer/partner portals with Firebase authentication, dynamic custom claims system, and admin management capabilities.

πŸš€ Features

  • Next.js 15 with App Router and TypeScript
  • Firebase Authentication with dynamic custom claims
  • Dynamic Custom Claims System - Easily configurable user attributes
  • Role-based Access Control (Admin, Customer, Partner)
  • Magic Link Authentication for existing users
  • Admin Interface for user management with dynamic forms
  • Shadcn/ui Components with Tailwind CSS
  • API-First Architecture with secure backend endpoints
  • ESLint & Prettier for code quality

πŸ“ Project Structure

src/
β”œβ”€β”€ app/                    # Next.js App Router pages
β”‚   β”œβ”€β”€ (auth)/            # Authentication pages
β”‚   β”‚   β”œβ”€β”€ login/         # Login page
β”‚   β”‚   └── verify-magic-link/ # Magic link verification
β”‚   β”œβ”€β”€ (protected)/       # Protected pages
β”‚   β”‚   β”œβ”€β”€ dashboard/     # User dashboard
β”‚   β”‚   └── admin/         # Admin interface
β”‚   β”‚       └── users/     # User management
β”‚   └── api/               # API routes
β”‚       β”œβ”€β”€ auth/          # Authentication endpoints
β”‚       └── admin/         # Admin API endpoints
β”œβ”€β”€ components/             # React components
β”‚   β”œβ”€β”€ ui/                # Shadcn/ui components
β”‚   β”œβ”€β”€ admin/             # Admin-specific components
β”‚   β”‚   β”œβ”€β”€ DynamicCustomClaimsFields.tsx
β”‚   β”‚   └── DynamicCustomClaimsTableCells.tsx
β”‚   └── user/              # User-specific components
β”‚       └── DynamicUserAccountInfo.tsx
β”œβ”€β”€ config/                # Application configuration
β”‚   └── appConfig.ts       # Dynamic custom claims configuration
β”œβ”€β”€ lib/                   # Utility libraries
β”‚   β”œβ”€β”€ firebase/          # Firebase configuration
β”‚   β”‚   β”œβ”€β”€ client.ts      # Firebase client SDK
β”‚   β”‚   └── admin.ts       # Firebase Admin SDK
β”‚   β”œβ”€β”€ auth.ts            # Authentication utilities
β”‚   β”œβ”€β”€ apiAuth.ts         # API authentication & authorization
β”‚   └── utils/             # Utility functions
β”‚       └── customClaims.ts # Custom claims helpers
β”œβ”€β”€ hooks/                 # Custom React hooks
β”‚   └── useAuth.ts         # Authentication context & hook
└── middleware.ts          # Next.js middleware for route protection

πŸ”§ Setup Instructions

1. Install Dependencies

npm install

2. Firebase Configuration

The Firebase configuration is already set up with the project credentials. For admin operations, you'll need to:

  1. Go to Firebase Console
  2. Navigate to Project Settings > Service Accounts
  3. Generate a new private key
  4. Update the .env.local file with the service account credentials:
FIREBASE_CLIENT_EMAIL=your-service-account-email
FIREBASE_PRIVATE_KEY="your-private-key-here"

3. Enable Firebase Authentication

  1. In Firebase Console, go to Authentication > Sign-in method
  2. Enable Email/Password provider
  3. Configure authorized domains if needed

4. Run Development Server

npm run dev

πŸŽ›οΈ Dynamic Custom Claims System

This boilerplate features a powerful dynamic custom claims system that allows you to easily add, modify, and manage user attributes without changing code throughout the application.

Adding New Custom Claims

To add a new custom claim, update two places in src/config/appConfig.ts:

1. Add the key to CUSTOM_CLAIMS_KEYS

export const CUSTOM_CLAIMS_KEYS = {
  ROLE: 'role',
  ORGANIZATION_ID: 'organizationId',
  EXTERNAL_ID: 'externalId',
  // Add your new claim here
  DEPARTMENT: 'department',
} as const;

2. Add the configuration to CUSTOM_CLAIMS_CONFIG

export const CUSTOM_CLAIMS_CONFIG: CustomClaimFieldConfig[] = [
  // ... existing configurations ...
  {
    key: CUSTOM_CLAIMS_KEYS.DEPARTMENT,
    label: 'Department',
    type: 'select',
    required: false,
    options: [
      { value: '', label: 'No Department' },
      { value: 'engineering', label: 'Engineering' },
      { value: 'marketing', label: 'Marketing' },
      { value: 'sales', label: 'Sales' }
    ],
    description: 'User department'
  }
];

Supported Field Types

  • text - Text input field
  • email - Email input with validation
  • number - Number input field
  • select - Dropdown with predefined options

Automatic Integration

Once configured, the new custom claim will automatically appear in:

  • βœ… Admin user management forms
  • βœ… User account displays
  • βœ… API validation
  • βœ… Firebase custom claims storage
  • βœ… Authentication context

Current Functionality

  1. Root Route (/): Automatically redirects to /dashboard if authenticated, or /login if not
  2. Login Page (/login): Functional login form with email/password
  3. Dashboard (/dashboard): Protected dashboard showing user info and dynamic custom claims
  4. Admin Users (/admin/users): Complete user management with dynamic forms
  5. Magic Link Verification (/verify-magic-link): Handles custom token authentication

Authentication Context

  • Global State Management: useAuth() hook provides user state across the app
  • Automatic Redirects: Pages automatically redirect based on authentication state
  • Loading States: Proper loading indicators during authentication checks
  • Error Handling: Comprehensive error handling for auth operations
  • Dynamic Claims: Real-time custom claims management

Testing Magic Links

  1. Use the admin interface at /admin/users to generate magic links
  2. Or use the API endpoint: POST /api/auth/generate-magic-link
  3. Requires admin authentication and either email or uid in request body
  4. Returns a magic link URL that can be used for authentication

API Endpoints

  • POST /api/auth/login - Login validation endpoint
  • POST /api/auth/logout - Logout processing endpoint
  • POST /api/auth/generate-magic-link - Magic link generation (admin only)
  • GET /api/admin/users - List all users (admin only)
  • POST /api/admin/users - Create new user (admin only)
  • PUT /api/admin/users/[userId] - Update user (admin only)

πŸ›  Available Scripts

  • npm run dev - Start development server
  • npm run build - Build for production
  • npm run start - Start production server
  • npm run lint - Run ESLint
  • npm run lint:fix - Fix ESLint issues

πŸ” Authentication Flow

  1. Automatic Routing: Root route redirects based on authentication state
  2. Context Management: Global authentication state via React Context
  3. Username/Password Login: Standard Firebase authentication via client SDK
  4. Magic Links: Admin-generated custom tokens for existing users
  5. Dynamic Custom Claims: Flexible user attribute system
  6. API Authorization: Bearer token verification with role-based protection
  7. Route Protection: Middleware and client-side guards for protected routes

πŸ”’ Security Features

  • Firebase ID Token Verification: All API routes verify Firebase tokens
  • Role-Based Access Control: Admin, Customer, Partner roles with proper checks
  • Organization Isolation: Users can only access their organization's data
  • Protected API Routes: withAuth wrapper for easy API protection
  • Client-Side Route Guards: Automatic redirects for unauthorized access
  • Dynamic Validation: Custom claims validation based on configuration

πŸ“š Key Technologies

  • Next.js 15 - React framework with App Router
  • TypeScript - Type safety and better DX
  • Firebase - Authentication and backend services
  • Tailwind CSS - Utility-first CSS framework
  • Shadcn/ui - Modern UI component library
  • ESLint & Prettier - Code quality and formatting

🀝 Contributing

This is a boilerplate project. Follow the existing patterns and conventions when adding new features. The dynamic custom claims system makes it easy to extend user attributes without modifying core components.

πŸ“„ License

MIT License - feel free to use this boilerplate for your projects.

πŸš€ Deployment & CI/CD

This boiler-plate ships with an opinionated yet fully automated Google Cloud Build + Cloud Run pipeline. The build recipe lives in cloudbuild.yaml and the helper script scripts/deploy.sh is just a convenience wrapper around gcloud builds submit.

One-click deploy for this repo

  1. Create / select a GCP project (e.g. customer-portals-446012).
  2. Enable APIs: Cloud Build, Cloud Run, Artifact Registry, Secret Manager.
  3. Create secrets in Secret Manager – they must keep the names below (version latest is used automatically):
    • FIREBASE_SERVICE_ACCOUNT_JSON
    • JWT_SECRET
    • HUBSPOT_API_KEY (exposed to the build as HUBSPOT_ACCESS_TOKEN)
    • NEXT_PUBLIC_FIREBASE_API_KEY
    • NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN
    • NEXT_PUBLIC_FIREBASE_PROJECT_ID
    • NEXT_PUBLIC_FIREBASE_APP_ID
  4. Grant IAM to the Cloud Build service account PROJECT_NUMBER@cloudbuild.gserviceaccount.com:
    • roles/secretmanager.secretAccessor
    • roles/run.admin
  5. Run
    ./scripts/deploy.sh         # builds, pushes and deploys to Cloud Run (region europe-west10)

Continuous Deployment from GitHub

  1. In Cloud Console β†’ Cloud Build β†’ Triggers β†’ Manage repositories β†’ Connect repository
    • Authorise the Google Cloud Build GitHub app if prompted.
    • Pick montamo/next-firebase-boilerplate (or your fork).
  2. Create Trigger
    • Repository: the repo you just connected.
    • Event: "Push to a branch" (e.g. ^main$).
    • Build config file: cloudbuild.yaml (leave the substitutions field empty – defaults are hard-coded in the file).
    • Service account: default Cloud Build SA (has the roles from step 4 above).
  3. Push to main – Cloud Build will: pull secrets β†’ build image β†’ push to Artifact Registry β†’ deploy to Cloud Run.

Re-using the boiler-plate in another GCP project

The only project-specific values that are hard-coded in cloudbuild.yaml are:

What Current Value How to change
Service name (Cloud Run) next-firebase-boilerplate search-&-replace the string in cloudbuild.yaml (3 occurrences)
Region europe-west10 change the --region= flag in the deploy step
Extra build args (Firebase bucket & sender ID) montamo-portals-v2.firebasestorage.app, 448992902846 edit the corresponding --build-arg values

Everything elseβ€”Dockerfile, build logic, Secret namesβ€”can stay the same as long as you recreate the Secret Manager entries in the new project.

Tip: if you prefer zero code edits, you can re-introduce Cloud Build substitutions (e.g. _SERVICE_NAME, _REGION) and reference them in the file – just make sure every substitution is actually used or Cloud Build will throw an error.

Minimal manual deploy (no trigger)

# (optional) override service name or region on the fly
SERVICE_NAME=my-service REGION=europe-north1 \
  gcloud builds submit --config cloudbuild.yaml \
  --substitutions=_SERVICE_NAME=$SERVICE_NAME,_REGION=$REGION

About

Boilerplate for a Next.js based platform with basic firebase auth methods, admin interface and example implementation of external data sources. API first.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages