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 Workers, auto-deployed on push to
main
- 📝 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:
# Apply migrations to the 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
# Run tests
bun run test
# Format code with Prettier
bun run format
# Apply migrations (local)
bun run db:migrate
# Apply migrations (production)
bun run db:migrate:prod
# Open Drizzle Studio on the local database
bun run db:studioMigrations are hand-written SQL, applied in order by wrangler (and by the tests, which build their database from them):
- Add the next numbered file to
db/migrations/, e.g.0010_add_widgets.sql. Make it additive or data-preserving — never drop user data. - Mirror the change in
db/schema.ts(tables and indexes). bun run db:migratelocally, thenbun run test.- Apply to production with
bun run db:migrate:prodbefore deploying code that needs it.
├── db/ # Database schema & migrations
│ ├── schema.ts # Drizzle schema definitions
│ └── migrations/ # Hand-written 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 Studio configuration
├── wrangler.jsonc # Cloudflare configuration
└── package.json
This is a Cloudflare Worker (not a Pages project). Pushing to main
deploys it through Workers Builds. DEPLOYMENT.md is the
runbook: where each config value and secret lives, the release checklist,
verification, rollback and troubleshooting.
- Minimum 44x44px touch targets
- 16px base font size (prevents iOS zoom)
- Large, clear tap targets for checkboxes
- Generous spacing (16px minimum)
- Smooth animations and transitions
- 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", }, ], }