Local Development Guide

This guide covers running the Refresh App Web locally, debugging techniques, hot reload, and working with Wrangler for Cloudflare Workers development.

Running Locally

Standard Vite Development Server

The default development workflow uses Vite's dev server with hot module replacement (HMR):

pnpm dev

This starts the app at http://localhost:5173 with:

  • ✅ Hot Module Replacement (HMR)

  • ✅ Fast refresh

  • ✅ Source maps for debugging

  • ✅ TypeScript checking

  • ✅ HTTPS support (if certs exist)

When to use: Regular feature development, UI work, component development

Wrangler Development Server

For testing Cloudflare Workers-specific features:

pnpm wrangler:dev

This runs your app in a local Workers environment with:

  • ✅ R2 bucket access (local simulation)

  • ✅ Environment variables from .dev.vars

  • ✅ Workers runtime behavior

  • ⚠️ Slower reload than Vite

When to use: Testing R2 uploads, Workers bindings, production-like environment

HTTPS Development

For testing OAuth flows (requires HTTPS redirect URIs):

  1. Generate self-signed certificates:

  1. Vite will auto-detect certs:

Vite config automatically looks for certs/key.pem and certs/cert.pem:

  1. Start dev server:

Access at https://localhost:5173 (accept self-signed cert warning)


Hot Module Replacement (HMR)

How HMR Works

Vite's HMR preserves application state while updating code:

  1. You save a file

  2. Vite detects the change

  3. Only the changed module is reloaded

  4. Page updates without full refresh

  5. Component state is preserved (when possible)

HMR-Friendly Code

✅ Good - State preserved:

When you edit this file and save, count value is preserved.

⚠️ Tricky - State may reset:

Side effects in module scope may re-run on HMR.

✅ Better - Use $effect:

Disabling HMR for a File

If HMR causes issues, force full reload:


Debugging

Browser DevTools

Chrome/Edge DevTools:

  1. Open DevTools (F12)

  2. Go to Sources tab

  3. Find your file in src/

  4. Set breakpoints

  5. Reload page or trigger code path

Source Maps: Vite generates source maps automatically in dev mode, so you see original TypeScript/Svelte code.

VS Code Debugging

Create .vscode/launch.json:

Usage:

  1. Start dev server: pnpm dev

  2. Press F5 in VS Code

  3. Chrome opens with debugger attached

  4. Set breakpoints in VS Code

  5. Debug in VS Code instead of browser

Server-Side Debugging

Console Logging:

Node Debugger:

Then in Chrome, go to chrome://inspect and click "inspect" on your Node process.

Wrangler Tail (Production Logs)

Stream real-time logs: npx wrangler tail --env production. See Reference: CLI Commands.


Database Development

Drizzle Studio

Visual database editor:

Opens at https://local.drizzle.studio with:

  • Browse all tables

  • Edit data directly

  • Run queries

  • View relationships

Making Schema Changes

Workflow:

  1. Edit schema file:

  1. Generate migration:

Creates a new file in drizzle/migrations/.

  1. Review migration SQL:

  1. Apply migration:

  1. Verify in Drizzle Studio:

  1. Commit migration file:

Development Database Resets

Reset entire database:

Seed development data:

Create scripts/seed-dev-data.ts:

Run: tsx scripts/seed-dev-data.ts


Environment Variables

Loading Environment Variables

Priority (highest to lowest):

  1. .env.local (git-ignored, local overrides)

  2. .env (git-ignored, main config)

  3. .env.example (git-tracked, template)

Fetching from AWS SSM

Managing Secrets Locally

Never commit secrets to git:

Add new secret:

  1. Add to AWS SSM:

  1. Re-fetch environment variables:

  1. Restart dev server


Testing Locally

Unit Tests

Type Checking

Linting and Formatting


Working with Cloudflare Workers

Local R2 Bucket Access

Using Wrangler Dev:

Wrangler simulates R2 buckets locally. Upload/download works, but data is ephemeral.

Accessing R2 in Code:

Testing Bindings

Environment Variables:

R2 Buckets:

KV Stores (if used):


Performance Profiling

Vite Build Analysis

Generate bundle size visualization:

Opens dist/bundle-analysis.html showing:

  • Chunk sizes

  • Dependencies per chunk

  • Treemap visualization

Lighthouse Testing

  1. Build production version:

  1. Open http://localhost:4173

  2. Run Lighthouse in Chrome DevTools

  3. Review performance, accessibility, SEO scores

Monitoring HMR Performance

Check Vite HMR speed:

In console, look for:

If HMR is slow (>500ms), check for:

  • Large dependency graphs

  • Too many components

  • Slow imports


Common Workflows

Adding a New Page

  1. Create route file:

  1. Add server load function:

  1. Create component:

  1. Test locally:

Navigate to http://localhost:5173/app/new-feature

Adding a Component

  1. Create component file:

  1. Implement component:

  1. Use in page:

Making an API Endpoint

  1. Create endpoint:

  1. Implement handler:

  1. Test endpoint:


Troubleshooting

Port Already in Use

HMR Not Working

  1. Check file watcher limits (Linux):

  1. Clear Vite cache:

TypeScript Errors

Database Connection Issues

  1. Check DATABASE_URL in .env

  2. Verify Neon database is accessible

  3. Test connection:


Best Practices

  1. Use HMR-friendly patterns - Avoid side effects in module scope

  2. Test with Wrangler before deploying - Catch Workers-specific issues early

  3. Keep .env in sync - Re-fetch from SSM when parameters change

  4. Run tests before committing - pnpm test && pnpm check

  5. Use TypeScript strictly - Catch errors at compile time

  6. Profile performance regularly - Use Lighthouse and bundle analysis



Last updated: October 2025

Last updated