> For the complete documentation index, see [llms.txt](https://anthonyyoo.gitbook.io/atlas-grid/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://anthonyyoo.gitbook.io/atlas-grid/how-i-built-atlasgrid.md).

# How I Built AtlasGrid

## The main technical decisions behind the prototype

I built it to explore a difficult product question: how do you turn a large collection of screens and user actions into something a product team can actually understand and use?

## 1. How the application fits together

At a high level:

* **Next.js routes choose the page.** They stay small and hand the work to the complete workspace experience.
* **The workspace coordinates features.** It brings together app selection, search, graph loading, editing controls, and error states.
* **The application keeps its core rules separate from the interface.** Calculations such as screen connections, percentages, and branch selection do not depend on React or the graph library.
* **Adapters translate between the core graph logic and the technology using it.** The React Flow adapter turns graph data and calculations into the visual nodes and connections shown on the canvas. Data adapters translate API responses into the graph model used by that core logic. This keeps the rules independent from the interface and data source.

Automated checks make sure browser code cannot accidentally access server-only systems. This keeps responsibilities clear and helps prevent architectural mistakes as the project grows.

### Giving each kind of state one owner

| Information                                  | Owner                       | Reason                                                                                      |
| -------------------------------------------- | --------------------------- | ------------------------------------------------------------------------------------------- |
| Original graph loaded from the server        | TanStack Query              | It handles loading, caching, errors, and refetching.                                        |
| Which app is open                            | The URL                     | Refreshing, sharing a link, and using Back or Forward should open the same app.             |
| This visitor's rearranged screen positions   | Browser storage             | Visitors can arrange the demo without needing an account or writing to the shared database. |
| Selection, dragging, undo, and save feedback | Zustand                     | These interactions need to be shared across the workspace but do not belong on the server.  |
| Pan and zoom                                 | React Flow                  | These are temporary canvas interactions.                                                    |
| Connections, labels, and branch results      | Plain calculation functions | They can be calculated from the graph instead of stored again.                              |

The key rule is that one owner does not copy everything from another. Zustand, for example, stores only the positions that changed. It does not keep another complete copy of the graph already loaded by TanStack Query.

This made the system easier to reason about. When something changes, it is usually clear which part of the application is responsible.

## 2. Keeping the graph movements performant

The larger Finch example contains 121 screens and 121 visible connections. My first editable version did too much work whenever a screen moved. Even if only one screen changed, it recalculated almost every connection in the graph.

I measured the slow path before changing it. The optimized version now:

* publishes at most one position update per animation frame;
* keeps an index of the connections attached to each screen;
* recalculates only the screens and lines affected by the movement;
* reuses unchanged React elements instead of rebuilding them; and
* waits until movement finishes before doing less urgent whole-graph work.

## 3. What I simplified along the way

Some of the most valuable decisions involved deleting work that no longer fit the product.

### Calculating connections instead of storing them

The early read-only graph stored detailed instructions for every line: which side of a screen it used, its curve, and where its label belonged.

That worked while screens never moved. Once the canvas became editable, those saved instructions became stale whenever a screen changed position.

I replaced them with a simpler rule: store which screens are connected, then calculate the line from their current positions.

This removed:

* saved route and label data;
* several database and API fields;
* special handles for individual connections;
* caches for saved attachment points; and
* duplicate preview implementations.

### Saving personal layouts in the browser

I originally built server autosave with revisions, conflict handling, retries, and atomic multi-screen updates. It was a useful exercise, but it did not match what was required for a shareable prototype.

The prototype has no user accounts or collaboration.

The final version treats the server layout as the shared original and stores each visitor's changes in that browser. This removed public write endpoints, network conflict handling, and the possibility of one visitor changing the layout for everyone else.

The browser record is still carefully validated. It is tied to the exact app, view, and baseline; has size and position limits; rejects malformed data; and can be removed with the **Restore original layout** button.

## 4. Testing the important behavior

I used different test layers for different kinds of risk.

* **Unit tests** cover graph rules, percentage calculations, connection geometry, branch selection, bounds, and browser-record validation.
* **Adapter tests** verify that API data and graph data are translated correctly for the browser and React Flow.
* **Component and workspace tests** cover loading, errors, selection, movement, undo, save failures, and restoring the original layout.
* **Database tests** cover migrations, constraints, repeatable seeding, and safety rules.
* **Playwright tests** exercise the complete experience in a browser, including routing, search, dragging, multi-selection, branch selection, reload, and browser-local persistence.
* **Performance profiles and visual checks** cover frame timing, Storybook states, accessibility, and the final rendered UI.

### Accessibility

The graph is not designed only for pointer input. A visitor can operate a screen's context menu without a mouse:

1. Press **Tab** until the desired screen is focused.
2. Press **Shift+F10** or the keyboard's dedicated **Context Menu** key to open its menu. On a Mac keyboard, **Fn+Shift+F10** may be required when the function row controls system features.
3. Use **Arrow Up** and **Arrow Down** to move between actions.
4. Use **Home** to move to the first action or **End** to move to the last. Most Mac keyboards use **Fn+Left Arrow** for Home and **Fn+Right Arrow** for End.
5. Press **Enter** or **Space** to choose the focused action, or **Escape** to close the menu without choosing one.

After an action is selected or the menu is dismissed, focus returns to the screen that opened it. Screens can also be moved with the keyboard. Selection and save changes are announced to assistive technology, focus remains visible, and decorative motion respects reduced-motion preferences.

## 5. Potential product directions

A future version of AtlasGrid could help teams move between different levels of detail. Users could begin with a simple overview, explore a product area, focus on a specific flow, or open the Full graph and choose the layout that best answers their question.

The basic path would be:

* **Overview:** understand the app at a glance.
* **Product area:** explore one broad part of the app.
* **Flow:** follow one specific user task.
* **Full graph:** see every screen and connection.

### Start with an overview

The Overview would represent the app as a small number of connected product-area boxes. Each box would show the product-area name and its main flows. Lines between boxes would mean that users can move from a screen in one area to a screen in another.

![Overview with connected product areas and their primary flows](https://1858062725-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhbmnIvjThG6gbS5gbPkP%2Fuploads%2Firhy2aRBfBEvheyTKLvy%2Fgitbook-overview.svg?alt=media)

A user could:

* select a product-area box to see all of its related screens and flows;
* select a flow name to open only that journey;
* open the Full graph to see the entire app.

Each line would summarize the screen-level transitions between two areas. The Overview would not draw every individual connection, which would make a large app difficult to scan.

### Product areas and flows

A **product area** is a broad part of the app, such as Food logging, Progress tracking, or Account. A **flow** is a specific task a user completes, such as scanning and logging food or reviewing weekly progress.

One product area can contain several flows:

* **Food logging**
  * Search for and log food
  * Scan a barcode
  * Log a saved meal
  * Enter food manually

A flow can also cross more than one product area. For example, an onboarding flow might begin in Account and finish in Subscription.

### Explore a product area or individual flow

Opening a product area would show its screens and connected flows together in a clear left-to-right arrangement. Opening a specific flow would narrow the graph to only the screens and transitions needed for that journey.

### Choose a Full graph layout

The Full graph would always contain the same screens and connections, but users could choose how those screens are arranged.

#### Current layered layout

The current layout places screens from left to right. Screens at a similar point in the journey sit in the same column, and arrows show where users can go next.

It is the clearest option for following steps, branches, and longer journeys, so it would remain the default full graph layout.

![Screens arranged from left to right in the current layered layout](https://1858062725-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhbmnIvjThG6gbS5gbPkP%2Fuploads%2F82xKmPfATqjpMK99P5rs%2Fgitbook-layered.svg?alt=media)

#### Radial layout

The radial layout places an important starting screen, usually Home, in the center. Screens that are one step away form the first ring, while screens that take more steps to reach sit farther out.

It quickly shows what is central to the app and how far other screens are from the starting point.

![Home at the center with screens arranged in rings by distance](https://1858062725-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhbmnIvjThG6gbS5gbPkP%2Fuploads%2F0gIPRFN8gsxNZjclYMDL%2Fgitbook-radial.svg?alt=media)

#### Force-directed layout

The force-directed layout reveals the app's natural structure by letting the connections determine where each screen is placed.

Highly connected screens tend to settle near the center. Screens that are closely related gather nearby, while less-related groups spread farther apart. This can reveal important hubs, natural groups, and unexpected connections.

It is useful for exploring the overall network, although it is less direct than the layered layout when someone wants to follow an exact step-by-step journey.

![A highly connected Home screen near the center with related screens grouped nearby](https://1858062725-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhbmnIvjThG6gbS5gbPkP%2Fuploads%2FkgYCuWsEFE2GCIQetV9o%2Fgitbook-force-directed.svg?alt=media)

#### Clustered layout

The clustered layout places individual screens inside labeled product-area boxes. Connections remain visible within each box and between different areas.

It makes a large Full graph easier to scan while still showing every screen. The clusters can surround Home so the main connections enter each area without crossing through unrelated groups.

![Individual screens organized inside product-area clusters around Home](https://1858062725-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FhbmnIvjThG6gbS5gbPkP%2Fuploads%2FTJIh8ASvNa8jxZ8Iu7wF%2Fgitbook-clustered.svg?alt=media)

The clustered Full graph is different from the Overview. The Overview shows one high-level box for each product area and hides the individual screens. The clustered Full graph shows the individual screens inside those boxes.

## Supporting technical material

* Frontend architecture
* Technical specification


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://anthonyyoo.gitbook.io/atlas-grid/how-i-built-atlasgrid.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
