SAPAA Web Application Deployment Documentation
Table of Contents
- Overview
- Prerequisites
- Required Services and API Keys
- Environment Variables
- Local Development Setup
- Deploying to Vercel
- Database Setup
- Post-Deployment Configuration
- Security Checklist
- Troubleshooting
- API Documentation
- Required Libraries and Dependencies
- Maintenance and Updates
Overview
The SAPAA Web Application is a Next.js application that provides a web interface for stewards and administrators to view and manage protected area inspection data. The application uses:
- Next.js - React framework with App Router
- Supabase - Database and authentication service
- AWS S3 - Image storage
- Vercel - Deployment platform
Deployed URL: https://w26-project-sapaa-dev-team.vercel.app/
Prerequisites
Before deploying the application, ensure you have:
- Node.js (version 20.x or higher)
- Download from nodejs.org
-
Verify installation:
node --version -
npm (comes with Node.js)
-
Verify installation:
npm --version -
Git (for cloning the repository)
- Download from git-scm.com
-
Verify installation:
git --version -
Vercel Account (free tier available)
-
Sign up at vercel.com
-
Supabase Account (free tier available)
-
Sign up at supabase.com
-
AWS Account (for S3 image storage)
- Sign up at aws.amazon.com
Required Services and API Keys
1. Supabase Setup
The application requires a Supabase project for authentication and database access.
Creating a Supabase Project
- Go to supabase.com and sign in
- Click "New Project"
- Fill in:
- Project Name:
sapaa-webapp(or your preferred name) - Database Password: Choose a strong password (save this securely)
- Region: Select the closest region to your users
- Click "Create new project"
- Wait for the project to be provisioned (2–3 minutes)
Getting Supabase Credentials
- In your Supabase project dashboard, go to Settings → API
- You will need the following values:
- Project URL: found under "Project URL"
- anon/public key: found under "Project API keys" →
anon public - service_role key: found under "Project API keys" →
service_role— KEEP THIS SECRET
Required Database Tables
The application expects the following tables/views in your Supabase database:
W26_sites-pa— Main list of protected sitesW26_answers— Answers to inspection reports questionsW26_attachments— holds links to external content types (like Images or Inaturalist)W26_form_sections— Inspection section recordsW26_form_reponses— Inspection detail recordsW26_questions— Inspection question definitions
2. AWS S3 Setup
The application uses AWS S3 for storing and serving images uploaded through the inspection workflow.
Creating an S3 Bucket
- Log in to the AWS Management Console
- Navigate to S3 and click "Create bucket"
- Configure the bucket:
- Bucket name: Choose a globally unique name (e.g.,
sapaa-inspection-images) - Region: Select the closest region to your users
- Block Public Access: Configure according to your access requirements (see CORS below)
- Click "Create bucket"
Configuring CORS
In your S3 bucket settings, go to Permissions → CORS and add:
[
{
"AllowedHeaders": ["*"],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
"AllowedOrigins": ["https://your-vercel-url.vercel.app"],
"ExposeHeaders": []
}
]
Creating an IAM User
- Navigate to IAM → Users → Create user
- Attach a policy granting access to your S3 bucket. Example policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject", "s3:DeleteObject"],
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
}
- Go to the user's Security credentials tab and click "Create access key"
- Save the Access Key ID and Secret Access Key securely
Environment Variables
The application requires the following environment variables.
Required Variables
| Variable Name | Description | Where to Get It |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Your Supabase project URL | Supabase Dashboard → Settings → API |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY |
Supabase anon/public key | Supabase Dashboard → Settings → API → anon public |
SUPABASE_SECRET |
Supabase service role key (server-side only) | Supabase Dashboard → Settings → API → service_role |
AWS_ACCESS_KEY_ID |
AWS IAM access key ID | AWS IAM → Users → Security credentials |
AWS_SECRET_ACCESS_KEY |
AWS IAM secret access key | AWS IAM → Users → Security credentials |
AWS_REGION |
AWS region of your S3 bucket | AWS S3 bucket settings |
AWS_S3_BUCKET |
S3 bucket name | AWS S3 console |
Environment Variable Format
Create a .env.local file in the webapp directory for local development:
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your_supabase_publishable_key
SUPABASE_SECRET=your_supabase_secret
AWS_ACCESS_KEY_ID=your_aws_access_key
AWS_SECRET_ACCESS_KEY=your_aws_secret_key
AWS_REGION=your_region
AWS_S3_BUCKET=your_bucket_name
Important:
- Never commit .env.local to version control
- The .env.local file is already in .gitignore
- SUPABASE_SECRET and all AWS_* keys are server-side only — never prefix them with NEXT_PUBLIC_
- For Vercel deployment, add these variables in the Vercel dashboard (see below)
Local Development Setup
Step 1: Clone the Repository
git clone https://github.com/SAPAA-Dev/W26Project-SAPAA-Dev-Team.git
cd webapp
Step 2: Install Dependencies
npm install
This will install all required packages listed in package.json.
Step 3: Configure Environment Variables
- Create a
.env.localfile in thewebappdirectory:
# On Mac/Linux
touch .env.local
# On Windows (PowerShell)
New-Item -Path .env.local -ItemType File
- Add your environment variables to
.env.localusing the format from the Environment Variables section above.
Step 4: Run the Development Server
npm run dev
The application will start on http://localhost:3000.
Step 5: Verify Installation
- Open http://localhost:3000 in your browser
- You should see the login page
- If you see errors, check:
- All environment variables are set correctly
- Supabase project is active
- Database tables are created
- AWS S3 bucket exists and IAM credentials are valid
Available Scripts
| Command | Description |
|---|---|
npm run dev |
Start development server on port 3000 |
npm run build |
Build production bundle |
npm run start |
Start production server (after build) |
npm run lint |
Run ESLint to check code quality |
npm test |
Run Jest test suite |
Deploying to Vercel
Vercel is the recommended deployment platform for Next.js applications. It provides automatic deployments, SSL certificates, and global CDN.
Option 1: Deploy via Vercel CLI
Step 1: Install Vercel CLI
npm install -g vercel
Step 2: Login to Vercel
vercel login
Step 3: Link Your Project
cd webapp
vercel link
Step 4: Configure Environment Variables
- Go to vercel.com/dashboard
- Select your project
- Go to Settings → Environment Variables
- Add all variables from the Environment Variables section
- Enable each variable for Production, Preview, and Development
- Click Save
Step 5: Deploy
vercel --prod
Or push to your main branch if you have connected a Git repository:
git push origin main
Option 2: Deploy via Vercel Dashboard (Web Interface)
- Go to vercel.com/new
- Import your Git repository:
W26Project-SAPAA-Dev-Team - Configure the project:
- Framework Preset: Next.js (auto-detected)
- Root Directory:
webapp - Build Command:
npm run build - Output Directory:
.next - Add all environment variables from the Environment Variables section
- Click Deploy
Vercel will automatically install dependencies, build the project, and deploy to a live URL.
CI/CD
Vercel provides built-in CI/CD through GitHub integration — no GitHub Actions required.
- Push to
mainbranch → triggers production deployment - Pull requests → creates preview deployments
Post-Deployment
After deployment, your app will be available at https://your-project-name.vercel.app. Test by visiting the login page, verifying authentication, checking that data loads, and confirming image uploads work.
Database Setup
Creating Database Tables
- Log into your Supabase Dashboard
- Go to SQL Editor
- Run the SQL scripts provided by your development team to create the required tables and views:
- Tables: -
W26_sites-pa,W26_answers,W26_attachments,W26_form_sections,W26_form_reponses,W26_questions
Note: Contact your development team for the complete SQL schema.
Setting Up Row Level Security (RLS)
- Go to Authentication → Policies in Supabase
- Create policies for each table to allow:
- Authenticated users to read data
- Admins to read/write data
Example Policy:
-- Allow authenticated users to read sites
CREATE POLICY "Allow authenticated users to read sites"
ON sites_list_fnr
FOR SELECT
TO authenticated
USING (true);
User Roles Setup
The application uses Supabase Auth user_metadata to store user roles in the user_metadata.role field.
How Roles Work:
- Default role: steward (assigned automatically if no role is set)
- Admin role: admin (must be set manually)
Setting Admin Role:
- Go to Supabase Dashboard → Authentication → Users
- Click the user you want to make an admin
- In the Raw User Meta Data section, add or update:
json { "role": "admin" } - Click Save
Note: New users created through the signup page default to steward. Only admins can change user roles through the Account Management interface.
User Authorization
The application uses Supabase Auth user_metadata to also store user authorization status in the user_metadata.authenicated field.
How Authorization Works:
- Upon account creation authorization is set to: False (assigned automatically as admin aproval is required for application access)
- Upon admin aproval of account the value is then set to: True (Indicating an admin has allowed you access to the application)
Setting Authorization Status:
- Go to Admin Dashbaord
- Proceed to Account Management
- Click the user you want to Authorize
- Toggle their approval status to: Approved
- Click Save
Note: New users created through the signup page default to False. Only admins can change user authorization status through the account management interface.
Post-Deployment Configuration
1. Verify Environment Variables
- Go to Vercel Dashboard → Your Project → Settings → Environment Variables
- Ensure all 7 required variables are present and enabled for Production
2. Configure Supabase Redirect URLs
- Go to Supabase Dashboard → Authentication → URL Configuration
- Add your Vercel URL to Redirect URLs:
https://your-project-name.vercel.app/auth/callbackhttps://your-project-name.vercel.app/auth/confirm- Set Site URL to:
https://your-project-name.vercel.app
3. Test Authentication
- Visit your deployed URL
- Verify login, signup, session persistence, and logout all work correctly
4. Test Database Connection
- Log in to the application
- Navigate to the Protected Areas page
- Verify sites load correctly and check the browser console for errors
5. Test Image Upload (S3)
- Log in and navigate to a page with image upload functionality
- Upload a test image and verify it appears correctly
- Check the browser console and network tab for any S3-related errors
6. Test Admin Features
- Log in with an admin account
- Verify the Admin Dashboard loads, charts display data, and heatmap search works
7. Test API Endpoints (See API Documentation)
# Example Test on geocoding
curl https://your-project-name.vercel.app/api/geocode?q=Alberta
Security Checklist
Before going to production, ensure:
- [ ] All environment variables are set in Vercel — not hardcoded in source
- [ ]
SUPABASE_SECRETand allAWS_*keys are never exposed to client-side code - [ ] Debug/test credentials are removed
- [ ] Default passwords are changed
- [ ] Row Level Security (RLS) is enabled on all Supabase tables
- [ ] S3 bucket CORS policy is restricted to your deployed domain
- [ ] S3 IAM policy follows least-privilege (only required actions granted)
- [ ] SSL/HTTPS is enabled (automatic with Vercel)
- [ ] API rate limiting is configured if needed
- [ ] Error messages don't expose sensitive information
- [ ] Authentication is required for all protected routes
- [ ] Admin routes are properly protected
- [ ] No
console.logstatements with sensitive data in production - [ ]
.env.localis never committed to version control (verify.gitignore)
Troubleshooting
Issue: "Unable to connect to Supabase"
Symptoms: Login fails, sites don't load, Supabase connection errors.
Solutions:
1. Verify NEXT_PUBLIC_SUPABASE_URL is correct
2. Check Supabase project is active (not paused)
3. Check status.supabase.com
Issue: "Authentication not working"
Symptoms: Users can't log in, redirect loops, "Invalid credentials" errors.
Solutions:
1. Verify Supabase redirect URLs are configured (see Post-Deployment Configuration)
2. Check NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY is correct
3. Verify Supabase Auth is enabled in your project
Issue: "No sites found" or empty data
Symptoms: Protected Areas page shows no sites, dashboard shows zero statistics.
Solutions:
1. Verify database tables exist and contain data
2. Check RLS policies allow read access for authenticated users
3. Verify SUPABASE_SECRET is set correctly for server-side queries
Issue: "S3 uploads failing"
Symptoms: Image uploads fail or images don't appear after upload.
Solutions:
1. Verify all four AWS_* environment variables are set correctly in Vercel
2. Check IAM policy grants s3:PutObject, s3:GetObject, and s3:DeleteObject on your bucket
3. Verify the bucket CORS configuration allows requests from your Vercel domain
4. Check browser console and network tab for specific error codes
Issue: "Build fails on Vercel"
Symptoms: Deployment fails during build, build logs show errors.
Solutions:
1. Check build logs in the Vercel dashboard
2. Verify all dependencies are listed in package.json
3. Run npm run build locally first to reproduce and debug the error
Issue: "App builds but fails at runtime" or blank page after deploy
Symptoms: Blank page, runtime errors in browser console.
Solutions:
1. Check environment variables are set in Vercel (not just .env.local)
2. Ensure variables are enabled for the Production environment
3. Redeploy after adding or changing variables
4. Check browser console for specific errors
Getting Help
If you encounter issues not covered here:
- Check Vercel deployment logs
- Check Supabase logs (Dashboard → Logs)
- Review browser console for client-side errors
- Check the network tab for failed API requests
- Contact your development team with error messages, steps to reproduce, browser/OS information, and screenshots
API Documentation
The full interactive API reference is available at /api-docs on your deployed instance (OpenAPI 3.0 / Swagger UI).
All endpoints are served from the base URL https://your-project-name.vercel.app (or http://localhost:3000 for local development).
Inspection Gallery
1. Get All Inspection Gallery Images
Endpoint: GET /api/gallery
Description: Returns all uploaded inspection image attachments with metadata and signed S3 URLs. Admin only.
Authentication: Required — Admin role
Query Parameters: None
Response 200:
{
"items": [
{
"id": 14,
"response_id": 3226,
"question_id": 27,
"caption": "Cross Country ski trails",
"identifier": "Ski Trails",
"date": "2026-01-31",
"storage_key": "inspections/207/3226/27/Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-aa05346a.jpg",
"content_type": "image/jpeg",
"file_size_bytes": 506701,
"filename": "Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-aa05346a.jpg",
"site_id": 207,
"site_name": "Riverlot 56 (NA)",
"imageUrl": "https://sapaa-inspection-images.s3.ca-central-1.amazonaws.com/..."
}
]
}
| Status | Description |
|---|---|
200 |
Gallery items returned successfully |
401 |
Unauthorized |
403 |
Forbidden — admin access required |
500 |
Failed to load gallery |
2. Get Inspection Images by Site or Response
Endpoint: GET /api/site-images
Description: Returns uploaded image attachments filtered by site ID and/or response ID. At least one query parameter must be provided.
Authentication: Required
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
siteid |
integer | No* | Filter images by site ID |
responseid |
integer | No* | Filter images by response ID |
*At least one of siteid or responseid must be provided.
Example Request:
GET /api/site-images?siteid=207
GET /api/site-images?responseid=3235
GET /api/site-images?siteid=207&responseid=3235
Response 200:
{
"items": [
{
"id": 14,
"response_id": 3235,
"question_id": 27,
"storage_key": "inspections/207/3235/27/Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-aa05346a.jpg",
"filename": "Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-aa05346a.jpg",
"content_type": "image/jpeg",
"file_size_bytes": 506701,
"caption": "Cross Country ski trails",
"identifier": "Ski Trails",
"site_id": 207,
"imageUrl": "https://sapaa-inspection-images.s3.ca-central-1.amazonaws.com/..."
}
]
}
| Status | Description |
|---|---|
200 |
Site images returned successfully |
400 |
Provide at least one of: siteid, responseid |
401 |
Unauthorized |
500 |
Failed to fetch site images |
3. Get Gallery Images for a Specific Site
Endpoint: GET /api/sites/{siteId}/gallery
Description: Returns image attachments for a specific site including signed S3 URLs. Requires authentication.
Authentication: Required
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
siteId |
integer | Yes | Site ID |
Example Request:
GET /api/sites/207/gallery
Response 200:
{
"items": [
{
"id": 14,
"caption": "Cross Country ski trails",
"identifier": "Ski Trails",
"filename": "Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-aa05346a.jpg",
"file_size_bytes": 506701,
"site_name": "Riverlot 56 (NA)",
"response_id": 3235,
"imageUrl": "https://sapaa-inspection-images.s3.ca-central-1.amazonaws.com/..."
}
]
}
| Status | Description |
|---|---|
200 |
Gallery items returned successfully |
400 |
Invalid site ID |
401 |
Unauthorized |
500 |
Failed to load gallery |
Homepage Image Gallery
4. Get All Homepage Image Uploads
Endpoint: GET /api/homepage-images
Description: Returns all homepage image uploads with metadata and signed S3 URLs. Admin only.
Authentication: Required — Admin role
Query Parameters: None
Response 200:
{
"items": [
{
"id": 16,
"site_id": 207,
"site_name": "Riverlot 56 (NA)",
"date": "2026-01-31",
"photographer": "Raiyana Rahman",
"caption": "Cross Country ski trails",
"identifier": "Ski Trails",
"filename": "Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-0642088a-b29f-400a-9ce7-e1003fa1e928.jpg",
"file_size_bytes": 506701,
"storage_key": "homepage-image-uploads/207/6966742d-b9e7-46c1-842f-030d4a97ba39/Riverlot56NA-...",
"imageUrl": "https://sapaa-inspection-images.s3.ca-central-1.amazonaws.com/homepage-image-uploads/..."
}
]
}
| Status | Description |
|---|---|
200 |
Homepage images returned successfully |
401 |
Unauthorized |
403 |
Forbidden — admin access required |
500 |
Failed to load images |
5. Get Homepage Image Uploads for a Specific Site
Endpoint: GET /api/homepage-images/{siteId}
Description: Returns homepage image uploads for a specific site including metadata and signed S3 URLs. Admin only.
Authentication: Required — Admin role
Path Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
siteId |
integer | Yes | Site ID |
Example Request:
GET /api/homepage-images/207
Response 200: Returns the same HomepageImageItem schema as above, scoped to the given site.
| Status | Description |
|---|---|
200 |
Homepage images for site returned successfully |
400 |
Invalid site ID |
401 |
Unauthorized |
500 |
Failed to load images |
Uploads
6. Generate Presigned S3 URL for Inspection Images
Endpoint: POST /api/s3/presign
Description: Generates a short-lived presigned S3 URL for uploading an inspection image attachment and returns the generated SAPAA-standardized filename.
Authentication: Required
Request Body (application/json):
{
"filename": "tree-photo.jpg",
"contentType": "image/jpeg",
"fileSize": 245678,
"responseId": 3226,
"questionId": 27,
"siteId": 207,
"siteName": "Riverlot 56 (NA)",
"date": "2026-01-31",
"photographer": "Raiyana Rahman",
"identifier": "Ski Trails"
}
Response 200:
{
"uploadUrl": "https://example-bucket.s3.amazonaws.com/...",
"key": "inspections/207/3226/27/Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-aa05346a.jpg",
"generatedFilename": "Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-aa05346a.jpg"
}
| Status | Description |
|---|---|
200 |
Presigned upload URL generated successfully |
400 |
Invalid file data, missing IDs or metadata, unsupported file type, or file too large |
401 |
Unauthorized |
500 |
Failed to generate upload URL |
7. Generate Presigned S3 URL for Homepage Images
Endpoint: POST /api/s3/presign-homepage-images
Description: Generates a short-lived presigned S3 URL for uploading a homepage image using standardized SAPAA filename metadata.
Authentication: Required
Request Body (application/json):
{
"contentType": "image/jpeg",
"fileSize": 688724,
"siteId": 207,
"siteName": "Riverlot 56 (NA)",
"date": "2026-01-31",
"photographer": "Zoe Prefontaine",
"identifier": "Broken Tree Trunk"
}
Response 200:
{
"uploadUrl": "https://example-bucket.s3.amazonaws.com/...",
"key": "homepage-image-uploads/207/user-id/Riverlot56NA-2026-01-31-ZoePrefontaine-BrokenTreeTrunk-f6f399ce-3521-4fa4-987a-43cf356c693b.jpg"
}
| Status | Description |
|---|---|
200 |
Presigned upload URL generated successfully |
400 |
Invalid file data, missing metadata, unsupported type, or file too large |
401 |
Unauthorized |
500 |
Failed to generate upload URL |
User Gallery
8. Get All Homepage Image Uploads (User)
Endpoint: GET /api/user-gallery/homepage-upload
Description: Returns all homepage image uploads with metadata and signed S3 URLs, ordered by date descending. Requires authentication.
Authentication: Required
Query Parameters: None
Response 200: Returns the same HomepageImageItem schema as endpoint 4, available to all authenticated users.
| Status | Description |
|---|---|
200 |
Homepage images returned successfully |
401 |
Unauthorized |
500 |
Failed to load images |
9. Get All Inspection Image Attachments (User)
Endpoint: GET /api/user-gallery/sir-upload
Description: Returns all inspection image attachments (JPEG, PNG, WebP) across all sites, with resolved site names and signed S3 URLs. Ordered by ID descending. Requires authentication.
Authentication: Required
Query Parameters: None
Response 200:
{
"items": [
{
"id": 14,
"response_id": 3226,
"question_id": 27,
"caption": "Cross Country ski trails",
"identifier": "Ski Trails",
"date": "2026-01-31",
"storage_key": "inspections/207/3226/27/Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-aa05346a.jpg",
"content_type": "image/jpeg",
"file_size_bytes": 506701,
"filename": "Riverlot56NA-2026-01-31-RaiyanaRahman-SkiTrails-aa05346a.jpg",
"site_id": 207,
"site_name": "Riverlot 56 (NA)",
"imageUrl": "https://sapaa-inspection-images.s3.ca-central-1.amazonaws.com/..."
}
]
}
| Status | Description |
|---|---|
200 |
Gallery items returned successfully |
401 |
Unauthorized |
500 |
Failed to load gallery |
PDF Export
10. Generate PDF Inspection Report
Endpoint: POST /api/pdf
Description: Generates PDF inspection reports in single, site, or multi-site mode. Admin only.
Authentication: Required — Admin role
Request Body (application/json):
{
"mode": "single",
"responseId": 3235,
"options": {
"includeImages": false,
"maxImagesPerInspection": 5,
"includeEmptyAnswers": false,
"includeCoverPage": true,
"includeNaturalnessSummary": true,
"selectedSections": "all",
"sortOrder": "newest",
"pageSize": "LETTER"
}
}
Request Body Fields:
| Field | Type | Description |
|---|---|---|
mode |
string | Report mode: single, site, or multi-site |
responseId |
integer | Required when mode is single |
options.includeImages |
boolean | Include images in PDF (default: false) |
options.maxImagesPerInspection |
integer | Max images per inspection, 0–20 (default: 5) |
options.includeEmptyAnswers |
boolean | Include unanswered questions (default: false) |
options.includeCoverPage |
boolean | Include a cover page (default: true) |
options.includeNaturalnessSummary |
boolean | Include naturalness summary section (default: true) |
options.selectedSections |
string | all or custom (default: all) |
options.sortOrder |
string | newest or oldest (default: newest) |
options.pageSize |
string | LETTER or A4 (default: LETTER) |
Response 200: Returns the generated PDF as application/pdf.
| Status | Description |
|---|---|
200 |
PDF generated successfully (application/pdf) |
401 |
Unauthorized |
403 |
Forbidden — admin access required |
500 |
Failed to generate PDF |
Utility Endpoints
11. Geocoding API
Endpoint: GET /api/geocode
Description: Geocodes a location name to coordinates using the OpenCage API.
Authentication: Required
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
q |
string | Yes | Location name to geocode |
Example Request:
GET /api/geocode?q=Elk Island Provincial Park
Response 200:
{
"latitude": 53.5731,
"longitude": -112.8583
}
| Status | Description |
|---|---|
200 |
Coordinates returned successfully |
400 |
Missing q parameter |
500 |
Geocoding failed |
Rate Limits: Limited by OpenCage API quota (2,500 requests/day on free tier).
12. Heatmap API
Endpoint: GET /api/heatmap
Description: Searches for sites matching a keyword and returns visit counts for heatmap visualization.
Authentication: Required
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
keyword |
string | No | Search term to match against site names |
Example Request:
GET /api/heatmap?keyword=park
Response 200:
{
"data": [
{ "namesite": "Elk Island Provincial Park", "count": 15 },
{ "namesite": "Writing-on-Stone Provincial Park", "count": 12 }
]
}
| Status | Description |
|---|---|
200 |
Site data returned successfully |
400 |
Invalid query or database error |
500 |
Database query failed |
Authentication Endpoints
These routes are handled internally by Next.js and Supabase. Use the frontend login/signup pages instead of calling them directly.
| Route | Description |
|---|---|
POST /login |
User login |
POST /signup |
User registration |
GET /auth/callback |
OAuth callback handler |
GET /auth/confirm |
Email confirmation handler |
Data Schemas
GalleryItem
| Field | Type | Nullable | Description |
|---|---|---|---|
id |
integer | No | Record ID |
response_id |
integer | No | Associated inspection response ID |
question_id |
integer | No | Associated inspection question ID |
caption |
string | Yes | Image caption |
identifier |
string | Yes | Short image label |
date |
string | Yes | Date of inspection (YYYY-MM-DD) |
storage_key |
string | No | S3 object key |
content_type |
string | No | MIME type (e.g. image/jpeg) |
file_size_bytes |
integer | Yes | File size in bytes |
filename |
string | No | SAPAA-standardized filename |
site_id |
integer | No | Associated site ID |
site_name |
string | Yes | Human-readable site name |
imageUrl |
string | No | Signed S3 URL for image access |
HomepageImageItem
| Field | Type | Nullable | Description |
|---|---|---|---|
id |
integer | No | Record ID |
site_id |
integer | No | Associated site ID |
site_name |
string | Yes | Human-readable site name |
date |
string | No | Upload date (YYYY-MM-DD) |
photographer |
string | Yes | Photographer name |
caption |
string | Yes | Image caption |
identifier |
string | Yes | Short image label |
filename |
string | No | SAPAA-standardized filename |
file_size_bytes |
integer | Yes | File size in bytes |
storage_key |
string | No | S3 object key |
imageUrl |
string | No | Signed S3 URL for image access |
ErrorResponse
| Field | Type | Description |
|---|---|---|
error |
string | Human-readable error message |
Required Libraries and Dependencies
Production Dependencies
| Package | Purpose |
|---|---|
next |
Next.js framework |
react / react-dom |
React library and DOM rendering |
@supabase/ssr |
Supabase server-side rendering support |
@supabase/supabase-js |
Supabase JavaScript client |
@aws-sdk/client-s3 |
AWS S3 SDK for image storage |
@aws-sdk/s3-request-presigner |
Presigned URL generation for S3 |
@mui/material |
Material-UI components |
@mui/icons-material |
Material-UI icons |
chart.js |
Chart library |
react-chartjs-2 |
React wrapper for Chart.js |
leaflet |
Map library |
react-leaflet |
React wrapper for Leaflet |
leaflet.heat |
Heatmap plugin for Leaflet |
axios |
HTTP client |
lucide-react |
Icon library |
react-icons |
Additional icons |
Development Dependencies
| Package | Purpose |
|---|---|
typescript |
TypeScript compiler |
eslint |
Code linting |
jest |
Testing framework |
@testing-library/react |
React testing utilities |
tailwindcss |
CSS utility framework |
Installation
All dependencies are installed with:
npm install
Maintenance and Updates
Updating Dependencies
# Check for outdated packages
npm outdated
# Update a specific package
npm update <package-name>
# Update all packages (use with caution — test thoroughly after)
npm update
Commit package-lock.json changes after any updates.
Rollback Procedure
Option 1: Vercel Instant Rollback
- Go to Vercel Dashboard → Deployments
- Select a previous stable deployment
- Click "Promote to Production"
Option 2: Git-Based Rollback
git checkout <previous-stable-commit>
git push origin main
This triggers a new Vercel deployment from the stable commit.
Monitoring
- Vercel Analytics: Monitor performance and errors
- Supabase Dashboard: Monitor database usage and logs
- AWS CloudWatch / S3 Access Logs: Monitor S3 usage and errors
Backup Strategy
- Database: Supabase provides automatic daily backups (on paid plans)
- Images: Enable S3 Versioning or cross-region replication for production use
- Code: Git repository serves as the primary code backup
- Environment Variables: Store all credentials securely using a password manager
Support and Resources
- Next.js Documentation
- Supabase Documentation
- Vercel Documentation
- AWS S3 Documentation
- OpenCage API Documentation
For deployment support or issues, contact your development team with error messages, reproduction steps, browser/OS information, and screenshots where applicable.
Document Version: 2.0
Last Updated: March 2026
Prepared for: Stewards of Alberta's Protected Areas Association