Expert guidance for developing the HappyGotchaDays pet adoption anniversary celebration PWA built on Cloudflare Workers with Hono, D1, R2, and Workers AI.
Expert guidance for working with the HappyGotchaDays Progressive Web App - a Cloudflare Workers-based platform for celebrating pet adoption anniversaries.
**HappyGotchaDays.com** is a fully deployed PWA for pet owners to celebrate and share their dogs' and cats' adoption anniversaries ("gotcha days"). Built entirely on Cloudflare's edge platform.
**Live URL:** https://happygotchadays.bill-burkey.workers.dev
**Critical Context:** This platform is exclusively for pet (dog/cat) adoption celebrations. Never conflate pet and human adoption contexts.
**Request Flow:**
1. Request → Cloudflare Worker (Hono app)
2. Logger & CORS middleware
3. Route matching (`/api/*` or static files)
4. Authentication middleware (where required)
5. Route handler (database/R2/AI operations)
6. Response
**Static File Serving:**
Frontend assets are embedded as JavaScript strings in `src/frontend/*.js` files and served via the Worker itself (no separate static hosting).
**Database Design:**
All tables use `TEXT` for IDs (UUIDs) and `INTEGER` for timestamps (Unix epoch). Key relationships:
**Entry Point:**
**Routes (6 API modules):**
**Utilities:**
**Middleware:**
**AI Integration:**
**Frontend (embedded as JS strings):**
```bash
npm run dev # Start local Worker (localhost:8787)
curl http://localhost:8787/health # Health check
npm run db:migrate:local # Apply migrations locally
npm run db:migrate # Apply migrations to remote D1
wrangler d1 execute gotchadays-db --local --command="SELECT * FROM users LIMIT 5"
npm test # Run all tests
npm test -- tests/unit/auth.test.js # Run specific test
npm run test:coverage # Coverage report
npm run deploy # Deploy to production
npm run deploy:preview # Deploy preview
wrangler secret list # List secrets
wrangler secret put JWT_SECRET # Set secret
```
**Query Patterns:**
```javascript
// Single result
const user = await c.env.DB.prepare(
'SELECT * FROM users WHERE id = ?'
).bind(userId).first();
// Multiple results
const pets = await c.env.DB.prepare(
'SELECT * FROM pets WHERE user_id = ?'
).bind(userId).all();
// Insert/Update/Delete
const result = await c.env.DB.prepare(
'INSERT INTO pets (id, user_id, name, species, gotcha_date, created_at) VALUES (?, ?, ?, ?, ?, ?)'
).bind(id, userId, name, species, gotchaDate, timestamp).run();
```
**Adding Migrations:**
1. Create new file in `migrations/` with sequential number
2. Run `npm run db:migrate:local` to test locally
3. Run `npm run db:migrate` to apply to remote D1
```javascript
// Upload with metadata
await c.env.PHOTOS.put(key, fileStream, {
httpMetadata: { contentType: 'image/jpeg' }
});
// Retrieve
const object = await c.env.PHOTOS.get(key);
const arrayBuffer = await object.arrayBuffer();
// Delete
await c.env.PHOTOS.delete(key);
```
**Image Classification:**
```javascript
const result = await c.env.AI.run('@cf/microsoft/resnet-50', {
image: arrayBuffer
});
```
**Vision Model:**
```javascript
const result = await c.env.AI.run('@cf/llava-hf/llava-1.5-7b-hf', {
image: arrayBuffer,
prompt: "Describe this pet"
});
```
**Text Generation:**
```javascript
const result = await c.env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [{ role: "user", content: "Generate a story..." }]
});
```
**Step-by-step:**
1. Add handler to appropriate route file in `src/routes/` (or create new route file)
2. If new route file, register in `src/index.js`: `app.route('/api/prefix', newRoutes)`
3. Add database migration if schema changes needed
4. Run `npm run db:migrate:local` to test
5. Test with `npm run dev`
6. Deploy with `npm run deploy`
**Route File Pattern:**
```javascript
import { Hono } from 'hono';
import { authMiddleware } from '../middleware/auth.js';
export const myRoutes = new Hono();
myRoutes.get('/resource', authMiddleware, async (c) => {
const user = c.get('user');
// Handler logic
return c.json({ data: result });
});
```
**IMPORTANT:** Frontend is embedded as JavaScript strings in `src/frontend/*.js` files.
**To update frontend:**
1. Edit the template literal content in `src/frontend/*.js` files
2. Run `npm run deploy` to update (frontend is bundled with Worker)
3. Hard refresh browser (Cmd+Shift+R) to bypass Service Worker cache
**Modal Pattern:**
Modals are dynamically created by injecting HTML into `#modalContainer`. Close by clicking backdrop or calling `closeModal()`.
**Protected Routes:**
```javascript
import { authMiddleware } from '../middleware/auth.js';
myRoutes.get('/protected', authMiddleware, async (c) => {
const user = c.get('user'); // { id: string, email: string }
// User is authenticated
});
```
**Optional Auth:**
Use `optionalAuth` for endpoints that work for both authenticated and guest users.
**JWT Details:**
**Run Tests:**
```bash
npm test # All tests
npm test -- tests/unit/auth.test.js # Specific test
npm run test:coverage # With coverage
```
**Test Files:**
**Mocking:**
Use Vitest to mock Cloudflare bindings (DB, KV, R2, AI).
**404 on API calls:**
**Frontend not updating:**
**Database errors:**
**Authentication not working:**
Access via `c.env` in Hono context:
**Production:**
```bash
npm run deploy
```
**Preview:**
```bash
npm run deploy:preview
```
**GitHub Actions:**
Auto-deploys on push to `main` via `.github/workflows/deploy.yml` (requires `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ACCOUNT_ID` secrets).
1. Frontend files must be embedded as JavaScript strings - they are NOT separate static files
2. All database IDs must be TEXT (UUIDs), timestamps must be INTEGER (Unix epoch)
3. This is exclusively a pet adoption celebration platform - never conflate with human adoption
4. Images must be validated and moderated before storage
5. JWT tokens expire after 1 hour - sessions managed in KV
6. All routes must use Hono router pattern and be registered in `src/index.js`
**Adding a new authenticated endpoint:**
```javascript
// In src/routes/pets.js
import { authMiddleware } from '../middleware/auth.js';
export const petsRoutes = new Hono();
petsRoutes.post('/celebrate', authMiddleware, async (c) => {
const user = c.get('user');
const { petId } = await c.req.json();
// Query database
const pet = await c.env.DB.prepare(
'SELECT * FROM pets WHERE id = ? AND user_id = ?'
).bind(petId, user.id).first();
if (!pet) {
return c.json({ error: 'Pet not found' }, 404);
}
// Generate celebration message with AI
const result = await c.env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [{
role: "user",
content: `Generate a celebration message for ${pet.name}'s gotcha day`
}]
});
return c.json({ message: result.response });
});
```
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/happygotchadays-pwa-development/raw