# Local Development Guide ## Prerequisites - Node.js 20+ - npm - PostgreSQL (running locally or via Docker) - A Contabo S3 bucket (or any S3-compatible storage) ## 1. Clone and Install ```bash git clone && cd spomeniQR npm install ``` ## 2. Set Up Environment Variables ```bash cp .env.example .env ``` Edit `.env` with your local values: ```env # Clerk - get from https://dashboard.clerk.com NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_... CLERK_SECRET_KEY=sk_test_... # Database - use localhost for local Postgres DATABASE_URL=postgresql://postgres:postgres@localhost:5432/monuments # Contabo S3 S3_ENDPOINT=https://eu2.contabostorage.com S3_REGION=eu-2 S3_ACCESS_KEY_ID=your-access-key S3_SECRET_ACCESS_KEY=your-secret-key S3_BUCKET_NAME=monuments-images # App NEXT_PUBLIC_APP_URL=http://localhost:3000 NEXT_PUBLIC_APP_DOMAIN=localhost:3000 ``` ## 3. Set Up the Database You need a PostgreSQL database. Options: ### Option A: Docker (recommended) Start only the database: ```bash docker compose up db -d ``` This starts PostgreSQL on port 5432 with user `postgres`, password `postgres`, database `monuments`. ### Option B: Local PostgreSQL Create the database manually: ```bash createdb monuments ``` Update `DATABASE_URL` in `.env` to match your local PostgreSQL credentials. ## 4. Run Prisma Migrations ```bash npx prisma migrate dev --name init ``` This creates the tables and generates the Prisma client. ## 5. Set Up Contabo S3 1. Log into your Contabo Object Storage dashboard 2. Create a bucket named `monuments-images` 3. Set bucket policy to **public read** (monument images must be publicly accessible) 4. Create an API key (access key + secret key) 5. Note your endpoint and region (e.g. `https://eu2.contabostorage.com`, region `eu-2`) Set the CORS policy on the bucket to allow browser uploads: ```json { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": ["*"] }, "Action": ["s3:GetObject", "s3:PutObject"], "Resource": ["arn:aws:s3:::monuments-images/*"] } ] } ``` Also set a CORS configuration: ```json [ { "AllowedHeaders": ["*"], "AllowedMethods": ["GET", "PUT"], "AllowedOrigins": ["http://localhost:3000"], "ExposeHeaders": [], "MaxAgeSeconds": 3600 } ] ``` ## 6. Configure Clerk 1. Go to [Clerk Dashboard](https://dashboard.clerk.com) 2. Create a new application 3. Under **Paths**, set: - Sign-in: `/sign-in` - Sign-up: `/sign-up` 4. Under **API Keys**, copy the publishable key and secret key to your `.env` 5. Under **Domains**, add `localhost:3000` ## 7. Start Development Server ```bash npm run dev ``` The app runs at **http://localhost:3000**. ## 8. Test Subdomain Routing Locally Subdomain routing (`eiffel-tower.testbed.mk`) doesn't work on `localhost`. For local testing of subdomain pages: 1. **Direct URL**: Visit `http://localhost:3000/eiffel-tower` (this simulates subdomain routing via the `[subdomain]` page route) 2. **Using /etc/hosts** (optional, for realistic testing): ```bash sudo nano /etc/hosts # Add: 127.0.0.1 eiffel-tower.testbed.mk 127.0.0.1 testbed.mk ``` Then add this to your `.env`: ``` NEXT_PUBLIC_APP_DOMAIN=testbed.mk ``` And modify `middleware.ts` temporarily to also check `localhost` in development. 3. **Using the X-Subdomain header directly** (for curl testing): ```bash curl -H "X-Subdomain: eiffel-tower" http://localhost:3000/ ``` ## 9. Useful Commands ```bash # Start dev server with hot reload npm run dev # Generate Prisma client (after schema changes) npx prisma generate # Create a new migration npx prisma migrate dev --name your-migration-name # Open Prisma Studio (DB GUI) npx prisma studio # Run linter npm run lint # Type check npx tsc --noEmit # Build for production npm run build ``` ## 10. Troubleshooting ### "Prisma Client could not be generated" ```bash npx prisma generate ``` ### Database connection refused - Make sure PostgreSQL is running: `docker compose up db -d` - Check `DATABASE_URL` in `.env` matches your DB credentials ### Clerk authentication errors - Verify your Clerk keys in `.env` are correct - Ensure `localhost:3000` is added as a domain in the Clerk dashboard ### S3 upload fails - Check that the bucket exists and permissions are set - Verify the CORS configuration allows `http://localhost:3000` - Ensure the access key has both read and write permissions ### Port 3000 already in use ```bash # Kill whatever is on port 3000 lsof -ti:3000 | xargs kill -9 # Or use a different port PORT=3001 npm run dev ```