Add developer documentation (REFERENCE.md and GUIDE.md)#12
Conversation
REFERENCE.md covers the overall system: what the app is, the tech stack, all five Cloudflare services (D1, KV, R2, Workflows, Assets), the full OAuth auth flow, storage at a glance, a codebase map, and access levels. GUIDE.md covers common development tasks for new contributors: using the Onshape Glassworks API Explorer, understanding Onshape document paths, adding new Onshape API wrappers, adding backend routes, modifying the DB schema with Drizzle, adding frontend routes with TanStack Router, and wiring up frontend data fetches with React Query. Co-Authored-By: Claude Sonnet 4.6 <[email protected]> Claude-Session: https://claude.ai/code/session_01JyPYTnfrcQbhgG76Z7bKYm
Covers JSX components, the .ts vs .tsx distinction and Vite Fast Refresh export constraint, factoring out composable components, hooks and the rules of hooks (with React docs link), custom hooks, and how SCSS/Mantine styling works in the project. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
|
|
||
| ## What Is This App? | ||
|
|
||
| FRCDesignApp is a part-library browser that runs **inside Onshape** as an embedded tab (technically an iframe). When a user opens an Onshape assembly document, they can open this app in a side panel, browse a curated library of FRC robot parts organized into groups, and click a part to insert it directly into their assembly. |
There was a problem hiding this comment.
part studio or assembly
Browse a curated library of parts
Click a part to insert it into an assembly or derive it into their part studio.
There was a problem hiding this comment.
The app reflects underlying Onshape documents that are owned and maintained by the FRCDesignLib team. Parts reflect the underlying Onshape documents; for example, part names come from the names of the underlying tabs, and configurations reflect the settings defined in Onshape.
There was a problem hiding this comment.
The app is hosted on Cloudflare. The frontend is served by Cloudflare as a Single Page Application (SPA) to the user's browser, meaning the frontend code loads and executes directly in the user's browser. The backend runs on Cloudflare, exposes endpoints for the frontend to call, and handles access to resources like the database and Onshape. For security, all communication with the Onshape API is routed through the backend.
|
|
||
| Queries go through **Drizzle ORM** so you write TypeScript instead of raw SQL. The schema is defined in `src/shared/schema.ts`. SQL migration files live in `drizzle/` and are applied automatically on deploy. | ||
|
|
||
| **Tables:** `libraries`, `groups`, `insertables`, `configurations`, `users`, `favorites` |
| - During the OAuth login flow, it briefly stores the OAuth `state` and the URL to redirect back to after login. | ||
| - After login succeeds, it stores the user's access token and refresh token, keyed to their session cookie. | ||
|
|
||
| KV is the right tool here because Cloudflare Workers are stateless — there is no in-memory session that persists between requests. KV gives us a fast, durable place to stash tokens between requests. |
There was a problem hiding this comment.
KV serves as a cheap, lightweight way to persist user data across multiple Cloudflare Workers (which Cloudflare automatically scales and provisions based on the app's current traffic).
|
|
||
| ### R2 — Thumbnail Storage (`c.env.THUMBNAILS`) | ||
|
|
||
| R2 is Cloudflare's object storage (similar to Amazon S3). The app uses it as a **thumbnail image cache**. |
There was a problem hiding this comment.
Cloudflare's blob storage, optimized for unstructured data like images and PDFs. The app uses it to store and cache thumbnails in order to improve reliability.
| 6. The callback handler reads the session from KV, verifies the `state` matches (preventing CSRF attacks), and exchanges the `code` for real access and refresh tokens using the [Arctic](https://arcticjs.dev/) OAuth library. | ||
| 7. The tokens are saved to KV under the session ID. The temporary login-session entry is deleted. | ||
| 8. The user is redirected back to the original `/init` URL, which now succeeds because the session cookie and tokens are in place. | ||
|
|
There was a problem hiding this comment.
Todo: talk about what loading looks like once it hits the client, /init saves off Onshape params into search params (app query string) and loads, then /app fetches client data (library version for cache busting, user preferences) in before load and kicks off some fetching in /loader, other loaders also run in parallel
|
|
||
| Use the `loader` approach when you want the data to be ready before the page renders (avoids a loading flash). Use React Query when you want to re-fetch in the background or share the data with other components. | ||
|
|
||
| ### 4. Navigate to the new route |
There was a problem hiding this comment.
This shouldn't be neccessary
|
|
||
| ### Posting data (mutations) | ||
|
|
||
| For actions that change data (POST, DELETE), use React Query's `useMutation`: |
There was a problem hiding this comment.
Add more detail, talk about our queryUpdater w/Immer, canceling outstanding queries, toasts, refetching/canceling afterwards
| | `useState` | Stores a piece of state; re-renders the component when it changes | | ||
| | `useRef` | Holds a mutable value that does **not** trigger a re-render | | ||
| | `useEffect` | Runs a side effect (e.g. set up a listener) after render | | ||
| | `useSyncExternalStore` | Subscribes a component to an external store (used for `localStorage` state in `ui-state.ts`) | |
There was a problem hiding this comment.
Don't talk about this one, talk about useLoader and useParams instead
REFERENCE.md: - Expand "What Is This App" with part studio/assembly mention, FRCDesignLib team ownership, and clearer frontend/backend split - Remove the Tables list from D1 section - Update KV description to explain multi-worker scaling rationale - Update R2 description to reviewer's preferred wording - Add "What happens on the client after auth" section covering /init search param retention, beforeLoad context fetch, and parallel loader prefetches - Remove Token refresh and SameSite cookie sub-sections - Simplify Codebase Map to high-level prose with key files per dir - Replace access levels table with prose noting admin=editor today GUIDE.md: - Add new "Path Params, Query Params, and Request Bodies" section covering semantics, frontend sending, backend reading, Onshape API - Expand migration section to explain what migrations are, commit expectations, and note about periodic squashing - Remove Step 4 (navigate to new route) from Adding a Frontend Route - Add useParams example to the route loading section - Expand mutations section with getQueryUpdater/Immer pattern, cancelQueries rationale, toasts, and onSettled explanation - Add props/hooks paragraph to JSX component section - Replace useSyncExternalStore hook row with useLoaderData/useParams - Add guidance on working around conditional hook constraints Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Summary
Adds two Markdown documentation files under
docs/aimed at new contributors who may not be familiar with Cloudflare Workers, Hono, or TanStack Router.docs/REFERENCE.md— System reference for understanding the app. Covers what the app is, the full tech stack with plain-language explanations, all five Cloudflare services (D1, KV, R2, Workflows, Assets) and why each is used, the complete OAuth auth flow step-by-step, a storage-at-a-glance table, a full codebase map with one-line descriptions per file/directory, and access levels (ADMIN/EDITOR/USER).docs/GUIDE.md— Developer task guide for implementing new features. Covers using the Onshape Glassworks API Explorer, understanding Onshape document paths (DocumentPath/InstancePath/ElementPathandapiPath()), adding new Onshape API wrapper functions, adding new backend Hono routes, modifying the Drizzle DB schema and generating migrations, adding TanStack Router frontend routes, and wiring up React Query data fetches and mutations.Test plan
apiPath()calls,queryOptionsusage)🤖 Generated with Claude Code
https://claude.ai/code/session_01JyPYTnfrcQbhgG76Z7bKYm
Generated by Claude Code