A modern links aggregator built with SvelteKit 5, Skeleton UI, and Supabase, designed to run as a Tor hidden service on Railway.
- Frontend: SvelteKit 5 with Skeleton UI
- Backend: Node.js 20+ with SvelteKit API routes
- Database: Supabase (PostgreSQL)
- Styling: Tailwind CSS with Skeleton UI components
- Testing: Vitest
- Linting: ESLint + Prettier
- Deployment: Railway with Docker
- Privacy: Tor hidden service support
- Modern, responsive UI with Skeleton components
- Real-time database with Supabase
- Docker containerization with Tor integration
- Railway deployment ready
- ESLint and Prettier configured
- Vitest testing setup
- Node.js 20+
- pnpm
- Supabase CLI (optional, for local development)
-
Clone the repository
-
Install dependencies:
pnpm install
-
Copy environment variables:
cp .env.example .env
-
Update
.envwith your Supabase credentials:# Client-side (PUBLIC_ prefix for browser exposure) PUBLIC_SUPABASE_URL=your_supabase_project_url PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key # Server-side (Private - no PUBLIC_ prefix) SUPABASE_SERVICE_ROLE_KEY=your_supabase_service_role_key SUPABASE_DB_PASSWORD=your_supabase_db_password SUPABASE_JWT_SECRET=your_supabase_jwt_secret
# Start development server (runs on http://localhost:8080)
pnpm dev
# Build for production
pnpm build
# Preview production build (runs on http://localhost:8080)
pnpm preview
# Run tests
pnpm test
# Run linting
pnpm lint
# Format code
pnpm format-
Install Supabase CLI:
pnpm add -g @supabase/cli
-
Start local Supabase:
pnpx supabase start
-
Create new migration:
pnpx supabase migrations new feature_name
- Create a new Supabase project
- Link your local project to Supabase:
pnpx supabase link
- Update environment variables with your project credentials
- Push migrations to your Supabase project:
pnpx supabase db push
docker build -t links-aggregator .docker run -p 8080:8080 links-aggregatorThe container will:
- Start Tor with hidden service configuration
- Display the
.onionaddress in logs - Serve the application on port 8080
-
Connect your repository to Railway
-
Set environment variables in Railway dashboard:
PUBLIC_SUPABASE_URLPUBLIC_SUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEYSUPABASE_DB_PASSWORDSUPABASE_JWT_SECRET
Note: These environment variables are required during both build and runtime for the Docker container.
-
Deploy using the included
railway.tomlconfiguration
- Deploy your project to Railway first
- Right-click on your service card in Railway dashboard
- Select "Add Volume"
- Mount Path:
/var/lib/tor(only field needed) - Save the volume
- Redeploy to activate the volume
Alternative: Run the setup script for guidance: bash scripts/setup-railway.sh
Note: The volume ensures your .onion address stays the same across deployments.
The deployment will automatically:
- Build using the Dockerfile
- Configure Tor hidden service with persistent volume for keys
- Start the application
The Railway deployment includes a persistent volume (tor-keys) mounted at /var/lib/tor to preserve Tor hidden service keys between deployments. This ensures your .onion address remains consistent across redeploys.
Volume Details (railway.toml):
[[deploy.volumes]]
name = "tor-keys"
mountPath = "/var/lib/tor"Purpose: Persist Tor hidden service private keys and hostname across deployments
├── src/
│ ├── lib/
│ │ └── supabase.js # Supabase client
│ ├── routes/
│ │ ├── +layout.svelte # Main layout
│ │ └── +page.svelte # Home page
│ ├── app.html # HTML template
│ └── app.css # Global styles
├── tests/ # Test files
├── docker/ # Docker configuration
├── supabase/ # Supabase configuration
├── package.json
├── svelte.config.js
├── vite.config.js
├── tailwind.config.js
└── Dockerfile
- Follow the established code style (ESLint + Prettier)
- Write tests for new features
- Update documentation as needed
- Create meaningful commit messages
MIT License