FireGEO Documentation

repository·main·Indexed 20 days ago

https://github.com/firecrawl/firegeo

An open-source SaaS starter kit for developers to implement authentication, billing, AI chat, and brand monitoring. Built with Next.js 15, PostgreSQL, Better Auth, and Drizzle ORM, it includes a brand analysis engine (performAnalysis) for competitor research and brand visibility scoring using multiple AI providers.

Tokens
16K
Snippets
45
Records
59
Agent score
71%

What's inside FireGEO

  1. Understand the database schema and migration structure

    main

    The migrations/ directory contains SQL scripts for application-specific tables.

    Key Migration Files

    • 001_create_app_schema.sql: Creates core application tables including conversations, messages, and user profiles.

    Schema Relationships and Constraints

    • Better Auth Integration: The application relies on Better Auth for authentication. Better Auth manages its own tables (user, session, account, verification) automatically.
    • Foreign Keys: Application tables reference the Better Auth user table using a user_id field of type text.
    • Idempotency: All migration scripts use IF NOT EXISTS to ensure they can be run multiple times without error.
  2. Quick Start with One-Command Setup

    main

    The fastest way to get the FireGEO SaaS starter running is using the automated setup script. This script installs dependencies, tests the database connection, generates Better Auth tables, applies migrations, and configures Autumn billing if an API key is provided.

    Prerequisites

    • Node.js 18+ and npm
    • PostgreSQL database

    Setup Steps

    1. Clone the repository and enter the directory:
      git clone https://github.com/mendableai/firegeo
      cd firegeo
    2. Copy the environment variables template:
      cp .env.example .env.local
    3. Add required keys to .env.local:
      • DATABASE_URL: Your PostgreSQL connection string.
      • BETTER_AUTH_SECRET: A secure secret generated via openssl rand -base64 32.
    4. Run the automated setup:
      npm run setup
    5. Start the development server:
      npm run dev

    Visit http://localhost:3000 to view your application.

    # Clone the repository
    git clone https://github.com/mendableai/firegeo
    cd firegeo
    
    # Copy environment variables
    cp .env.example .env.local
    
    # Run the automated setup
    npm run setup
    
    # Start Development
    npm run dev
  3. Manual Setup (Step-by-Step)

    main

    If you need granular control, follow these steps to manually configure the project:

    1. Install Dependencies

    npm install

    2. Environment Variables

    Copy the example file and edit it:

    cp .env.example .env.local
    nano .env.local

    Generate a secure secret for BETTER_AUTH_SECRET using:

    openssl rand -base64 32

    3. Database Initialization

    Push the schema, generate Better Auth tables, and apply migrations:

    npm run db:push
    npx @better-auth/cli generate --config better-auth.config.ts
    npm run db:push

    4. Configure Autumn Billing

    Run the specific Autumn setup script:

    npm run setup:autumn

    5. Verify Setup

    Check the database via Drizzle Studio and start the server:

    npm run db:studio
    npm run dev
    # Manual Setup Sequence
    npm install
    cp .env.example .env.local
    # (Edit .env.local with DATABASE_URL and BETTER_AUTH_SECRET)
    npm run db:push
    npx @better-auth/cli generate --config better-auth.config.ts
    npm run db:push
    npm run setup:autumn
    npm run dev
  4. Run database migrations

    main

    To apply the application database schema to your database, you can use psql directly or use a migration tool like dbmate or migrate. The migrations are idempotent because all tables use IF NOT EXISTS.

    # Using psql directly
    psql $DATABASE_URL -f migrations/001_create_app_schema.sql
    
    # Using dbmate
    dbmate up
    
    # Using migrate
    migrate -path migrations -database $DATABASE_URL up
  5. Configure Autumn Billing

    main

    To enable billing, you must configure Autumn with specific product IDs and features.

    1. Create Account: Sign up at useautumn.com.
    2. Get API Key: Navigate to Settings → Developer and create an API key. Add it to .env.local as AUTUMN_SECRET_KEY.
    3. Stripe Integration: Add your Stripe secret key in the Autumn dashboard under Integrations → Stripe. Webhooks are handled automatically.
    4. Create Usage Feature:
      • Name: Messages
      • ID: messages (Must match exactly)
      • Type: Usage
      • Unit: message
    5. Create Products:
      • Free Product: Name: Free, ID: (auto-generated), Price: $0/month. Add Messages feature with a limit of 100.
      • Pro Product: Name: Pro, ID: pro (Must match exactly), Price: $20/month. Add Messages feature with a limit of 0 (unlimited).
  6. Database Schema Overview

    main
    The FireGEO database schema is built using drizzle-orm and manages several core entities for a SaaS application, including user profiles, chat conversations, AI message feedback, user settings, and brand analysis data. The schema uses PostgreSQL-specific features like uuid, jsonb, and custom pgEnum types.
  7. Understand the ErrorResponse JSON structure

    main

    When an error occurs, the API returns a standardized JSON object. The structure depends on the error type, but the base schema is as follows:

    {
      "error": {
        "message": "string",
        "code": "ERROR_CODE_STRING",
        "statusCode": 123,
        "timestamp": "ISO_8601_TIMESTAMP",
        "fields": { "field_name": "error_message" }, // Only for ValidationError
        "metadata": { ... } // Contextual data for RateLimit, InsufficientCredits, or ExternalService errors
      }
    }

    Specific metadata fields include:

    • ValidationError: fields object mapping input names to error messages.
    • RateLimitError: metadata.retryAfter (number of seconds).
    • InsufficientCreditsError: metadata.creditsRequired and metadata.creditsAvailable.
    • ExternalServiceError: metadata.service (the name of the failing service).
  8. PromptStatus and PromptCompletionStatus

    main

    The system uses PromptStatus to track the lifecycle of an individual prompt execution: 'pending' | 'running' | 'completed' | 'failed' | 'skipped'.

    PromptCompletionStatus is a nested mapping used to track these statuses across multiple prompts and providers, keyed by the prompt string: {[promptKey: string]: {[provider: string]: PromptStatus}}.

  9. Troubleshoot Authentication Errors

    main

    If you encounter the error relation 'user' does not exist, it means the Better Auth tables have not been created in your database.

    To fix this, generate the schema and push it to your database:

    # Generate Better Auth schema
    npx @better-auth/cli generate --config better-auth.config.ts
    
    # Push the schema to database
    npm run db:push
    npx @better-auth/cli generate --config better-auth.config.ts
    npm run db:push
  10. Configure brand detection behavior

    main

    The brand detection system can be configured globally using updateBrandDetectionConfig. This allows you to modify detection options, brand aliases, ignored suffixes, negative context patterns, and confidence thresholds.

    Configuration Schema (BrandDetectionConfig)

    • defaultOptions: BrandDetectionOptions object (e.g., caseSensitive, wholeWordOnly, includeVariations, excludeNegativeContext).
    • brandAliases: A Map<string, string[]> mapping brand names to their known variations.
    • ignoredSuffixes: An array of strings (e.g., ['inc', 'llc']) to ignore when matching brands.
    • negativeContextPatterns: An array of RegExp used to exclude matches found in negative contexts (e.g., patterns matching "avoid using" or "scam").
    • confidenceThresholds: An object containing high, medium, and low numeric thresholds (default values: high: 0.8, medium: 0.5, low: 0.3).
    import { updateBrandDetectionConfig } from './lib/brand-detection-config';
    
    updateBrandDetectionConfig({
      confidenceThresholds: {
        high: 0.9,
        medium: 0.6,
        low: 0.4
      },
      ignoredSuffixes: ['corp', 'ltd']
    });
  11. Configure Drizzle ORM for FireGEO

    main

    The project uses drizzle-kit for database migrations. The configuration is defined in drizzle.config.ts and uses a PostgreSQL dialect. It specifically excludes tables managed by Better Auth from the migration process using the tablesFilter option to prevent conflicts.

    Key configuration settings:

    • schema: Points to the source of truth for the database schema at ./lib/db/schema.ts.
    • out: The directory where generated migrations are stored (./drizzle-generated).
    • dialect: Set to postgresql.
    • dbCredentials: Requires a url provided via the DATABASE_URL environment variable.
    • tablesFilter: Uses negation patterns to exclude Better Auth tables (!user, !session, !account, !verification) from being managed by Drizzle migrations.
    import type { Config } from 'drizzle-kit';
    import * as dotenv from 'dotenv';
    
    // Load environment variables
    dotenv.config({ path: '.env.local' });
    
    export default {
      schema: './lib/db/schema.ts',
      out: './drizzle-generated',
      dialect: 'postgresql',
      dbCredentials: {
        url: process.env.DATABASE_URL!,
      },
      // Exclude Better Auth tables from migrations since they're managed by Better Auth
      tablesFilter: ['!user', '!session', '!account', '!verification'],
    } satisfies Config;
  12. Enable or disable AI providers

    main

    You can control which AI providers are available in the system by modifying the PROVIDER_ENABLED_CONFIG object.

    Note that setting a provider to true only enables it for selection; the provider still requires a valid API key in your environment variables to actually function. If a provider is enabled but the corresponding API key is missing, isProviderConfigured() will return false and getProviderModel() will return null.

    export const PROVIDER_ENABLED_CONFIG: Record<string, boolean> = {
      openai: true,      // OpenAI is enabled
      anthropic: true,   // Anthropic is enabled
      google: false,    // Google is disabled
      perplexity: true,  // Perplexity is enabled
    };