This guide will walk you through setting up Supabase for your Shelf.nu application. Supabase provides our database, authentication, and file storage.
- A Supabase account (free tier available)
- Access to your
.envfile in your local Shelf.nu project
-
Sign up/Login to Supabase
-
Click "New Project"
-
Choose your organization (or create one)
-
Fill in project details:
- Name:
shelf-nu(or your preferred name) - Database Password: Create a strong password (save this! 🔐)
- Region: Choose closest to your location
- Pricing Plan: Free tier works great for development
- Name:
-
Click "Create new project"
-
⏳ Wait for your project to be ready (usually 1-2 minutes)
- Click the "Connect" button in your project header
- Select "ORM" → "Prisma"
- Copy the connection strings and update your
.env(replace[YOUR-PASSWORD]with your actual database password):
# Connection pooling (for app runtime)
DATABASE_URL="postgres://postgres.xxxxx:[YOUR-PASSWORD]@xxx.pooler.supabase.com:6543/postgres?pgbouncer=true"
# Direct connection (for migrations)
DIRECT_URL="postgres://postgres.xxxxx:[YOUR-PASSWORD]@xxx.supabase.com:5432/postgres"💡 Important: Replace
[YOUR-PASSWORD]with your actual database password
- Go to Project Settings → API keys
- Copy the API keys and update your
.env:
SUPABASE_URL="https://your-project-ref.supabase.co"
SUPABASE_ANON_PUBLIC="your-anon-public-key"
SUPABASE_SERVICE_ROLE="your-service-role-key"- Go to Project Settings → Database
- Find "Connection pooling" section
- Set Mode to "Transaction"
- Click "Save"
- Go to Authentication → URL Configuration
- Site URL: Set to
https://localhost:3000(for development with SSL) orhttp://localhost:3000(without SSL) - Redirect URLs: Add these URLs:
https://localhost:3000/reset-password http://localhost:3000/reset-password https://your-staging-domain.com/reset-password https://your-live-domain.com/reset-password
💡 Note: Include both HTTP and HTTPS localhost URLs to support different SSL configurations
Shelf uses One-Time Passwords (OTP) instead of magic links. Update the email templates:
- Go to Authentication → Email Templates
- Update each template with the content below:
📧 Confirm Signup Template (click to expand)
Replace the entire email content with:
<p>
To confirm your account, please use the following One Time Password (OTP):
</p>
<h2><b>{{ .Token }}</b></h2>
<p>
Don't share this OTP with anyone. Our customer service team will never ask you
for your password, OTP, credit card, or banking info. We hope to see you again
soon.
</p>🔐 Magic Link Template (click to expand)
Replace the entire email content with:
<p>To authenticate, please use the following One Time Password (OTP):</p>
<h2><b>{{ .Token }}</b></h2>
<p>
Don't share this OTP with anyone. Our customer service team will never ask you
for your password, OTP, credit card, or banking info. We hope to see you again
soon.
</p>🔄 Reset Password Template (click to expand)
Replace the entire email content with:
<h2>Reset Password</h2>
<p>To reset your password, please use the following (OTP):</p>
<h2><b>{{ .Token }}</b></h2>
<p>
Don't share this OTP with anyone. Our customer service team will never ask you
for your password, OTP, credit card, or banking info. We hope to see you again
soon.
</p>- Click "Save" for each template after updating
Shelf needs several storage buckets for file uploads. For each bucket below:
- Go to Storage → Buckets
- Click "Create bucket"
- Name:
profile-pictures - Make it public: ✅ Checked
- Click "Create"
Setup Policies:
- Click on the bucket → Policies
- Create policy for INSERT, UPDATE, DELETE with:
- Expression:
(bucket_id = 'profile-pictures'::text) AND (false) - Target roles:
authenticatedandanon
- Expression:
- Create bucket:
assets - Public: ❌ Unchecked
- Policies: Same as above but with
(bucket_id = 'assets'::text) AND (false)
- Create bucket:
kits - Public: ❌ Unchecked
- Policies: Same as above but with
(bucket_id = 'kits'::text) AND (false)
- Create bucket:
files - Public: ✅ Checked
- Policies: Same as above but with
(bucket_id = 'files'::text) AND (false)
💡 Why these policies? They prevent direct browser access to modify files while allowing our server to manage them securely.
Your .env should now look like this:
# Database connections
DATABASE_URL="postgres://postgres.xxxxx:[YOUR-PASSWORD]@xxx.pooler.supabase.com:6543/postgres?pgbouncer=true"
DIRECT_URL="postgres://postgres.xxxxx:[YOUR-PASSWORD]@xxx.supabase.com:5432/postgres"
# Supabase API
SUPABASE_URL="https://your-project-ref.supabase.co"
SUPABASE_ANON_PUBLIC="your-anon-public-key"
SUPABASE_SERVICE_ROLE="your-service-role-key"
# App configuration
SESSION_SECRET="your-super-secret-session-key"
SERVER_URL="https://localhost:3000" # With SSL (recommended)
# SERVER_URL="http://localhost:3000" # Without SSL
FINGERPRINT="a-custom-host-fingerprint"
# Features (optional - set to false to disable premium features)
ENABLE_PREMIUM_FEATURES="false"
# Email configuration (required for auth emails)
SMTP_HOST="smtp.yourhost.com"
SMTP_PORT=465
SMTP_USER="you@example.com"
SMTP_PWD="yourSMTPpassword"
SMTP_FROM="You from Shelf.nu <you@example.com>"
# Map integration (optional)
MAPTILER_TOKEN="your-maptiler-token"
GEOCODING_USER_AGENT="Your App Name (https://yoursite.com)"
# Security
INVITE_TOKEN_SECRET="your-invite-token-secret"
# Analytics (optional)
MICROSOFT_CLARITY_ID="your-clarity-id"Generate secure random strings for your secrets:
# Generate session secret
openssl rand -hex 32
# Generate invite token secret
openssl rand -hex 32
# Generate fingerprint
openssl rand -hex 32Copy these values to your .env file.
Shelf requires email configuration for user authentication. You can use:
- Gmail: Use app passwords
- SendGrid: Free tier available
- Mailgun: Free tier available
- Any SMTP provider
Update the SMTP settings in your .env file with your email provider's details.
Get a free MapTiler account for location features:
- Sign up at MapTiler
- Get your API key
- Add to your
.envfile:
MAPTILER_TOKEN="your_token_here"Shelf.nu uses OpenStreetMap Nominatim for geocoding addresses into map coordinates. This is a free service that requires no API key or registration.
Configuration:
- Set
GEOCODING_USER_AGENTenvironment variable to identify your deployment - Example:
GEOCODING_USER_AGENT="My Company Assets (https://assets.mycompany.com)" - Defaults to "Self-hosted Asset Management System" if not set
How it works:
- When you add an address to a location, it's automatically geocoded and cached in the database
- Subsequent page loads use the cached coordinates for instant map display
- Rate limit: 1 request per second (automatically handled)
Important limitations:
- Nominatim has usage policies you should be aware of
- For heavy usage, consider running your own Nominatim instance
- The service runs on donated servers with limited capacity
For production deployments with high geocoding volume:
- Consider commercial alternatives like MapBox, Google Maps, or MapTiler geocoding APIs
- Set up your own Nominatim server following the installation guide
Your Supabase setup is complete! You should now have:
- ✅ Supabase project created
- ✅ Database connection strings in
.env - ✅ API keys in
.env - ✅ Connection mode set to "Transaction"
- ✅ Auth templates configured for OTP
- ✅ Storage buckets created with policies
- ✅ Email configuration completed
- ✅ Session secrets generated
Now you can return to the main setup and run:
npm run setup
npm run devWith SSL: Your Shelf.nu app will be available at https://localhost:3000 🔒
Without SSL: Your Shelf.nu app will be available at http://localhost:3000 🎉
Your app should connect to Supabase successfully!
Connection Error: Double-check your database password and connection strings
Auth Not Working: Verify email templates use the escaped token syntax instead of URLs
File Upload Fails: Ensure storage buckets exist and have proper policies
Email Issues: Test your SMTP settings with a simple email client first
This guide covers development setup. For production deployment, see our Deployment Guide.