This guide walks you through setting up a complete local development environment for sptfy.in, including both the SvelteKit frontend and PocketBase backend.
Prerequisites
Before you begin, make sure you have:
- Node.js 18+ - Download
- pnpm - Install with
npm install -g pnpm
- PocketBase v0.23.12 binary (instructions below)
- Git - For cloning the repository
Architecture Overview
| Component | Production | Local Development |
|---|
| Frontend | Cloudflare Pages | pnpm dev (localhost:5173) |
| Backend | VPS (PocketBase v0.23.12) | Local PocketBase binary |
| Database | Production SQLite | Fresh local SQLite |
Quick Start
Once you’ve completed the setup, starting the development environment is simple:
# Terminal 1: Start PocketBase backend
cd pocketbase
# Windows
start-dev.bat
# Linux/macOS
CF_SECRET_KEY=1x0000000000000000000000000000000AA ./pocketbase serve
# Terminal 2: Start SvelteKit frontend
pnpm dev
# Open http://127.0.0.1:5173 in your browser
First-Time Setup
1. Clone the Repository
git clone https://github.com/ayamkv/sptfyin.git
cd sptfyin
2. Install Dependencies
The project uses pnpm exclusively. The preinstall script will prevent npm or yarn from being used.
3. Download PocketBase v0.23.12
Use v0.23.12 specifically to match production. Later versions may have breaking changes.
Download from: PocketBase v0.23.12 Releases
| Operating System | File to Download |
|---|
| Windows | pocketbase_0.23.12_windows_amd64.zip |
| macOS (Intel) | pocketbase_0.23.12_darwin_amd64.zip |
| macOS (Apple Silicon) | pocketbase_0.23.12_darwin_arm64.zip |
| Linux | pocketbase_0.23.12_linux_amd64.zip |
Extract the pocketbase (or pocketbase.exe) binary into the pocketbase/ folder at the root of the project.
4. Start PocketBase
cd pocketbase
# Windows: Use the batch file (sets required env vars)
start-dev.bat
# Linux/macOS: Set CF_SECRET_KEY manually
CF_SECRET_KEY=1x0000000000000000000000000000000AA ./pocketbase serve
On first run, PocketBase will:
- Create the
pb_data/ directory
- Load hooks from
pb_hooks/
- Start the admin UI at
http://127.0.0.1:8090/_/
5. Create Admin Account
- Open http://127.0.0.1:8090/_/
- Create your admin email and password
- This is your local admin - use any credentials you want
6. Import Database Schema
The pb_migrations/ folder is empty by default. Import the schema from production:
- Go to production PocketBase admin: https://pbbase.sptfy.in/_/
- Navigate to Settings > Export collections
- Click Export to download the JSON file
- In your local PocketBase admin (
http://127.0.0.1:8090/_/):
- Go to Settings > Import collections
- Upload the JSON file
- Click Review then Confirm import
This imports all collections (users, random_short, analytics, etc.) with their rules and fields.
To test authentication features locally:
-
Go to Spotify Developer Dashboard
-
Create a new app or use an existing one
-
In App Settings, add this redirect URI:
http://127.0.0.1:5173/auth/spotify/callback
Use 127.0.0.1, NOT localhost. Spotify changed their policy in April 2025.
-
In local PocketBase admin (
http://127.0.0.1:8090/_/):
- Go to Settings > Auth providers
- Enable Spotify
- Enter your Client ID and Client Secret
8. Environment Variables
The .env.development file should already exist with these values:
VITE_DEBUG_MODE=false
# Turnstile test keys (always pass)
VITE_CF_SECRET=1x0000000000000000000000000000000AA
VITE_CF_SITE_KEY=1x00000000000000000000AA
# Local PocketBase
VITE_POCKETBASE_URL=http://127.0.0.1:8090
# IMPORTANT: Use 127.0.0.1, NOT localhost
VITE_APP_URL=http://127.0.0.1:5173
For local overrides, create .env.development.local (gitignored).
9. Start the Frontend
The app will be available at http://127.0.0.1:5173
Directory Structure
sptfyin/
├── pocketbase/
│ ├── pocketbase.exe # PocketBase binary (download separately, gitignored)
│ ├── pb_data/ # Database files (created on first run, gitignored)
│ ├── pb_hooks/ # Server-side hooks (committed)
│ │ ├── main.pb.js # Custom routes
│ │ └── random.pb.js # Turnstile, record protection, OAuth hooks
│ ├── pb_migrations/ # Schema migrations (committed)
│ └── pb_public/ # Static files served by PocketBase
├── src/ # SvelteKit app
│ ├── lib/ # Shared components and utilities
│ ├── routes/ # SvelteKit routes (+page.svelte files)
│ └── app.html # HTML template
├── static/ # Static assets
├── .env.development # Dev environment variables
├── package.json # Dependencies and scripts
└── svelte.config.js # SvelteKit configuration
PocketBase Hooks
The pb_hooks/ folder contains server-side JavaScript hooks that run on the PocketBase backend:
random.pb.js
| Hook | Purpose |
|---|
onRecordCreateRequest (analytics) | Logs IP geolocation on record creation |
onRecordCreateRequest (random_short) | Validates Turnstile token before creating short links |
onRecordUpdateRequest | Protects fields from unauthorized modification |
onRecordAuthRequest (users) | Extracts Spotify user ID on OAuth login |
main.pb.js
Custom API routes (e.g., /hello/{name} test endpoint).
Turnstile in Development
Local development uses Cloudflare’s official test keys that always pass verification:
| Key | Value |
|---|
| Site Key | 1x00000000000000000000AA |
| Secret Key | 1x0000000000000000000000000000000AA |
No actual CAPTCHA verification occurs during local development.
Testing Data-Backed Routes
If you’re testing routes that fetch data from PocketBase (like /recent, /top, /dash/links), always start local PocketBase first.Without PocketBase running, these routes will fail to load and UI behavior checks become unreliable.
Common Issues
”localhost is not allowed as redirect URI”
Spotify changed their rules in April 2025. Use 127.0.0.1 instead:
- In
.env.development: VITE_APP_URL=http://127.0.0.1:5173
- In browser: Access via
http://127.0.0.1:5173
- In Spotify Dashboard: Use
http://127.0.0.1:5173/auth/spotify/callback
”PocketBase connection refused”
Make sure PocketBase is running:
cd pocketbase && ./pocketbase serve
“Migrations failed”
If migrations fail, start fresh:
cd pocketbase
rm -rf pb_data
./pocketbase serve
Then repeat the schema import steps.
Hooks not loading
Check PocketBase console output. Hooks must:
- Be in the
pb_hooks/ directory
- End with
.pb.js extension
- Have valid JavaScript syntax
Docker Alternative (Optional)
If you prefer Docker over running the binary directly:
services:
pocketbase:
image: ghcr.io/muchobien/pocketbase:0.23.12
container_name: sptfyin-pocketbase-dev
ports:
- '8090:8090'
volumes:
- ./pocketbase/pb_data:/pb_data
- ./pocketbase/pb_hooks:/pb_hooks
- ./pocketbase/pb_migrations:/pb_migrations
- ./pocketbase/pb_public:/pb_public
environment:
CF_SECRET_KEY: '1x0000000000000000000000000000000AA'
Run with:
docker compose -f docker-compose.dev.yml up -d
Next Steps