Picking the feature
What ships well across surfaces.
Before diving into four implementations, pick the right feature to build. Not every feature ships well on every surface β some are web-first, some are mobile-first, some only make sense on desktop. The wrong pick wastes the chapter.
Our pick β Bookmarks
Bookmarks: let the user save products to a personal list, view them, remove them. It's our running example for the next three lessons. Why?
- Simple data model. One table:
bookmarks(id, user_id, product_id, created_at). - Cross-surface obvious. Users expect to bookmark on phone, see it on web. Multi-platform is the value.
- Trivial offline story. Save bookmark offline β push when online. Good for chapter 4.
- Shows the shared layer. One type, one Zod schema, three frontends.
The decision rubric
For any feature, ask:
- Where do users START? If 90% of usage is on mobile, build mobile first. Don't force a desktop UI for a feature nobody opens desktop for.
- Where do users FINISH? "Quick-add on mobile, manage on web" is a common pattern. Lean into it; don't replicate the full UX on every surface.
- What HARDWARE matters? Camera β mobile-first. Keyboard shortcuts β desktop/web. Push notifications β mobile + web; not desktop (usually).
- Can it survive offline? If yes, mobile + desktop need a sync story. If no, fail fast with a clear error.
Examples by category
- Web-first / mobile read-only: Admin panels, billing, settings. Power-user features. Heavy form work.
- Mobile-first / web view-only: Photo capture, location check-in, "quick action" flows.
- Desktop-first: File I/O at scale (batch import / export), offline-tolerant tools, long-running tasks (PDF generation), shortcuts-heavy workflows.
- Equal across all: Bookmarks, comments, notifications, profile. Light data, mostly read.
What we'll build over the next 3 lessons
Bookmarks, end to end:
- API β POST
/api/bookmarks, GET/api/bookmarks, DELETE/api/bookmarks/:id. (We'll touch this briefly β the focus is the four frontends.) - Web β bookmark button on a product page, /bookmarks list page.
- Mobile β heart icon on product card, dedicated Bookmarks tab.
- Desktop β keyboard shortcut (Cmd/Ctrl+D), bookmarks sidebar.
Same backend, three different presentations playing to each surface's strengths.
Quick API scaffold (we'll trust this and move on)
Use the resource generator so we can focus on the frontends:
- Run
grit generate resource Bookmark user_id:uint product_id:uint - That gives us model + handler + routes + Zod schemas + TS types.
- Add an auth gate so users can only see their own bookmarks (we'll show the snippet next lesson).
Quick check
Try it
Set up for the next three lessons:
- Run
grit generate resource Bookmark user_id:uint product_id:uint - Edit the generated handler so the LIST endpoint only returns bookmarks for the authed user (filter by
user_id = c.GetUint("user_id")). - Add a unique index on (user_id, product_id) so a user can't bookmark the same product twice.
- Run
grit syncto update shared types. - Use Postman / curl to POST a bookmark and GET the list. Confirm the auth gate works.
Once that's green, you're ready for the implementation lessons.
What's next
Next lesson β Web implementation. Bookmark button, list page, optimistic UI updates with React Query.
Spot a typo? Have an idea?
Help us improve this lesson. One click opens a GitHub issue with the lesson URL pre-filled β suggest clearer wording, report a bug, or request more depth. The course keeps improving thanks to learners like you.
Suggest an improvement on GitHub