Skip to content

Complete Setup Guide

This comprehensive guide walks you through setting up astro-basics with all its features including authentication, database integration, role-based access control, and security features.

Astro-basics is a production-ready web development framework with:

  • ✅ Authentication - Clerk integration with protected routes
  • ✅ Database Support - Supabase (PostgreSQL) with native Clerk integration
  • ✅ Role System - Configurable roles with TypeScript type safety
  • ✅ Security - CSRF protection, rate limiting, RLS policies
  • ✅ Testing - Unit tests (Vitest) and E2E tests (Playwright)
  • ✅ PWA Ready - Progressive Web App capabilities

For experienced developers who want to get running quickly:

Terminal window
# 1. Install and configure
git clone https://github.com/shawn-sandy/astro-basics.git
cd astro-basics
npm install # ~4 minutes
npm run prepare # Setup hooks
cp .env.example .env # Copy template
# 2. Add Clerk keys to .env (required)
# PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
# CLERK_SECRET_KEY=sk_test_...
# 3. Setup database (optional)
npm run db:wizard # Interactive setup
# 4. Start developing
npm run start # Dev server + SCSS watcher

Visit http://localhost:4321 to see your site!

  • Node.js v18.0.0 or higher
  • npm v9.0.0 or higher
  • Git for version control
Terminal window
# Clone repository
git clone https://github.com/shawn-sandy/astro-basics.git
cd astro-basics
# Install dependencies (takes ~4 minutes, warnings are expected)
npm install
# Setup pre-commit hooks (Husky + lint-staged)
npm run prepare
# Install Playwright browsers (for E2E tests)
npx playwright install

Authentication is required for protected routes and user features.

  1. Sign up at clerk.com (free tier available)
  2. Create a new application
  3. Choose authentication methods (email, Google, GitHub, etc.)

From your Clerk dashboard:

  1. Navigate to API Keys
  2. Copy Publishable Key → PUBLIC_CLERK_PUBLISHABLE_KEY
  3. Copy Secret Key → CLERK_SECRET_KEY
  4. (Optional) Copy Webhook Secret → CLERK_WEBHOOK_SECRET
Terminal window
# Copy environment template
cp .env.example .env
# Edit .env file
vim .env

Add your Clerk keys:

# Authentication (Required)
PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_WEBHOOK_SECRET=whsec_... # Optional

These routes require authentication (configured in src/middleware.ts):

  • /dashboard/* - User dashboard and profile
  • /forum/* - Reserved for forum routes (no forum pages ship today)
  • /organization/* - Organization management

Unauthenticated users are automatically redirected to sign-in.

The project uses Supabase (PostgreSQL): real-time features, native Clerk integration, RLS.

Use the interactive database wizard:

Terminal window
npm run db:wizard

The wizard will:

  • Prompt for your Supabase project URL and keys
  • Check that the values look valid
  • Save them to .env without touching unrelated settings

It does not create tables — apply the migrations as in Option B, step 3.

1. Create Supabase Project

  • Sign up at supabase.com
  • Create a new project
  • Wait for initialization (~2 minutes)

2. Get Credentials

Navigate to Project Settings → API to find your credentials:

Steps to locate your API keys:

  1. Open Supabase Dashboard: https://supabase.com/dashboard
  2. Select your project from the project list
  3. Click “Settings” (gear icon) in the left sidebar
  4. Navigate to “API” section
  5. Find “Project API keys” section:
    • anon (public) - This is your SUPABASE_ANON_KEY ✅
    • service_role (secret) - This is your SUPABASE_SERVICE_ROLE_KEY 🔒
  6. Find “Project URL” at the top - This is your SUPABASE_URL

Add these to your .env file:

SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ... # Required for server operations
# Public keys (for client-side)
PUBLIC_SUPABASE_URL=https://your-project.supabase.co
PUBLIC_SUPABASE_ANON_KEY=eyJ...

3. Run Migrations

Apply the SQL migrations with psql (see scripts/migrations/README.md):

Terminal window
# Apply database schema (users, roles, organizations, comments)
psql $DATABASE_URL -f scripts/migrations/001_core_schema.sql
psql $DATABASE_URL -f scripts/migrations/002_security_policies.sql
psql $DATABASE_URL -f scripts/migrations/007_data_api_grants.sql
# Set up Clerk-Supabase user sync
npm run db:setup-users

See the Clerk-Supabase Integration Guide for detailed instructions.

The project includes a configurable role system for setup-time customization.

Roles control user access with hierarchical privilege escalation:

Level 3: super_admin ⚡ Full system access
│
Level 2: admin 👔 Manage users & settings
│
Level 1: member 👤 View content (default)

Default Behavior: Higher-level roles automatically inherit lower-level permissions.

Pre-configured roles in config/roles.config.ts:

  • member (level 1) - Default for new users
  • admin (level 2) - Administrative access
  • super_admin (level 3) - Full system access

1. Edit Configuration

Terminal window
vim config/roles.config.ts

2. Add Custom Roles

export const roleConfig: RoleConfig = {
roles: [
{ id: 'member', level: 1, name: 'Member', isDefault: true },
{ id: 'author', level: 2, name: 'Author' }, // New
{ id: 'moderator', level: 3, name: 'Moderator' }, // New
{ id: 'admin', level: 4, name: 'Admin' },
{ id: 'super_admin', level: 5, name: 'Super Admin' },
],
}

3. Generate Types and Migrations

Terminal window
# Preview changes
npm run setup:roles:dry-run
# Generate files
npm run setup:roles

This creates:

  • TypeScript types in src/types/generated-roles.ts
  • Database migrations in scripts/migrations/

4. Apply Migration

Terminal window
# Use the migration number setup:roles printed
psql $DATABASE_URL -f scripts/migrations/<NNN>_user_roles.sql

5. Commit Changes

Terminal window
git add config/ src/types/ scripts/migrations/
git commit -m "Configure custom roles"

Protect components and pages:

---
import { RoleGuard } from '#components/react/RoleGuard'
---
<!-- Hierarchical (default): members, admins, super_admins can access -->
<RoleGuard allowedRoles={['member']} client:load>
<Dashboard />
</RoleGuard>
<!-- Exact matching: only admins can access -->
<RoleGuard allowedRoles={['admin']} useHierarchy={false} client:load>
<AdminPanel />
</RoleGuard>

See the Configurable Roles Guide and Role Guard Usage Guide for complete documentation.

Terminal window
# Recommended: Dev server + SCSS watcher together
npm run start
# Or start separately:
npm run dev # Astro dev server (port 4321)
npm run sass # SCSS watcher
src/
├── components/ # Reusable components
│ ├── astro/ # Server-rendered (.astro)
│ ├── react/ # Client-side (.tsx)
│ └── dashboard/ # Protected components
├── pages/ # Route pages & API endpoints
├── content/ # Content collections (MDX)
│ ├── posts/ # Blog posts
│ ├── docs/ # Documentation
│ └── content/ # General content
├── layouts/ # Page layouts
├── styles/ # SCSS stylesheets
├── libs/ # Database clients & utilities
├── utils/ # Helper functions
└── middleware.ts # Authentication middleware

Use # path aliases for clean imports:

// ✅ Recommended
import Header from '#components/astro/Header.astro'
import { SITE_TITLE } from '#utils/site-config'
import type { User } from '#types/users'
// ❌ Avoid
import Header from '../../components/astro/Header.astro'

Before committing:

Terminal window
# Fix all auto-fixable issues
npm run fix:all
# Or run individually:
npm run lint # ESLint
npm run format # Prettier
npm run type-check # TypeScript
npm run lint:styles:fix # StyleLint
npm run lint:md:fix # Markdown

Pre-commit hooks (Husky) automatically run on staged files.

Terminal window
# Run all unit tests
npm test
# Run specific test
npm test path/to/test.test.ts
# Watch mode
npm test -- --watch
Terminal window
# Run all E2E tests
npm run test:e2e
# Run with UI
npx playwright test --ui
# View report
npm run test:e2e:report

Note: E2E tests target http://localhost:4321 by default, and reuse a dev server already running there. To test a server on another port, such as a second worktree, set PLAYWRIGHT_BASE_URL:

Terminal window
PLAYWRIGHT_BASE_URL=http://localhost:4330 npm run test:e2e

If nothing is running at that address, Playwright starts npm run dev on the same port.

Terminal window
# Status
npm run db:status # Check Supabase configuration
# Users
npm run db:setup-users # Set up Clerk-Supabase user sync
npm run db:sync-user # Sync the current user

Migrations live in scripts/migrations/ and are applied with psql, with rollback_*.sql files alongside the reversible ones. See scripts/migrations/README.md.

Terminal window
# Create production build
npm run build
# Preview locally
npm run preview
# Deploy to Netlify
npm run deploy:prod

Build time: ~10-15 seconds Output: dist/ directory

Configure via .env:

ASTRO_ADAPTER=netlify # or 'node', 'vercel'

Problem: “Clerk keys not configured”

Solution:

Terminal window
# Verify keys in .env
grep CLERK .env
# Keys should start with:
# PUBLIC_CLERK_PUBLISHABLE_KEY: pk_test_ or pk_live_
# CLERK_SECRET_KEY: sk_test_ or sk_live_

Problem: “Failed to connect to database”

Solution:

Terminal window
# Check status
npm run db:status

Confirm SUPABASE_URL, SUPABASE_ANON_KEY and SUPABASE_SERVICE_ROLE_KEY are set, and that the Supabase project is not paused.

Problem: “Table does not exist” errors

Solution:

Terminal window
# Apply the migrations (see scripts/migrations/README.md)
psql $DATABASE_URL -f scripts/migrations/001_core_schema.sql
psql $DATABASE_URL -f scripts/migrations/002_security_policies.sql
psql $DATABASE_URL -f scripts/migrations/007_data_api_grants.sql

Problem: getStaticPaths warnings

Solution: These are expected for dynamic routes and don’t affect functionality.

Problem: Commits fail due to linting

Solution:

Terminal window
# Fix all issues
npm run fix:all

Now that you’re set up:

  1. Explore Features

  2. Learn the Stack

  3. Build Your App

    • Create components in src/components/
    • Add content to collections in src/content/
    • Build API endpoints in src/pages/api/
  • Documentation - Browse this guide for detailed information
  • GitHub Issues - Report bugs or request features
  • Examples - Check /src/pages/ for usage examples

Happy coding! 🚀