Plan a multi-page AI application before you build
Map routes, user journeys, state ownership, service dependencies, and acceptance checks so a multi-page app is more than linked mock screens.
By Uvilno · 8 min read · Updated
Written by the Uvilno team. Examples illustrate the workflow; service availability and third-party requirements should be checked before launch.
Read as MarkdownStart with one complete journey across the app
Write the journey with sample inputs and expected outputs. ‘Add a book’ becomes ‘Enter a title, save it, return to the list, and see that title once.’ ‘Edit a note’ becomes ‘Change the text, save, reload, and read the new text.’ These examples reveal duplicate saves, stale lists, and missing persistence while giving you a compact test script after generation.
A multi-page application is not simply a homepage plus several destinations. Its pages share state, identity, navigation, and rules about what a visitor can do. Start by writing one complete journey: a visitor understands the tool, signs in, creates a record, finds it again, changes it, and leaves safely. This exposes dependencies that a feature list hides. It also gives you a way to decide whether the first release is actually usable.
Choose one primary job for the first version. A personal reading journal can support adding books and notes without becoming a social network, bookstore, recommendation engine, and subscription service at once. Put later ideas in a separate list. Smaller scope is useful when it creates a complete loop, not when it removes the save action or hides an unfinished route. Every promised part of the first journey should work before adding a second major workflow.
Map routes to purpose, access, and actions
For each route, record its audience, purpose, required data, and main action. A public introduction explains the product; a private list shows the current visitor's records; an edit view changes one record. Identify how someone reaches the route and what happens if they open it directly. Do not rely on a previous page silently preparing essential state. A bookmarked URL and a refresh are normal browser behavior, not unusual edge cases.
State whether you need actual separate pages or a section on one page. In Uvilno's supported multi-page static frontend, each approved route should have real content; an anchor on the homepage is not a substitute for a requested route. Keep navigation labels stable and show the current location. For private routes, define the signed-out destination and whether a visitor can return to the intended task after authentication. Avoid losing their safe unsent input during that transition.
Scroll sideways for all columns.
| Route purpose | Access | Main action |
|---|---|---|
| Home | Public | Understand the app and begin |
| Login | Signed out | Start supported authentication |
| My Books | Signed in | Find and filter personal records |
| Add or edit a book | Signed in, own record | Validate and save changes |
| Profile | Signed in | Review profile and sign out |
Decide where every kind of state belongs
A form's unsent text, a selected filter, and a saved book record are different kinds of state. Temporary interface state can live in the current view. A preference may be browser-local. Private records that should survive across devices need a supported hosted service and authentication. Write down these boundaries before building. Without them, an app can look as though it saved data while merely keeping a JavaScript array until the next refresh.
Describe ownership as well as storage. In a personal app, each visitor reads and edits their own records. Shared workspaces and role-based administration require a different authorization model; do not infer that they exist because the interface has a team selector. Uvilno.db offers typed fields and declared references through a bounded hosted service, with optional transactional create/update/increment/notification rules. It is not arbitrary backend provisioning. If your application needs scheduled processing, cross-organization permissions or custom server logic, identify that as separate development or a supported external service and verify it independently.
- Unsent form text has a clear lifetime.
- Local preferences are labelled as browser-local.
- Saved private records use a real hosted service.
- Record ownership is checked beyond the visible interface.
- Unsupported backend requirements are identified before generation.
Write an interaction contract for each important control
A control needs a trigger, a state transition, and a visible result. For a save action, specify validation, pending feedback, successful persistence, and a recoverable failure. For a filter, define which records it affects and what happens when none match. For deletion, decide whether confirmation or undo is appropriate and where focus goes afterward. These small decisions make the difference between an application and a collection of styled components.
Keep actions consistent across routes. If a record changes on an edit page, the list should reflect that change when the visitor returns. If a delete request fails, the record should not vanish permanently from the interface as if it succeeded. Avoid duplicate submissions and stale success messages. Describe these outcomes in ordinary language; you do not need to dictate a particular state-management library to make the expected behavior precise.
Example brief · replace with your details
When Save is selected, validate the title, show a pending state, and persist through the managed personal-record service. Navigate back to My Books only after success. On failure, retain the text and explain how to retry. Returning to the list must show the saved title without a manual full-page refresh.
Use the plan to resolve decisions before generation
In Uvilno, Plan mode returns a readable proposal in the conversation. Review its page map, service needs, and intended interactions, then use the explicit approval action when the proposal matches your goal. Planning does not expose private source architecture to a locked project. It is a product discussion that prepares a build. Ask for a revision when the plan invents a service, misses a route, or turns private persistence into a local demonstration.
Approval is tied to the current project, brief, draft revision, and base version. If those change, a new approval may be needed. This protects you from building an old plan against a different project state. Planning involves actual processing and can count toward usage, so use it for meaningful uncertainty. A tiny text change on a finished page usually needs a focused edit rather than a new application-wide planning exercise.
Turn the plan into a route and behavior test map
After the build, test every required route directly and through navigation. Reload private and nested pages, use Back and Forward, and try the main journey on a phone. Check the actual expected page content rather than accepting any heading as proof the route exists. A polished platform 404 is still a missing page. Confirm that menus, dialogs, and keyboard focus behave correctly as you move between views.
For data, create a record, reload, edit it, delete it, and repeat with a second account. Test the empty state after deletion and a failed request without losing input. For service dependencies, test consent cancellation and the deployed origin separately from the preview. Record the first failing step with the route, state, action, and visible result. This produces a useful correction request and prevents a broad redesign from hiding the original behavior problem.
Scroll sideways for all columns.
| Area | Test | Evidence |
|---|---|---|
| Routes | Open and reload every required URL | Expected content and successful response |
| State | Save, navigate away, and return | The same saved record is visible |
| Privacy | Repeat with two accounts | Records stay with their owner |
| Recovery | Cancel auth or simulate failure | Useful input and a real retry remain |
| Phone | Complete the whole task | No blocked action or overflow |
Expand through complete, reviewable slices
Once the first journey works, add a related capability as another complete slice. A status filter is a smaller extension than a public social feed. Describe how the addition changes routes, state, ownership, and failure handling. Preserve a known-good version before the larger change and test the existing main journey afterward. A saved version gives you a recovery point; it does not prove that new changes are safe to publish.
Before export, record hosted dependencies and the service configuration needed on your chosen domain. Source unlock releases the frontend files, not a separately provisioned database or identity system. Keep a release note listing the completed journey and any deliberate limits, such as personal records rather than team collaboration. A small app with honest boundaries is easier to maintain, hand off, and extend than a large interface whose underlying behaviors were never decided.
Common questions
Do multiple navigation links prove an app is multi-page?
No. Verify each required route opens directly, reloads correctly, and contains the expected content. Homepage anchors do not replace separate routes when separate pages were requested.
Does adding login solve the data model?
No. You must define persistence, record ownership, supported operations, and recovery states. Authentication identifies a visitor; authorization still controls their records.
Prepare your own brief
Adapt this starting point to your project. You can name the project and review the text before you explicitly send a build.