Frontend Interview Task
Edge Saved – Article Bookmarking App Time Limit 1 hour Goal Build a small server-side rendered web application using Cloudflare Workers and React Router (v7). The app allows users to bookmark articles, with bookmark state rendered via SSR and persisted using signed cookies.
Functional Requirements
- Routes & Pages (SSR required) GET / — Article List Page
- Display a list of articles (hard-coded data is fine, ~10 items).
- Each article shows:
- Title
- Short description
- A Bookmark / Unbookmark button
- At the top of the page, show:
- “Bookmarked: X articles” SSR requirement On first load, bookmark status must be rendered on the server using data from cookies (not client-only state).
GET /saved — Bookmarked Articles Page
- Display only bookmarked articles.
- If there are no bookmarked articles:
- Show an empty-state message
- Provide a link back to /
- Bookmark Toggle (Action) POST /toggle (or equivalent action)
- Receives an articleId
- Reads current bookmarks from cookies
- Toggles bookmark state
- Writes updated state back via Set-Cookie
- Returns:
- Minimum: a redirect back to the previous page
- Optional (bonus): use useFetcher() for a no-reload toggle
- Signed Cookie (Required) Bookmark state must be protected against tampering.
- Store bookmark data in a cookie payload, e.g.:
- { "ids": ["a1", "a3"], "iat": 1700000000 }
- Sign the payload using HMAC-SHA256
- Cookie format example:
- base64(payload).base64(signature)
- Use an environment secret:
- APP_SECRET Important
- Use Cloudflare Workers Web Crypto API (crypto.subtle)
- Do not use Node.js crypto
- If signature verification fails:
- Treat the cookie as invalid (empty bookmarks or clear cookie)
- Headers & SSR Behavior
- All loaders/actions must run on the server (Workers runtime)
- Responses that depend on user cookies must include:
- Cache-Control: private, no-store
- Bookmark cookie should include reasonable attributes:
- HttpOnly
- Secure
- SameSite=Lax
- Path=/
- Error Handling
- Implement at least one Error Boundary or errorElement
- Example cases:
- Cookie parsing/signature verification failure
- Unexpected loader/action errors
- Error UI can be minimal but should be user-friendly
Constraints To keep the scope reasonable:
- ❌ No database (D1, KV, external DB not required)
- ❌ No authentication system
- ❌ No complex UI or styling
- ✅ Hard-coded article data is acceptable
- ✅ TypeScript is strongly recommended
Deliverables
- GitHub repository URL
- Development process documentation
- Deployment to Cloudflare Workers
- A demonstration video recorded by yourself after development is completed
