Skip to main content

Self-Hosting Installation Guide

This guide walks you through setting up Studley AI on your own infrastructure. Perfect for organizations, schools, or developers who want full control over their study platform.
This guide is for self-hosting Studley AI. If you’re looking to use the hosted platform, check out our Quick Start Guide instead.

Prerequisites

Before you begin, ensure you have:
  • Node.js 18+ installed on your system
  • PostgreSQL database (local or hosted)
  • Git for cloning the repository
  • Text editor (VS Code, Vim, etc.)
  • Terminal/Command line access
  • Basic knowledge of JavaScript/TypeScript and command line
This installation uses Supabase for authentication and database management. You can use Supabase Cloud (free tier available) or self-host Supabase.

Installation Steps

Step 1: Clone the Repository

First, clone the Studley AI repository to your local machine:
# Clone the repository
git clone https://github.com/your-org/studley-ai.git

# Navigate to the project directory
cd studley-ai
Replace your-org/studley-ai with the actual repository URL provided by your organization.

Step 2: Install Dependencies

Install all required npm packages:
npm install
This will install all dependencies defined in package.json, including:
{
  "dependencies": {
    "next": "16.0.10",
    "react": "19.2.0",
    "react-dom": "19.2.0",
    "@supabase/supabase-js": "2.89.0",
    "@supabase/ssr": "0.8.0",
    "ai": "5.0.108",
    "@ai-sdk/groq": "2.0.32",
    "framer-motion": "12.23.26",
    "lucide-react": "^0.454.0",
    "tailwindcss": "^4.1.9",
    "@radix-ui/react-*": "various versions",
    "zod": "3.25.76"
  },
  "devDependencies": {
    "@types/node": "^22",
    "@types/react": "^19",
    "typescript": "^5",
    "postcss": "^8.5"
  }
}
Installation may take 2-5 minutes depending on your internet connection. Do not interrupt the process.

Step 3: Set Up Database

1

Create Supabase Project

  1. Go to supabase.com
  2. Sign up or log in
  3. Click “New Project”
  4. Fill in project details:
    • Name: studley-ai-production
    • Database Password: Choose a strong password
    • Region: Select closest to your users
2

Get Your Credentials

Once created, navigate to Project Settings → API:
  • Copy your Project URL (NEXT_PUBLIC_SUPABASE_URL)
  • Copy your anon/public key (NEXT_PUBLIC_SUPABASE_ANON_KEY)
3

Run Database Migrations

In your Supabase dashboard, go to SQL Editor and run the initialization script.

Option B: Local PostgreSQL

1

Install PostgreSQL

Download and install PostgreSQL from postgresql.org if not already installed.
2

Create Database

# Login to PostgreSQL
psql -U postgres

# Create database
CREATE DATABASE studley_ai;

# Create user
CREATE USER studley_user WITH PASSWORD 'your_secure_password';

# Grant privileges
GRANT ALL PRIVILEGES ON DATABASE studley_ai TO studley_user;
3

Set Connection String

Your database URL will be:
postgresql://studley_user:your_secure_password@localhost:5432/studley_ai

Step 4: Run Database Schema

Execute the database initialization script to create all necessary tables:
-- Enable UUID extension for generating UUIDs
CREATE EXTENSION IF NOT EXISTS "pgcrypto";

-- Create users table
CREATE TABLE IF NOT EXISTS users (
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
  name TEXT,
  email TEXT UNIQUE NOT NULL,
  "emailVerified" TIMESTAMP,
  password TEXT NOT NULL,
  image TEXT,
  credits INTEGER DEFAULT 5000,
  "createdAt" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  "updatedAt" TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Create accounts table for OAuth providers
CREATE TABLE IF NOT EXISTS accounts (
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
  "userId" TEXT NOT NULL,
  type TEXT NOT NULL,
  provider TEXT NOT NULL,
  "providerAccountId" TEXT NOT NULL,
  refresh_token TEXT,
  access_token TEXT,
  expires_at INTEGER,
  token_type TEXT,
  scope TEXT,
  id_token TEXT,
  session_state TEXT,
  FOREIGN KEY ("userId") REFERENCES users(id) ON DELETE CASCADE,
  UNIQUE(provider, "providerAccountId")
);

-- Create sessions table
CREATE TABLE IF NOT EXISTS sessions (
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
  "sessionToken" TEXT UNIQUE NOT NULL,
  "userId" TEXT NOT NULL,
  expires TIMESTAMP NOT NULL,
  FOREIGN KEY ("userId") REFERENCES users(id) ON DELETE CASCADE
);

-- Create verification_tokens table
CREATE TABLE IF NOT EXISTS verification_tokens (
  identifier TEXT NOT NULL,
  token TEXT UNIQUE NOT NULL,
  expires TIMESTAMP NOT NULL,
  UNIQUE(identifier, token)
);

-- Create credit_usage table for tracking
CREATE TABLE IF NOT EXISTS credit_usage (
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
  "userId" TEXT NOT NULL,
  amount INTEGER NOT NULL,
  type TEXT NOT NULL,
  description TEXT,
  "createdAt" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY ("userId") REFERENCES users(id) ON DELETE CASCADE
);

-- Create generations table
CREATE TABLE IF NOT EXISTS generations (
  id TEXT PRIMARY KEY DEFAULT gen_random_uuid()::text,
  "userId" TEXT NOT NULL,
  type TEXT NOT NULL,
  topic TEXT NOT NULL,
  content TEXT NOT NULL,
  "createdAt" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY ("userId") REFERENCES users(id) ON DELETE CASCADE
);

-- Create indexes for performance
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
CREATE INDEX IF NOT EXISTS idx_sessions_userId ON sessions("userId");
CREATE INDEX IF NOT EXISTS idx_sessions_sessionToken ON sessions("sessionToken");
CREATE INDEX IF NOT EXISTS idx_accounts_userId ON accounts("userId");
CREATE INDEX IF NOT EXISTS idx_credit_usage_userId ON credit_usage("userId");
CREATE INDEX IF NOT EXISTS idx_generations_userId ON generations("userId");
Run the script:
  1. Go to SQL Editor in your Supabase dashboard
  2. Click “New Query”
  3. Copy and paste the SQL script above
  4. Click “Run” or press Cmd/Ctrl + Enter
Additional migration scripts in the scripts/ folder can be run in numerical order for enhanced features like shared sessions, feedback tables, and user profiles.

Step 5: Configure Environment Variables

Create your environment configuration file:
# Create .env.local file
touch .env.local
Add the following environment variables:
# Supabase Configuration
NEXT_PUBLIC_SUPABASE_URL=https://your-project-id.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key-here

# Database (if not using Supabase)
DATABASE_URL=postgresql://studley_user:password@localhost:5432/studley_ai

# NextAuth Configuration
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-nextauth-secret-here

# AI Configuration (Groq for LLM)
GROQ_API_KEY=your-groq-api-key-here

# Optional: Analytics
NEXT_PUBLIC_VERCEL_ANALYTICS_ID=your-analytics-id

# Optional: Email (for welcome emails)
RESEND_API_KEY=your-resend-api-key
EMAIL_FROM=[email protected]

# App Configuration
NEXT_PUBLIC_APP_URL=http://localhost:3000
NODE_ENV=development
Security Critical: Never commit .env.local to version control. Add it to your .gitignore file.

Getting Your API Keys

  1. Go to your Supabase project dashboard
  2. Navigate to SettingsAPI
  3. Copy Project URL (NEXT_PUBLIC_SUPABASE_URL)
  4. Copy anon public key (NEXT_PUBLIC_SUPABASE_ANON_KEY)
Generate a secure random string:
# Using openssl
openssl rand -base64 32

# Using Node.js
node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
Copy the output and use it as your NEXTAUTH_SECRET.
  1. Go to console.groq.com
  2. Sign up or log in
  3. Navigate to API Keys
  4. Click Create API Key
  5. Copy the generated key (save it securely - you can’t view it again)
  1. Go to resend.com
  2. Sign up for a free account
  3. Navigate to API Keys
  4. Create a new API key
  5. Verify your domain or use the test domain for development

Step 6: Build and Run

Now you’re ready to build and run Studley AI!

Development Mode

Run the development server with hot reloading:
npm run dev
Your application will start at http://localhost:3000
Development mode includes hot module replacement (HMR) - changes to your code will automatically refresh the browser.

Production Build

For production deployment:
1

Build the Application

npm run build
This compiles and optimizes your application for production.
2

Start Production Server

npm start
The production server will run on http://localhost:3000 by default.
# Start development server
npm run dev

# Server starts on http://localhost:3000
# Hot reload enabled
# Detailed error messages
# Source maps included

Step 7: Verify Installation

Test that everything is working correctly:
1

Access the Application

Open your browser and navigate to http://localhost:3000You should see the Studley AI homepage with animated hero section.
2

Create a Test Account

  1. Click “Sign Up” in the navigation
  2. Fill in your details:
  3. Submit the form
3

Check Database

Verify the user was created in your database:
SELECT id, name, email, credits FROM users WHERE email = '[email protected]';
You should see the user with 5000 starting credits.
4

Test AI Generation

  1. Navigate to the Quiz Generator
  2. Enter a topic: “Solar System”
  3. Click “Generate Quiz”
  4. Verify that the AI generates a quiz successfully
This requires a valid GROQ_API_KEY. If generation fails, check your API key configuration.
5

Check Credit Deduction

After generating content, verify credits were deducted:
SELECT credits FROM users WHERE email = '[email protected]';
-- Should show 4980 credits (5000 - 20)

SELECT * FROM credit_usage WHERE "userId" = (SELECT id FROM users WHERE email = '[email protected]');
-- Should show one usage record
If any step fails, check the browser console and server logs for error messages. Common issues are covered in the Troubleshooting section below.

Project Structure

Understanding the codebase structure:
studley-ai/
├── app/                      # Next.js App Router
│   ├── dashboard/           # Dashboard and user pages
│   │   ├── page.tsx        # Main dashboard
│   │   ├── library/        # User's saved content
│   │   └── settings/       # User settings
│   ├── tools/              # Generator tools
│   │   ├── quiz-generator/
│   │   ├── flashcard-generator/
│   │   ├── essay-grader/
│   │   └── writing-generator/
│   ├── api/                # API routes
│   │   ├── auth/          # Authentication endpoints
│   │   │   ├── signup/route.ts
│   │   │   ├── login/route.ts
│   │   │   └── logout/route.ts
│   │   └── ai-tutor/      # AI generation endpoints
│   ├── login/             # Login page
│   ├── signup/            # Signup page
│   ├── layout.tsx         # Root layout
│   ├── page.tsx           # Homepage
│   └── globals.css        # Global styles
├── components/             # React components
│   ├── dashboard/         # Dashboard components
│   ├── generators/        # Generator UIs
│   ├── home/             # Homepage sections
│   └── ui/               # shadcn/ui components
├── lib/                   # Utilities and config
│   ├── supabase/
│   │   ├── client.ts     # Client-side Supabase
│   │   └── server.ts     # Server-side Supabase
│   ├── generators-config.ts  # Generator configurations
│   └── email.ts          # Email utilities
├── scripts/               # Database migrations
│   ├── 001_initialize_database.sql
│   └── [...more migrations]
├── public/                # Static assets
│   └── images/
├── .env.local            # Environment variables (create this)
├── package.json          # Dependencies
├── tailwind.config.ts    # Tailwind configuration
├── tsconfig.json         # TypeScript configuration
└── next.config.js        # Next.js configuration

Configuration Files

Supabase Client Setup

import { createServerClient } from "@supabase/ssr"
import { cookies } from "next/headers"

export async function createClient() {
  const cookieStore = await cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll()
        },
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) => 
              cookieStore.set(name, value, options)
            )
          } catch {
            // Server component context
          }
        },
      },
    }
  )
}

Production Deployment

1

Push to GitHub

git add .
git commit -m "Initial Studley AI setup"
git push origin main
2

Connect to Vercel

  1. Go to vercel.com
  2. Click “New Project”
  3. Import your GitHub repository
  4. Configure project settings
3

Set Environment Variables

In Vercel project settings, add all your environment variables from .env.local:
  • NEXT_PUBLIC_SUPABASE_URL
  • NEXT_PUBLIC_SUPABASE_ANON_KEY
  • NEXTAUTH_SECRET
  • GROQ_API_KEY
  • etc.
4

Deploy

Click “Deploy” and wait for the build to complete. Vercel will automatically:
  • Install dependencies
  • Build the project
  • Deploy to production
  • Provide a production URL
5

Update Environment URLs

Update these variables with your production domain:
NEXTAUTH_URL=https://your-domain.vercel.app
NEXT_PUBLIC_APP_URL=https://your-domain.vercel.app

Deploying to Other Platforms

Create a Dockerfile:
FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN npm run build

EXPOSE 3000

CMD ["npm", "start"]
Build and run:
docker build -t studley-ai .
docker run -p 3000:3000 --env-file .env.local studley-ai

Troubleshooting

Error: Error: connect ECONNREFUSED 127.0.0.1:5432Solutions:
  • Check PostgreSQL is running: sudo service postgresql status
  • Verify DATABASE_URL is correct in .env.local
  • Check firewall isn’t blocking port 5432
  • For Supabase, verify project is not paused
Error: Invalid API key or supabase.auth is not definedSolutions:
  • Verify NEXT_PUBLIC_SUPABASE_URL is correct
  • Check NEXT_PUBLIC_SUPABASE_ANON_KEY is the anon/public key, not service role
  • Ensure environment variables start with NEXT_PUBLIC_ for client access
  • Restart dev server after changing env variables
Error: API key invalid or Generation failedSolutions:
  • Verify GROQ_API_KEY is set correctly
  • Check your Groq account has available credits
  • Test API key with a curl request:
curl -X POST https://api.groq.com/openai/v1/chat/completions \
  -H "Authorization: Bearer $GROQ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"mixtral-8x7b-32768","messages":[{"role":"user","content":"Hello"}]}'
Error: Type error: ...Solutions:
  • Run npm install to ensure all types are installed
  • Check tsconfig.json is properly configured
  • Clear Next.js cache: rm -rf .next
  • Update TypeScript: npm install -D typescript@latest
Error: Error: listen EADDRINUSE: address already in use :::3000Solutions:
  • Kill the process using port 3000:
# Find the process
lsof -ti:3000

# Kill it
kill -9 $(lsof -ti:3000)
  • Or use a different port:
PORT=3001 npm run dev
Solutions:
  • Check database user table has credits column
  • Verify credit_usage table exists
  • Check server logs for SQL errors
  • Ensure atomic credit deduction function is working:
SELECT credits FROM users WHERE id = 'user-id';
SELECT * FROM credit_usage WHERE "userId" = 'user-id' ORDER BY "createdAt" DESC LIMIT 10;

Performance Optimization

Database Indexing

Ensure all indexes are created (they’re in the init script):
  • idx_users_email
  • idx_sessions_userId
  • idx_credit_usage_userId
  • idx_generations_userId

Image Optimization

Next.js automatically optimizes images. Use the Image component:
import Image from 'next/image'
<Image src="/logo.png" width={100} height={100} alt="Logo" />

Caching

Enable Next.js caching for static content:
export const revalidate = 3600 // 1 hour

Environment Variables

For production, set:
NODE_ENV=production
NEXT_TELEMETRY_DISABLED=1

Security Best Practices

1

Secure Environment Variables

  • Never commit .env.local to version control
  • Use strong random values for secrets
  • Rotate API keys regularly
  • Use different keys for dev/staging/production
2

Database Security

  • Use Row Level Security (RLS) in Supabase
  • Create separate database users with minimal permissions
  • Enable SSL for database connections
  • Regular backups (Supabase does this automatically)
3

Authentication

  • Enforce strong password requirements (minimum 6 characters)
  • Implement rate limiting on auth endpoints
  • Use HTTPS in production (required)
  • Enable email verification if needed
4

API Protection

  • Implement rate limiting for AI generation
  • Validate all user inputs
  • Use CORS properly
  • Monitor API usage and costs

Maintenance

Regular Tasks

  • Monitor logs: Check for errors and unusual activity
  • Database backups: Automate daily backups (Supabase handles this)
  • Update dependencies: Run npm audit and update packages monthly
  • Monitor costs: Keep track of AI API usage and database size
  • Performance monitoring: Use Vercel Analytics or similar tools

Updating Studley AI

# Pull latest changes
git pull origin main

# Install any new dependencies
npm install

# Run new database migrations
psql -U studley_user -d studley_ai -f scripts/NEW_MIGRATION.sql

# Rebuild and restart
npm run build
pm2 restart studley-ai

Next Steps

Customize Branding

Update colors, logo, and text in app/globals.css and components to match your brand.

Add Custom Generators

Create new generator types by following the pattern in app/tools/ and lib/generators-config.ts.

Configure Email

Set up Resend for welcome emails and notifications. Update email templates in lib/email.ts.

Set Up Analytics

Add Vercel Analytics, Google Analytics, or PostHog for user insights.

Support

Need help with installation? Congratulations! You’ve successfully installed Studley AI. Start generating AI-powered study materials!

Build docs developers (and LLMs) love