Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ The 12 migrations tell the story of iterative feature development, not a pre-pla

**What this progression demonstrates:** The schema evolved with the product. Search started as text-only (002), added semantic vectors (003), then face vectors were accelerated with HNSW (006). Data integrity was tightened retroactively (005, 008) as pipeline re-runs exposed edge cases. The sentinel pattern (009, 012) was iterated and refined during testing. Each migration solves a specific problem encountered during development — not a theoretical schema design exercise.

**Developer experience:** For new deployments, `supabase/schema.sql` consolidates all 12 migrations into a single file — one paste into the Supabase SQL Editor creates the full schema. The individual migrations remain for incremental updates on existing databases. A setup script (`scripts/setup.sh`) automates dependency installation, `.env` creation, and prerequisite validation.

## 5. Pipeline Design

### 5.1 Origin: Python to TypeScript
Expand Down Expand Up @@ -506,7 +508,7 @@ The goal is not multi-tenant SaaS but a **portable, customizable tool** that any

### 9.2 Minimal Changes for Portability

1. **Setup wizard** — a first-run experience that collects Drive folder ID, API keys, and event branding. Currently these are environment variables; a wizard would write them to Vercel env vars or a config file.
1. **Setup wizard** — a first-run experience that collects Drive folder ID, API keys, and event branding. The current `scripts/setup.sh` handles local setup; the next step is a web-based wizard that writes directly to Vercel env vars or a config file.
2. **Auth improvement** — replace the prototype cookie with Supabase Auth or a simple hashed-password check. The organizer sets a password during setup.
3. **Dynamic theming** — extract the current hardcoded color scheme (matrix green/magenta) into CSS custom properties or a theme config. The organizer picks colors during setup.
4. **Face matching as optional** — already partially implemented (face-embed phase skips if `FACE_API_URL` is unset). The UI should gracefully hide face matching features when the service isn't configured.
Expand Down
53 changes: 20 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,60 +97,43 @@ Next.js 15 App (Vercel)

## Setup

### Prerequisites

- Node.js 18+
- Google Cloud project with **Drive API** enabled + API key
- Google Drive folder with event photos (shared as "Anyone with the link can view")
- Supabase project with pgvector extension enabled
- Gemini API key (from [aistudio.google.com](https://aistudio.google.com))
- (Optional) InsightFace microservice deployed for face matching

### 1. Clone and install
### Quick Start

```bash
git clone <repo-url>
cd eventlens
npm install
./scripts/setup.sh
```

### 2. Set up Supabase
The setup script checks prerequisites, installs dependencies, creates your `.env` file, validates required keys, and prints next steps.

Create a Supabase project, then run the 12 migrations in order via the SQL Editor:
### Database

```
supabase/migrations/001_match_faces.sql
supabase/migrations/002_search_photos.sql
supabase/migrations/003_description_embeddings.sql
supabase/migrations/004_match_sessions.sql
supabase/migrations/005_add_face_embedding_unique_constraint.sql
supabase/migrations/006_add_face_embedding_hnsw_index.sql
supabase/migrations/007_match_session_analytics.sql
supabase/migrations/008_drive_file_id_canonical.sql
supabase/migrations/009_sentinel_face_embedding_guard.sql
supabase/migrations/010_phash_dedup.sql
supabase/migrations/011_auto_tags.sql
supabase/migrations/012_allow_null_face_embedding.sql
Create a [Supabase](https://supabase.com) project with the pgvector extension enabled, then run the bootstrap schema:

```sql
-- Paste into Supabase SQL Editor → Run
-- File: supabase/schema.sql
```

These create the `photos` and `face_embeddings` tables, pgvector indexes (HNSW for face embeddings), full-text search with tsvector, RPC functions for similarity search, and match session analytics.
This single file creates all tables, indexes, and RPC functions. It's the consolidated equivalent of the 12 incremental migrations in `supabase/migrations/` — use those if you need to apply changes to an existing deployment.

### 3. Deploy the face-api service (optional)
### Face Matching (Optional)

The InsightFace microservice lives in `services/face-api/`. It's a Flask app that accepts base64 images and returns face embeddings + bounding boxes. Deploy to Railway, Render, or Fly.io:
The InsightFace microservice lives in `services/face-api/`. Deploy to Railway, Render, or Fly.io:

```bash
cd services/face-api
docker build -t face-api .
# Deploy to your platform of choice
```

The service uses InsightFace's `buffalo_l` model (512-dim embeddings). It needs ~2GB RAM and takes 30-60s to cold start while downloading the model.
Uses InsightFace's `buffalo_l` model (512-dim embeddings). Needs ~2GB RAM, 30-60s cold start for model download.

### 4. Configure environment
### Environment

```bash
cp .env.example .env.local
cp .env.example .env
```

Fill in the values:
Expand Down Expand Up @@ -317,7 +300,11 @@ services/face-api/ # InsightFace microservice (Flask + Doc
│ ├── Dockerfile
│ └── requirements.txt
supabase/migrations/ # 12 SQL migrations
scripts/setup.sh # Guided local setup
supabase/
│ ├── schema.sql # Bootstrap: full schema in one file
│ └── migrations/ # 12 incremental migrations
```

---
Expand Down
128 changes: 128 additions & 0 deletions scripts/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/usr/bin/env bash
# EventLens — Local Development Setup
# Usage: ./scripts/setup.sh
#
# This script:
# 1. Checks prerequisites (Node.js, npm)
# 2. Installs dependencies
# 3. Creates .env from .env.example (if needed)
# 4. Validates required environment variables
# 5. Prints next steps (Supabase schema, optional face-api)
#
# @TheTechMargin 2026

set -euo pipefail

# ── Colors ──────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m' # No Color

info() { echo -e "${CYAN}ℹ${NC} $1"; }
success() { echo -e "${GREEN}✓${NC} $1"; }
warn() { echo -e "${YELLOW}⚠${NC} $1"; }
fail() { echo -e "${RED}✗${NC} $1"; }

echo ""
echo -e "${CYAN}╔══════════════════════════════════════╗${NC}"
echo -e "${CYAN}║ EventLens — Setup Script ║${NC}"
echo -e "${CYAN}╚══════════════════════════════════════╝${NC}"
echo ""

# ── Step 1: Prerequisites ──────────────────────────────────────
info "Checking prerequisites..."

if ! command -v node &> /dev/null; then
fail "Node.js is not installed. Install it from https://nodejs.org (v18+)"
exit 1
fi

NODE_VERSION=$(node -v | sed 's/v//' | cut -d. -f1)
if [ "$NODE_VERSION" -lt 18 ]; then
fail "Node.js v18+ required (found v$(node -v))"
exit 1
fi
success "Node.js $(node -v)"

if ! command -v npm &> /dev/null; then
fail "npm is not installed"
exit 1
fi
success "npm $(npm -v)"

# ── Step 2: Install dependencies ───────────────────────────────
info "Installing dependencies..."
npm install --silent
success "Dependencies installed"

# ── Step 3: Environment file ───────────────────────────────────
if [ ! -f .env ]; then
if [ -f .env.example ]; then
cp .env.example .env
warn "Created .env from .env.example — fill in your keys before running"
else
fail ".env.example not found"
exit 1
fi
else
success ".env already exists"
fi

# ── Step 4: Validate required env vars ─────────────────────────
info "Checking environment variables..."

MISSING=()

check_var() {
local val
val=$(grep "^$1=" .env 2>/dev/null | cut -d= -f2-)
if [ -z "$val" ]; then
MISSING+=("$1")
fi
}

check_var "GOOGLE_API_KEY"
check_var "GOOGLE_DRIVE_FOLDER_ID"
check_var "GEMINI_API_KEY"
check_var "NEXT_PUBLIC_SUPABASE_URL"
check_var "SUPABASE_SERVICE_ROLE_KEY"
check_var "APP_PASSWORD"
check_var "ADMIN_API_SECRET"

if [ ${#MISSING[@]} -gt 0 ]; then
warn "Missing environment variables in .env:"
for var in "${MISSING[@]}"; do
echo -e " ${YELLOW}→${NC} $var"
done
echo ""
else
success "All required environment variables set"
fi

# ── Step 5: Next steps ─────────────────────────────────────────
echo ""
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${CYAN} Next Steps${NC}"
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo ""
echo " 1. Fill in any missing .env values"
echo ""
echo " 2. Set up your Supabase database:"
echo " → Go to your Supabase project SQL Editor"
echo " → Paste and run: supabase/schema.sql"
echo " (This creates all tables, indexes, and functions)"
echo ""
echo " 3. Start the dev server:"
echo " npm run dev"
echo ""
echo " 4. Open the admin panel to run the pipeline:"
echo " http://localhost:3000/admin"
echo ""
echo -e " ${YELLOW}Optional:${NC} Face matching"
echo " → Deploy services/face-api/ to Railway/Render"
echo " → Set FACE_API_URL and FACE_API_SECRET in .env"
echo ""
echo -e "${GREEN}Setup complete!${NC}"
echo ""
Loading
Loading