Skip to content

mostafa-drz/nextjs-dify-firebase-starter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

83 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Next.js Dify Firebase Starter

A secure Next.js 15 boilerplate for integrating Dify.ai with Firebase authentication and credit-based usage tracking. This project provides a complete foundation for building AI-powered applications with proper user management and cost tracking.

πŸ“‘ Table of Contents

πŸš€ Features

Core Features

  • βœ… Next.js 15 with App Router and Server Actions
  • βœ… Firebase Authentication with magic link (passwordless) login
  • βœ… Firestore Database with security rules and real-time updates
  • βœ… Credit Management System with token-based deduction (1 credit = 1000 tokens)
  • βœ… Secure Dify.ai Integration using server-side API calls only
  • βœ… TypeScript for type safety
  • βœ… Tailwind CSS 4 with shadcn/ui components
  • βœ… ESLint & Prettier for code quality
  • βœ… Google Analytics with Firebase Analytics integration

Security Features

  • πŸ”’ HTTP-only cookie authentication - Secure Firebase ID token handling
  • πŸ”’ API keys never exposed to client-side code
  • πŸ”’ Server-side validation for all Dify API calls
  • πŸ”’ Credit pre-flight checks to prevent unauthorized usage
  • πŸ”’ Atomic transactions for credit deduction
  • πŸ”’ Firebase security rules protecting user data
  • πŸ”’ Sentry error tracking with privacy-first configuration

User Experience

  • πŸ“± Responsive design for all screen sizes
  • ⚑ Real-time credit updates via Firestore listeners
  • πŸ’¬ Custom chat interface with token usage tracking
  • πŸ“Š Credit history and usage analytics
  • 🎨 Modern UI with loading states and error handling
  • πŸ”„ Conversation management with React Query caching
  • ⚑ Optimistic updates for instant UI feedback
  • 🌊 Real-time streaming chat with production-ready error handling and retry logic

πŸ“‹ Prerequisites

  • Node.js 18+ and npm/yarn
  • Firebase project with Firestore and Authentication enabled
  • Dify.ai account with API access

πŸ› οΈ Setup Instructions

1. Installation

git clone https://github.com/mostafa-drz/nextjs-dify-firebase-starter.git
cd nextjs-dify-firebase-starter
npm install

2. Firebase Project Setup

  1. Create Firebase Project

  2. Enable Authentication

    • Go to Authentication β†’ Sign-in method
    • Enable Email/Password provider
    • (Optional) Enable Google provider for OAuth
  3. Setup Firestore Database

    • Go to Firestore Database
    • Click "Create database"
    • Choose "Production mode"
    • Select your preferred location
  4. Generate Service Account Key

    • Go to Project Settings β†’ Service accounts
    • Click "Generate new private key"
    • Download the JSON file (keep it secure)
  5. Enable Analytics (Optional)

    • Go to Analytics β†’ Dashboard
    • Follow setup steps if not already enabled
    • Copy the Measurement ID from Data Streams

3. Environment Configuration

Copy .env.example to .env.local and fill in your values:

cp .env.example .env.local

Required environment variables:

# Firebase Client Configuration
NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_project.firebaseapp.com
NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your_project.appspot.com
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your_sender_id
NEXT_PUBLIC_FIREBASE_APP_ID=your_app_id
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-XXXXXXXXXX

# Firebase Admin (Server-side)
FIREBASE_PROJECT_ID=your_project_id
FIREBASE_CLIENT_EMAIL=your_service_account_email
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"

# Dify AI Configuration
DIFY_API_KEY=your_dify_api_key
DIFY_BASE_URL=https://api.dify.ai/v1

# Application Configuration
NEXT_PUBLIC_SUPPORT_EMAIL=support@yourdomain.com

# Sentry Configuration (Optional)
NEXT_PUBLIC_SENTRY_DSN=https://your_public_key@o0.ingest.sentry.io/0
SENTRY_DSN=https://your_public_key@o0.ingest.sentry.io/0
SENTRY_AUTH_TOKEN=your_sentry_auth_token_here
SENTRY_ORG=your_sentry_org_slug
SENTRY_PROJECT=your_sentry_project_slug

# App Configuration
SUPPORT_EMAIL=support@yourdomain.com
NEXT_PUBLIC_SUPPORT_EMAIL=support@yourdomain.com

4. Firestore Security Rules Setup

Deploy the security rules to protect your data:

# Install Firebase CLI globally
npm install -g firebase-tools

# Login to Firebase
firebase login

# Initialize Firestore in your project
firebase init firestore
# - Select your existing Firebase project
# - Keep default firestore.rules file
# - Keep default firestore.indexes.json file

# Deploy the security rules
firebase deploy --only firestore:rules

5. Dify.ai Setup

  1. Get Dify API Key

    • Visit Dify.ai and create account
    • Create a new app or use existing one
    • Copy the API key from app settings
  2. Configure App Settings

    • Ensure your Dify app supports the required endpoints
    • Configure any necessary conversation settings
    • Test the API key works with your app

6. Start Development Server

npm run dev

Open http://localhost:3000 to see the application.

πŸ”¨ Development Experience

This project includes a comprehensive development setup with automated code formatting, linting, and quality checks to ensure consistent code style and prevent common errors.

Development Tools Setup

The project is configured with modern development tools for the best developer experience:

Code Quality Tools

  • Prettier: Simple, standard code formatting with Tailwind CSS class sorting
  • ESLint: Minimal linting with Next.js and TypeScript defaults
  • TypeScript: Type checking for build validation
  • Husky: Git hooks for automated quality checks

IDE Configuration

Pre-configured VSCode/Cursor settings for optimal development:

  • Format on save enabled
  • Auto-fix ESLint issues on save
  • Tailwind CSS IntelliSense support
  • TypeScript IntelliSense and error highlighting
  • Recommended extensions list

Git Hooks

Automated quality checks run on every commit and push:

  • Pre-commit: Runs linting and formatting on staged files
  • Pre-push: Runs TypeScript checking and build verification

Available Scripts

# Development
npm run dev          # Start development server with hot reload
npm run build        # Build for production
npm run start        # Start production server

# Code Quality
npm run lint         # Check code with ESLint
npm run lint:fix     # Fix ESLint issues automatically
npm run format       # Format code with Prettier
npm run format:check # Check if code is properly formatted
npm run typecheck    # Type check with TypeScript compiler

# Git Hooks (handled automatically)
npm run prepare      # Initialize Husky (runs on npm install)

IDE Setup (VSCode/Cursor)

The project includes .vscode/ configuration with:

Recommended Extensions

  • Prettier: Code formatting
  • ESLint: Code linting
  • Tailwind CSS IntelliSense: CSS class completion
  • Code Spell Checker: Spelling validation
  • Error Lens: Inline error display
  • Auto Rename Tag: Automatic HTML/JSX tag renaming

Editor Settings

  • Auto-format on save for consistent code style
  • Auto-fix ESLint issues to prevent common errors
  • Tailwind class sorting for better organization
  • TypeScript hints for better development experience

First-Time Setup for New Developers

  1. Clone and install dependencies:

    git clone https://github.com/mostafa-drz/nextjs-dify-firebase-starter.git
    cd nextjs-dify-firebase-starter
    npm install
  2. Open in VSCode/Cursor:

    code .  # or cursor .
  3. Install recommended extensions when prompted

  4. Configure environment (see Environment Configuration section)

  5. Verify setup:

    npm run typecheck  # Should pass without errors
    npm run lint       # Should pass without errors
    npm run build      # Should build successfully

Code Formatting Rules

The project uses minimal, standard formatting conventions:

  • Print width: 100 characters
  • Single quotes for strings
  • Semicolons required
  • 2 spaces for indentation
  • Tailwind classes automatically sorted

Quality Checks

Before every commit, the following checks run automatically:

  1. ESLint: Checks for code quality issues
  2. Prettier: Ensures consistent formatting
  3. TypeScript: Validates type safety

Before every push:

  1. TypeScript compilation: Ensures no type errors
  2. Production build: Ensures the app builds successfully

Troubleshooting

Husky hooks not working?

npx husky install

ESLint/Prettier conflicts? The project uses eslint-config-prettier to disable conflicting rules automatically.

TypeScript errors on build?

npm run typecheck  # Check specific TypeScript issues

Extensions not working in Cursor? Cursor is compatible with VSCode extensions. Install the recommended extensions manually if auto-prompt doesn't appear.

🎯 Usage

Basic Integration

Use the DifyChat component in your pages:

import { DifyChat } from '@/components/dify/DifyChat';

export default function MyPage() {
  return (
    <DifyChat
      apiKey="app-your-dify-key" // Server-side only, never exposed
      name="My Assistant"
      placeholder="Ask me anything..."
      welcomeMessage="Hello! How can I help you today?"
    />
  );
}

Streaming Chat (New!)

Enable real-time streaming for instant message updates:

import { DifyChat } from '@/components/dify/DifyChat';

export default function StreamingPage() {
  return (
    <DifyChat
      name="Streaming Assistant"
      enableStreaming={true}
      streamingMode="auto"
      placeholder="Ask me anything with real-time streaming..."
      welcomeMessage="Hello! Watch my responses appear in real-time!"
    />
  );
}

Streaming Features:

  • βœ… Real-time message updates - See responses as they're generated
  • βœ… Production-ready error handling - Automatic retry with exponential backoff
  • βœ… Proper cleanup - AbortController prevents memory leaks
  • βœ… Stop functionality - Users can stop streaming at any time
  • βœ… Fallback support - Gracefully falls back to blocking mode on errors
  • βœ… Configurable - Choose between auto-streaming or manual control

Credit Management

Access credit information using the useCredits hook:

import { useCredits } from '@/lib/hooks/useCredits';

export function MyComponent() {
  const { availableCredits, hasEnoughCredits, deductForTokens } = useCredits();

  return (
    <div>
      <p>Available: {availableCredits} credits</p>
      {!hasEnoughCredits(10) && <p>Insufficient credits!</p>}
    </div>
  );
}

Server Actions

Use server actions for secure Dify API calls:

import { sendDifyMessage } from '@/lib/actions/dify';

// In a server action or API route
const result = await sendDifyMessage(userId, apiKey, {
  query: 'Hello',
  user: userId,
  response_mode: 'blocking',
});

if (result.success) {
  console.log('Response:', result.data?.answer);
  console.log('Tokens used:', result.usage?.total_tokens);
}

πŸ’¬ Conversation Management

This boilerplate implements a client-side conversation management system using React Query for caching and optimistic updates. This approach prioritizes simplicity and performance while providing a solid foundation for developers to extend with their own persistence strategies.

Architecture Overview

Why React Query?

  • Automatic caching with intelligent invalidation
  • Optimistic updates for instant UI feedback
  • Background refetching to keep data fresh
  • Error handling with retry logic
  • DevTools for debugging (development only)

Why Not Firebase/Firestore?

  • Simplicity: Avoids additional database complexity
  • Performance: Client-side caching is faster than database queries
  • Flexibility: Developers can choose their own persistence layer
  • Cost: Reduces Firebase read/write operations

Data Flow

User Action β†’ Optimistic Update β†’ API Call β†’ Cache Update β†’ UI Update
     ↓              ↓                ↓           ↓           ↓
  Click Send β†’ Show Message β†’ Call Dify β†’ Update Cache β†’ Show Response

Usage Examples

Basic Conversation Management

import { useConversationMessages } from '@/lib/hooks/useConversationMessages';

export function ChatComponent() {
  const { messages, isLoading, addMessageOptimistically, invalidate } = useConversationMessages(
    conversationId,
    userId,
    apiKey
  );

  const handleSendMessage = async (content: string) => {
    const tempMessage = { id: 'temp', content, role: 'user' };
    addMessageOptimistically(tempMessage); // Instant UI update

    const result = await sendDifyMessage(userId, apiKey, { query: content });
    // Cache automatically updated with real data
  };

  return (
    <div>
      {isLoading && <div>Loading conversation...</div>}
      {messages.map((message) => (
        <div key={message.id}>{message.content}</div>
      ))}
    </div>
  );
}

Conversation List Management

import { ConversationList } from '@/components/dify/ConversationList';

export function ChatPage() {
  const [currentConversationId, setCurrentConversationId] = useState<string>();

  return (
    <div className="grid gap-8 lg:grid-cols-4">
      <div className="lg:col-span-1">
        <ConversationList
          apiKey="app-demo-key"
          userId={user.uid}
          currentConversationId={currentConversationId}
          onConversationSelect={setCurrentConversationId}
          onCreateNew={() => setCurrentConversationId(undefined)}
        />
      </div>
      <div className="lg:col-span-3">
        <DifyChat
          apiKey="app-demo-key"
          conversationId={currentConversationId}
          // ... other props
        />
      </div>
    </div>
  );
}

Performance Features

  • Smart Caching: 5-minute cache with 1-minute stale time
  • Background Refetching: Keep data fresh without user interaction
  • Prefetching: Preload messages on conversation hover
  • Memory Management: Automatic garbage collection of unused data
  • Bundle Size: React Query adds only ~13KB gzipped

Extending the System

Option 1: Add Firebase Persistence

// Add to your Firebase functions
export const syncConversationToFirestore = async (conversationId: string, messages: unknown[]) => {
  await db.collection('conversations').doc(conversationId).set({
    messages,
    lastUpdated: new Date(),
    userId: auth.currentUser?.uid,
  });
};

// Call after successful message send
const result = await sendDifyMessage(userId, apiKey, request);
await syncConversationToFirestore(result.data.conversation_id, messages);

Option 2: Add Local Storage Backup

// Add to useConversationMessages hook
useEffect(() => {
  if (data) {
    localStorage.setItem(`conversation-${conversationId}`, JSON.stringify(data));
  }
}, [data, conversationId]);

Option 3: Add Real-time Sync

// Add WebSocket or Server-Sent Events
const useRealtimeMessages = (conversationId: string) => {
  useEffect(() => {
    const ws = new WebSocket(`/ws/conversations/${conversationId}`);
    ws.onmessage = (event) => {
      const newMessage = JSON.parse(event.data);
      addMessageOptimistically(newMessage);
    };
    return () => ws.close();
  }, [conversationId]);
};

Debug Tools

React Query DevTools are automatically enabled in development:

// Automatically included in development builds
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';

Best Practices

Do's:

  • βœ… Use optimistic updates for better UX
  • βœ… Implement proper error boundaries
  • βœ… Add loading states for all async operations
  • βœ… Use TypeScript for type safety
  • βœ… Test with React Query DevTools

Don'ts:

  • ❌ Don't bypass the cache for real-time updates
  • ❌ Don't store sensitive data in client-side cache
  • ❌ Don't forget to handle offline scenarios
  • ❌ Don't over-fetch data (use pagination)

πŸ—οΈ Project Structure

src/
β”œβ”€β”€ app/                    # Next.js App Router pages
β”‚   β”œβ”€β”€ chat/              # Chat demo page with conversation management
β”‚   β”œβ”€β”€ conversations/     # Dedicated conversation management page
β”‚   β”œβ”€β”€ dashboard/         # User dashboard
β”‚   β”œβ”€β”€ login/            # Authentication page
β”‚   └── test-credits/     # Credit testing utilities
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ auth/             # Authentication components
β”‚   β”œβ”€β”€ credits/          # Credit management UI
β”‚   β”œβ”€β”€ dify/            # Dify integration components
β”‚   β”‚   β”œβ”€β”€ DifyChat.tsx           # Main chat interface
β”‚   β”‚   β”œβ”€β”€ ConversationList.tsx  # Conversation management
β”‚   β”‚   β”œβ”€β”€ MessageFeedback.tsx   # Message feedback system
β”‚   β”‚   └── SuggestedQuestions.tsx # Suggested questions
β”‚   β”œβ”€β”€ providers/        # React context providers
β”‚   β”‚   └── QueryProvider.tsx     # React Query provider
β”‚   └── ui/              # shadcn/ui components
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ actions/         # Server actions
β”‚   β”œβ”€β”€ hooks/           # Custom React hooks
β”‚   β”‚   β”œβ”€β”€ useCredits.ts              # Credit management
β”‚   β”‚   └── useConversationMessages.ts # Conversation caching
β”‚   β”œβ”€β”€ services/        # Dify API services
β”‚   β”‚   └── dify/        # Modular Dify service architecture
β”‚   β”œβ”€β”€ utils/           # Utility functions
β”‚   └── config/          # Configuration constants
└── types/               # TypeScript type definitions

πŸ”§ Configuration

Credit System

Configure credit costs and limits in src/lib/config/constants.ts:

export const CREDIT_CONFIG = {
  TOKENS_PER_CREDIT: 1000, // 1 credit = 1000 tokens
  FREE_TIER_CREDITS: 100, // Free credits per month
  MIN_CREDITS_WARNING: 10, // Show warning below this
  CREDIT_PURCHASE_AMOUNTS: [10, 50, 100, 500],
} as const;

Dify Apps

For multiple Dify apps, create an app configuration:

const DIFY_APPS = {
  chat: {
    name: 'Chat Assistant',
    apiKey: process.env.DIFY_CHAT_API_KEY!,
  },
  summarizer: {
    name: 'Document Summarizer',
    apiKey: process.env.DIFY_SUMMARIZER_API_KEY!,
  },
};

πŸ§ͺ Testing

Testing Philosophy

This project follows focused, self-descriptive testing principles that prioritize quality over quantity. Our tests focus on essential business logic and real-world scenarios rather than exhaustive coverage.

Core Principles:

  • Self-Descriptive: Test names clearly describe what's being tested and expected outcomes
  • Essential Focus: Test business-critical logic first (credit system, authentication, payment flows)
  • Not Exhaustive: Skip trivial functions, third-party libraries, and implementation details
  • Real-World Scenarios: Test user journeys and integration points where things can break
  • Maintainable: Simple, focused tests that are easy to understand and modify

What We Test:

  • βœ… Business logic (credit calculations, user authentication flows)
  • βœ… Error handling and failure scenarios
  • βœ… Integration points between different parts of the system
  • βœ… User journeys and complete workflows
  • βœ… Edge cases and boundary conditions

What We Don't Test:

  • ❌ Third-party libraries (Firebase SDK, Dify API)
  • ❌ Simple utilities and data transformations
  • ❌ Configuration and environment variables
  • ❌ Styling and visual appearance
  • ❌ Trivial getters/setters without business logic

Run Tests

npm test              # Run all tests
npm test:watch        # Run tests in watch mode
npm test:coverage     # Run tests with coverage report
npm test:ui           # Run tests with UI interface
npm test:run          # Run tests once (CI mode)
npm test:ci           # Run tests with coverage and verbose output
npm test:firebase     # Run tests with Firebase emulators
npm test:dify         # Test Dify API connection

Test Coverage

Our test suite covers:

  • βœ… Business Logic: Credit calculations, user authentication, rate limiting
  • βœ… Server Actions: Credit management, user initialization, Dify API integration
  • βœ… Utility Functions: Credit utilities, input validation, rate limiting
  • βœ… Dify Services: Chat service, conversation management, API integration
  • βœ… React Hooks: useCredits, useChatMessages, useDify integration
  • βœ… Error Handling: Database errors, API failures, network issues
  • βœ… Edge Cases: Insufficient credits, rate limit exceeded, invalid inputs

Test Structure

src/
β”œβ”€β”€ __tests__/
β”‚   β”œβ”€β”€ setup.ts              # Test environment setup
β”‚   β”œβ”€β”€ mocks/                # Mock implementations
β”‚   β”‚   β”œβ”€β”€ handlers.ts       # MSW API handlers
β”‚   β”‚   β”œβ”€β”€ firebase-admin.ts # Firebase Admin mocks
β”‚   β”‚   └── firebase-client.ts# Firebase Client mocks
β”‚   β”œβ”€β”€ fixtures/             # Test data fixtures
β”‚   β”‚   β”œβ”€β”€ users.ts          # User test data
β”‚   β”‚   └── dify-responses.ts # Dify API response mocks
β”‚   └── utils/                # Test utilities
β”‚       β”œβ”€β”€ render.tsx        # Custom render function
β”‚       └── auth.ts           # Auth test helpers
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ actions/__tests__/    # Server action tests
β”‚   β”œβ”€β”€ hooks/__tests__/      # React hook tests
β”‚   β”œβ”€β”€ services/dify/__tests__/ # Dify service tests
β”‚   └── utils/__tests__/      # Utility function tests

Test Credit System

Visit /test-credits to test credit deduction and management.

Test Dify Integration

Visit /chat to test the Dify chat interface.

Test Sentry Integration

Visit /sentry-test to test error tracking and logging.

Enable Google Analytics

  1. Enable Analytics in your Firebase project console
  2. Copy the Measurement ID from Analytics settings
  3. Add NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-XXXXXXXXXX to .env.local

🌍 Adding More Languages

This boilerplate supports internationalization using next-intl. Currently configured for English only, but you can easily add more languages:

Adding a New Language (e.g., Spanish)

  1. Add locale to config:

    // src/i18n/config.ts
    export const locales = ['en', 'es'] as const;
  2. Create translation file:

    # Create src/i18n/messages/es.json
    {
      "common": {
        "loading": "Cargando...",
        "error": "OcurriΓ³ un error"
      },
      "chat": {
        "title": "Asistente de Chat IA",
        "placeholder": "Escribe tu mensaje..."
      }
    }
  3. Update middleware:

    // middleware.ts
    export const config = {
      matcher: ['/', '/(en|es)/:path*'],
    };
  4. Add language switcher component (optional)

Context Integration

The system automatically passes user language context to Dify AI for smarter responses:

// Language context is automatically included
const context = {
  language: { code: 'es', locale: 'es-ES' },
  timestamp: '2024-12-19T10:30:00Z',
  timezone: 'Europe/Madrid',
};

This helps the AI provide responses in the user's preferred language and cultural context.

πŸš€ Deployment

Vercel (Recommended)

  1. Push your code to GitHub
  2. Connect repository to Vercel
  3. Add environment variables in Vercel dashboard
  4. Deploy

Other Platforms

This Next.js app can be deployed to any platform supporting Node.js:

  • Railway
  • Render
  • Heroku
  • DigitalOcean App Platform
  • AWS Amplify

πŸ“Š Monitoring

Firebase Console

  • Monitor authentication metrics
  • View Firestore usage and costs
  • Check security rule violations

Sentry Error Tracking

This project includes production-ready Sentry integration with minimal but essential logging:

Features

  • Smart Error Filtering: Automatically filters non-critical errors (network timeouts, browser quirks)
  • Privacy-First: Masks sensitive data, excludes cookies and IP addresses
  • Performance Monitoring: Tracks slow operations and API performance
  • Production Optimized: Lower sampling rates to reduce noise (10% traces, 1% sessions)

Setup

  1. Create a free Sentry account and project
  2. Copy your DSN and add to .env.local:
    NEXT_PUBLIC_SENTRY_DSN=https://your_key@o0.ingest.sentry.io/0
    SENTRY_DSN=https://your_key@o0.ingest.sentry.io/0
  3. Test with /sentry-test page

Usage Examples

import { logError, logMessage, LogLevel } from '@/lib/sentry';

// Log critical errors
try {
  await processPayment();
} catch (error) {
  logError(error, { userId, amount, paymentMethod });
}

// Log important events
logMessage('User upgraded to premium', LogLevel.INFO);

What Gets Logged

  • βœ… API errors (5xx responses)
  • βœ… Authentication failures
  • βœ… Payment processing errors
  • βœ… Slow operations (>3s)
  • βœ… Unhandled exceptions
  • ❌ Network timeouts (filtered)
  • ❌ Browser extension errors (filtered)
  • ❌ Expected auth errors (filtered)

Application Monitoring

  • Credit usage patterns in Firestore
  • Real-time error alerts and performance monitoring
  • User activity via Firebase Analytics

Google Analytics Integration

This project includes privacy-first Google Analytics using Firebase Analytics with minimal data collection:

Features

  • Production Only: Analytics only tracks in production environment
  • Essential Events: Tracks only business-critical events (auth, chat, credits)
  • Privacy Focused: No personal data collection or tracking
  • Client-Side Only: Simple Firebase Analytics integration

Tracked Events

  • βœ… Page Views: User navigation patterns
  • βœ… Authentication: Login/logout events
  • βœ… Chat Usage: Message sending and conversation starts
  • βœ… Credit Usage: Purchase and deduction events
  • βœ… External Links: Outbound link clicks

Setup

  1. Enable Analytics in your Firebase Console
  2. Copy Measurement ID from Analytics β†’ Data Streams
  3. Add to Environment: NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-XXXXXXXXXX
  4. Deploy: Analytics will automatically start tracking in production

Usage Examples

import { trackAuth, trackChat, trackCredits } from '@/lib/analytics';

// Track user authentication
trackAuth('login');

// Track chat interactions
trackChat('message_sent', messageLength);

// Track credit events
trackCredits('purchase', amount);

Privacy Compliance

  • GDPR Compliant: No personal data collection
  • Development Safe: No tracking in development environment
  • Error Handling: Graceful failures without breaking user experience

πŸ” Authentication System

This project uses HTTP-only cookie authentication for secure Firebase integration. No manual token handling required!

How It Works

  1. User signs in β†’ Firebase client gets ID token
  2. Token sent to server β†’ /api/auth/set-token sets HTTP-only cookie
  3. Automatic authentication β†’ Cookie sent with every request
  4. User signs out β†’ Cookie cleared via /api/auth/clear-token

Security Features

  • βœ… HTTP-only cookies - XSS protection
  • βœ… HTTPS only - Secure in production
  • βœ… SameSite=strict - CSRF protection
  • βœ… Proper JWT verification - Firebase Admin SDK
  • βœ… 7-day expiry - Reasonable session length

Files

  • src/lib/config/auth-config.ts - Simple constants
  • src/app/api/auth/set-token/route.ts - Set cookie
  • src/app/api/auth/clear-token/route.ts - Clear cookie
  • src/lib/utils/auth-cookie.ts - Cookie helpers
  • src/lib/auth/middleware-auth.ts - JWT verification

πŸ›‘οΈ Security Considerations

  1. Authentication: HTTP-only cookies with proper JWT verification
  2. API Keys: Never expose Dify API keys to client-side code
  3. Credit Limits: Implement proper credit limits to prevent abuse
  4. Rate Limiting: Consider adding rate limiting for API calls
  5. User Validation: Always validate user authentication server-side
  6. Firestore Rules: Keep security rules restrictive and test thoroughly

🀝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests if applicable
  5. Submit a pull request

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ†˜ Support

For support and questions:

πŸ“š Additional Resources

About

Full-stack Next.js 15 starter for AI apps. Includes Firebase Auth, Dify AI, credit management, and streaming chat.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors