A mobile-first packing list web app for travel with all-items management, trip planning, and bag organization. Built with Astro, Solid.js, Tailwind CSS, Cloudflare D1, and Clerk Auth.
- Frontend: Astro.js + Solid.js + Tailwind CSS + TypeScript
- Backend: Cloudflare Workers (TypeScript)
- Database: Cloudflare D1 (SQLite at the edge)
- ORM: Drizzle ORM
- Auth: Clerk
- Deployment: Cloudflare Pages
- 📝 All items list with categories for your packing items
- 🧳 Trip-specific packing lists
- 👜 Bag organization (carry-on, checked, personal item)
- ✅ Pack/unpack tracking
- 📱 Mobile-first design with large touch targets
- 🔄 Multi-device sync via Cloudflare D1
- 🔐 Secure authentication with Clerk
- Bun installed
- Cloudflare account
- Clerk account
bun install- Go to Clerk Dashboard
- Create a new application
- Copy your Publishable Key and Secret Key
- Create a
.envfile:
cp .env.example .env- Update
.envwith your Clerk keys:
PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_your_key_here
CLERK_SECRET_KEY=sk_test_your_key_here# Login to Cloudflare (if you haven't already)
npx wrangler login
# Create D1 database
npx wrangler d1 create packzen-dbThis will output something like:
✅ Successfully created DB 'packzen-db' in region WEUR
Created your database using D1's new storage backend.
[[d1_databases]]
binding = "DB"
database_name = "packzen-db"
database_id = "your-database-id-here"
Copy the database_id and update wrangler.jsonc:
# Generate migrations from schema
bun run db:generate
# Apply migrations to local D1 database
bun run db:migratebun run devThe app will be available at http://localhost:4321
# Start dev server
bun run dev
# Build for production
bun run build
# Preview production build
bun run preview
# Format code with Prettier
bun run format
# Generate database migrations
bun run db:generate
# Apply migrations (local)
bun run db:migrate
# Apply migrations (production)
bun run db:migrate:prod
# Open Drizzle Studio (database GUI)
bun run db:studio├── db/ # Database schema & migrations
│ ├── schema.ts # Drizzle schema definitions
│ └── migrations/ # Generated SQL migrations
├── src/
│ ├── components/ # Solid.js components
│ ├── layouts/ # Astro layouts
│ ├── lib/ # Utilities
│ ├── middleware.ts # Astro middleware for auth
│ ├── pages/ # Astro routes & API endpoints
│ ├── stores/ # Solid stores
│ └── styles/ # Global CSS
├── public/ # Static assets
├── astro.config.mjs # Astro configuration
├── drizzle.config.ts # Drizzle ORM configuration
├── wrangler.jsonc # Cloudflare configuration
└── package.json
# Build the project
bun run build
# Deploy to Cloudflare Workers (includes static assets)
npx wrangler deployThe first deployment will create a new Worker in your Cloudflare account.
# Set Clerk secret key
npx wrangler secret put CLERK_SECRET_KEY
# Paste your Clerk secret key when promptedUpdate wrangler.jsonc with your production values:
{
"vars": {
"PUBLIC_CLERK_PUBLISHABLE_KEY": "pk_live_your_production_key",
},
}Then redeploy: npx wrangler deploy
bun run db:migrate:prod- ✅ Phase 1: Project Setup
- ✅ Phase 2: Database Schema & Auth
- ✅ Phase 3: All Items Management
- ✅ Phase 4: Trip Management
- ✅ Phase 5: Bag Management
- ✅ Phase 6: Trip Items & Packing
- ✅ Phase 7: Layout & Navigation
- ⏳ Phase 8: Polish & Optimization
- Minimum 44x44px touch targets
- 16px base font size (prevents iOS zoom)
- Bottom navigation for easy thumb access
- Large, clear tap targets for checkboxes
- Generous spacing (16px minimum)
- Smooth animations and transitions
- Cloudflare Pages: Unlimited sites, 500 builds/month
- Cloudflare Workers: 100K requests/day
- Cloudflare D1: 5GB storage, 5M reads/day, 100K writes/day
- Clerk: 10K monthly active users
MIT
{ "d1_databases": [ { "binding": "DB", "database_name": "packzen-db", "database_id": "paste-your-database-id-here", }, ], }