Browse by type
A modern photography portfolio website built with Next.js 16, featuring interactive maps, photo management, and a comprehensive dashboard.
Home Page
Dashboard
Before deploying, ensure you have:
# Clone the repository
git clone https://github.com/ECarry/photography-website.git
cd photography-website
# Install dependencies
bun install
# or
npm install
Create a .env file in the root directory:
cp .env.example .env
Configure the following environment variables:
# PostgreSQL connection string
DATABASE_URL=postgresql://username:password@host:port/database_name?sslmode=require
For Neon Database:
For Supabase:
# Generate a random secret key (32+ characters)
BETTER_AUTH_SECRET=your-super-secret-key-here
# Your app's base URL
BETTER_AUTH_URL=https://your-domain.com
NEXT_PUBLIC_APP_URL=https://your-domain.com
# S3-compatible storage settings
S3_ENDPOINT=https://your-s3-endpoint.com
S3_BUCKET_NAME=your-bucket-name
S3_PUBLIC_URL=https://your-custom-domain.com
S3_ACCESS_KEY_ID=your-access-key
S3_SECRET_ACCESS_KEY=your-secret-key
NEXT_PUBLIC_S3_PUBLIC_URL=https://your-custom-domain.com
Supported Storage Providers:
Cloudflare R2:
S3_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com
S3_BUCKET_NAME=your-bucket-name
NEXT_PUBLIC_S3_PUBLIC_URL=https://your-custom-domain.com
AWS S3:
S3_ENDPOINT=https://s3.amazonaws.com
S3_BUCKET_NAME=your-aws-bucket
NEXT_PUBLIC_S3_PUBLIC_URL=https://your-bucket.s3.amazonaws.com
DigitalOcean Spaces:
S3_ENDPOINT=https://nyc3.digitaloceanspaces.com
S3_BUCKET_NAME=your-space-name
NEXT_PUBLIC_S3_PUBLIC_URL=https://your-space.nyc3.digitaloceanspaces.com
MinIO (Self-hosted):
S3_ENDPOINT=http://localhost:9000
S3_BUCKET_NAME=your-minio-bucket
NEXT_PUBLIC_S3_PUBLIC_URL=http://localhost:9000/your-bucket
Wasabi:
S3_ENDPOINT=https://s3.wasabisys.com
S3_BUCKET_NAME=your-wasabi-bucket
NEXT_PUBLIC_S3_PUBLIC_URL=https://your-bucket.s3.wasabisys.com
If you are not using Cloudflare R2 (or you don’t want to use the Cloudflare-specific custom image loader), make sure to remove or update the following in next.config.*:
loader: 'custom',
loaderFile: './src/lib/cloudflare-image-loader.ts',
Otherwise, Next.js image optimization/loading may fail locally or in production.
Setup Instructions:
# Mapbox access token
NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN=pk.your-mapbox-token
Get Mapbox Token:
# Default admin user for seeding
SEED_USER_EMAIL=admin@yourdomain.com
SEED_USER_PASSWORD=your-secure-password
SEED_USER_NAME=Admin User
# Push database schema
bun run db:push
# Create admin user
bun run seed:user
# Build the application
bun run build
# Test the production build locally
bun run start
Visit http://localhost:3000 to verify everything works correctly.
# Install Vercel CLI
npm i -g vercel
# Login to Vercel
vercel login
# Deploy
vercel --prod
In your Vercel dashboard, add all environment variables from your .env file:
# If you need to run migrations on production
vercel env pull .env.local
bun run db:push
# Seed admin user in production
vercel env pull .env.local
bun run seed:user
Change Summary
The database url field now stores the S3 object key (e.g., photos/IMG_0001.jpg) instead of a full public URL.
Benefit: You can switch domains or CDNs freely by updating environment variables for the public base URL, without mass-updating the database.
Migration Steps (run before production, recommended)
Backup your database (strongly recommended).
bash
bun run clean:photo-urlsurl should look like a key such as path/to/object.jpg.If you need to rollback, run:
bash
bun run rollback:photo-urls
Notes
S3_PUBLIC_URL or NEXT_PUBLIC_S3_PUBLIC_URL. At runtime, the app combines this base URL with the key to form a full public URL.This project supports two Docker deployment modes: Standalone (self-hosted) and Cloud (managed services).
Run the entire stack (App, PostgreSQL, RustFS) locally. Ideal for testing and self-hosting.
docker compose up -d
# or explicitly:
docker compose -f docker-compose.standalone.yml up -d
Run only the App container, connecting to external services (e.g., Neon Postgres, AWS S3, Cloudflare R2).
.env file with your credentials:
bash
DATABASE_PROVIDER=cloud
DATABASE_URL="postgres://..."
BETTER_AUTH_SECRET="..."
S3_ACCESS_KEY_ID="..."
S3_SECRET_ACCESS_KEY="..."
S3_BUCKET_NAME="..."
S3_ENDPOINT="..." # Optional
S3_PUBLIC_URL="..."bash
docker compose -f docker-compose.cloud.yml up -dThis project uses a Runtime Build strategy for Docker. The Next.js application is built inside the container when it starts, not when the Docker image is built. This ensures that Static Site Generation (SSG) can successfully fetch data from the database (which is only available at runtime in the Standalone mode).
next_cache volume).Vercel Custom Domain:
Go to Project Settings > Domains
Configure DNS records as instructed
Update Environment Variables:
env
BETTER_AUTH_URL=https://your-custom-domain.com
NEXT_PUBLIC_APP_URL=https://your-custom-domain.com
bash
npm install @vercel/analytics
Environment Variables:
Never commit .env files
Rotate keys regularly
Database Security:
Use connection pooling
Restrict database access by IP
File Upload Security:
The application is fully responsive and optimized for mobile devices:
# Clear Next.js cache
rm -rf .next
# Reinstall dependencies
rm -rf node_modules
bun install
DATABASE_URL is correctIf you find this project helpful, please give it a ⭐️ on GitHub!
This project is licensed under the MIT License - see the LICENSE file for details.
Need help? Check the troubleshooting section above or open an issue in the repository.
browse all types & interfaces →
$ claude mcp add photography-website \
-- python -m otcore.mcp_server <graph>