# Generated web surface

A scaffolded Fresh app contains both editable starter code and modules that are regenerated from route files. A file created by the CLI is not necessarily generator-owned. In particular, `ui:add page` output has no generated header banner; use the roles below to decide what to edit. All paths below are relative to the Fresh app root, such as `apps/dashboard/`.

| Surface | Role and ownership | How to change it |
| --- | --- | --- |
| `routes/catalog/index.tsx` | App-owned page created by `netscript ui:add page catalog`. Imports `definePage` from `@app/utils.ts` and binds `appRoutes['catalog']` from `@app/router.ts`. | Edit the page, metadata, view, and loaders. Move it together with its owned colocated files. |
| `routes/catalog/(_shared)/query-loaders.ts` | Editable server query loader, created when `--island` selects a service client. | Edit data loading and repair imports after a move. |
| `routes/catalog/(_islands)/CatalogIsland.tsx` | Editable client island created alongside that loader. | Edit the interactive view and its query inputs; keep its loader import in sync. |
| `router.ts` | Editable app route registry (`appRoutes`). `ui:add page` adds `createRouteReference('/catalog', { id: 'catalog', kind: 'page' })`. | Reconcile the literal URL, key, metadata `id`, and consumers manually after a move/removal. Vite manifest generation does not reconcile this registry. |
| `utils.ts` | Scaffolded, editable shared `define` and `definePage` wiring. | Keep app state and builder configuration consistent with page imports. |
| A sibling `*.contract.ts` | App-owned route contract sidecar, if you author one; not part of the `ui:add page` triad. | Move it with its matching page and reconcile schemas when parameters change. |
| `.generated/manifest.ts` | Generator-owned `routePatterns` tree derived from filesystem routes. | Refresh through the configured NetScript Vite plugin; do not hand-edit. |
| `.generated/routes.ts` | Generator-owned `routes` tree of bound references, using discovered contracts where present. | Refresh through the configured NetScript Vite plugin; update consumers when accessor keys change. |

The loader/island pair is optional: a page without `--island` has the page and registration only. `(_shared)` and `(_islands)` are co-location groups and do not add URL segments. Renaming component symbols is optional; updating their imports is necessary whenever the move changes relative paths.

## Refreshing the route tree

With `routeManifest` enabled in `createNetScriptVitePlugin`, the plugin writes the generated route modules on initialization and build, and refreshes them on relevant route changes during a dev server run. Use the app's configured Vite build or dev task after a move. A standalone `deno check` does not refresh these modules. Run `netscript generate routes --app dashboard` to refresh them without a Vite build; `--project-root <app-root>` selects an explicit application.

The plugin also manages route-binding seams for the authoring forms described in [Routing and route contracts](https://rickylabs.github.io/netscript/web-layer/route/#three-authoring-forms-one-generated-binding). That does not make the separate string-literal `appRoutes` registry track filesystem renames.

## Rename safety and manual lifecycle

After regeneration, a removed accessor such as `routes.catalog.$route` fails type checking at consumers that still reference it. `appRoutes['catalog']`, however, can keep compiling after a folder move because its pattern is a string literal. Typed href parameters do not prove that a route file exists at that URL.

Use the [Renaming or Moving a Route checklist](https://rickylabs.github.io/netscript/web-layer/route/#renaming-or-moving-a-route) to reconcile the directory, colocated files, `router.ts`, page binding, navigation, and generated tree. Verify the new URL and loader/island behavior in the running app as well as type checking.

For a move from `routes/catalog/` to `routes/inventory/`, change the `router.ts` pattern from `/catalog` to `/inventory`. The registry key and metadata `id` are identifiers, not URL segments: you may keep `catalog`, or rename both to `inventory` and update the page to `.withRoute(appRoutes['inventory'])` and every consumer of the old key. Remove obsolete or duplicate registrations. Search for the old URL and generated accessor too; check navigation, redirects, and partial pairings. If parameters change, reconcile path schemas and href inputs. After refreshing the tree, type-check and visit the new URL, including any loader and island. Decide whether the old URL should return 404 or needs an authored redirect for existing links.

There is currently no `netscript ui:rename` or `netscript route rename` command. `netscript ui:remove <name>` removes a copied Fresh UI registry item. Use `netscript ui:remove page catalog --dry-run` to validate and preview a page removal. Without `--dry-run`, it deletes only unchanged `ui:add page` output (page plus optional loader/island), prunes its generated string-literal router registration, and regenerates the derived route modules. It preserves authored siblings, sidecars and unrelated routes. Use `--client <service>` when the original data client is ambiguous. Formatting with the scaffold’s `deno task fmt` is accepted: scaffold files are compared after Deno formatting, and wrapped router entries are recognized. Code or comment edits, missing scaffold parts and customized registrations are refused; there is no force override. Remove customized pages manually, prune their registration and consumers, then run `netscript generate routes`. Idempotent reruns rebuild missing derived modules without deleting authored files and report “Nothing to remove” for an absent page. Empty parent directories are pruned without removing the routes root or authored siblings. Update links and type-check after removal.
