Web Service SPA Source Tree
HiNC-2025-webservice/wwwroot-src/src is the flagship front end: a Quasar CLI single-page
application in Vue 3, TypeScript and Pinia, served by the same ASP.NET Core process that answers its
REST calls. Every page in Anatomy documents something in this tree or in the backend beside it.
Folders below follow the stock Quasar skeleton order, with the two places the skeleton breaks called out where they occur.
The One Thing to Know First
components/ is grouped both ways at the same level, and that is deliberate rather than untidy:
- Page-scoped —
components/execution/and half ofcomponents/mech/are chrome for exactly one route. - Domain-scoped —
components/geom/,components/topo/,components/toolhouse/,components/spindle/andcomponents/mission/are pulled in from wherever the domain surfaces, most often the Control Tree. - Primitives —
components/widgets/andcomponents/panels/have no domain at all and are the most-imported folders in the application.
So a component's folder does not tell a reader who mounts it. components/mission/ has no Mission
page — /mission redirects into the Execution page's tree — and no folder is named for the
workpiece at all: its editors are Control-Tree panels.
The second break is history. The application has been re-architected repeatedly, and because
Control-Tree node ids ride in ?tree= links they are a public surface: every regroup adds a
migration hop rather than rewriting the last one. The residue is visible in wwwroot-src/src/router/routes.ts, where a large share of the table is
redirects preserving URLs from earlier architectures — a route existing there does not mean a
page exists for it.
Root and Boot
wwwroot-src/src/App.vue— not the shell. It is a bare router view plus the once-per-load wiring that subscribes the project store to the execution-status hub. The real shell iswwwroot-src/src/layouts/MainLayout.vue. Documented in Session State.wwwroot-src/src/boot/auth.ts,wwwroot-src/src/boot/i18n.ts,wwwroot-src/src/boot/routine-toast.ts— Quasar boot files, run once before mount and in a declared order. The auth boot file patches the global fetch and inspects every 401, which is why no API module carries its own 401 handling — but the redirect it can raise is conditional: it fires only while the auth store reports the login gate enabled, and not when the router is already on the login route, so on a build with the gate off a 401 redirects nowhere. The toast boot file patches the shared notify helper so every toast is mirrored into the footer history without touching a call site. Documented in Login and Authentication and Internationalization.wwwroot-src/src/layouts/MainLayout.vue— the shell: menu bar, the routed page container, footer. It also owns the mechanism every page depends on and no page implements: a project epoch, bumped when the loaded project changes, is the keep-alive key, so a project change destroys and rebuilds every cached page. Documented in Main Panel and Session State.wwwroot-src/src/product/— the product module: the parts of the shell a host that builds this SPA may supply for itself, imported through the build-time aliasproductrather than by path.wwwroot-src/quasar.config.tsresolves the alias to this folder unlessHINC_PRODUCT_SPAnames, as an absolute path, another folder with the same exports, which the build then compiles in this one's place; the menu bar imports each of them by name. What is here is the web service's own choice for each part, andwwwroot-src/src/product/index.tslists the exports:VersionBadge, the version mark beside the menu bar's logo (wwwroot-src/src/product/VersionBadge.vue, an outlined badge readingv+ the version the auth store holds);HelpMenuItems, the items appended to the Help dropdown after the Log Viewer (null, so Help ends there); andCloudStatusBadge, the cloud licence badge the menu bar shows on every page after the connection badge and before the sign-out button (null, so the bar shows none).wwwroot-src/src/product/boot.tsis the last entry of the declared boot order,'~product/boot', and is empty: Quasar skips a boot file with no default export. The same config deduplicatesvue,quasar,pinia,vue-i18n,vue-routerand@quasar/app-vite, so a module folder outside this tree — whose files import only those packages and the app's own aliases (src/…,stores/…,components/…) — resolves them to the app's one copy. Such a folder keeps its strings in namespaces of its own, one bundle per locale, which its boot file merges into the app's bundles, where a repeated namespace would let one side's strings overwrite the other's (whichever bundle merges last wins); while the variable is set,npm run lint:i18nscans that folder as well and refuses a namespace that repeats one of the app's, and a locale the folder leaves out, in which its strings would show in English. Documented in Main Panel and Hosting from another project.
The REST Edge
wwwroot-src/src/api/ is one thin typed module per backend controller family — functions, DTO types
and kind unions, no Vue code. This is the tightest correspondence between the two halves of the
application: each module wraps one named controller almost one-to-one.
wwwroot-src/src/api/http.ts— the shared response layer. Its own header names the modules that deliberately bypass it, so “every API module goes through it” would be wrong.wwwroot-src/src/api/index-service.ts— not a barrel file. It wraps the backend's keyed object store, which is where thekeystring threaded through the whole application comes from. Documented in Object Store (IndexService).wwwroot-src/src/api/equipmentTopology.ts— the one module whose routes take an owner segment (machine-tool,fixture,workpiece, andequipmentfor the worktable attachment) rather than a key: the equipment topology graph, roles and editing. Documented in Equipment Topology.
Components
wwwroot-src/src/components/— the shared top level:wwwroot-src/src/components/AppMenuBar.vue,wwwroot-src/src/components/AppFooter.vue,wwwroot-src/src/components/RenderingCanvas.vue,wwwroot-src/src/components/FileExplorer.vuewith the two viewers it slots in for a file the text editor does not take —wwwroot-src/src/components/CsvStripPane.vuefor a.csvandwwwroot-src/src/components/PagedTextViewer.vuefor a file over the editor's size cap —, andwwwroot-src/src/components/StlPreviewPane.vue. The canvas does not render locally: it opens a SignalR connection and paints server-rendered frames, which is why several pages each own a canvas bound to a different backend scene. Documented in Rendering Canvas on Web Service, File Explorer and STL Preview Pane.wwwroot-src/src/components/controlTree/— the largest folder undercomponents/by a factor of two, and a registry-driven panel system rather than a folder of tree widgets.wwwroot-src/src/components/controlTree/itemTypes.tsand its domain siblings map an item-type string onto a panel component and a child-building function;wwwroot-src/src/components/controlTree/useControlTreeHost.tsis the state machine that builds the tree, gates a dirty selection switch, and syncs the selection with the URL; the many panel components are the editors the registry resolves. It serves three consumers, not one — the Execution, Equipment and Tool House pages each instantiate their own scoped host (execution,equipment,toolhouse) and render the same two panes,wwwroot-src/src/components/controlTree/ControlTreePanel.vueandwwwroot-src/src/components/controlTree/PrimarySlavePanel.vue— stacked as the rows of the Execution page's left dock, side by side as columns on the other two. The Execution and Equipment hosts keep the selection in?tree=; the Tool House host is rooted at the one tool picked in the page's tool list and keeps the selection in the URL path. Documented in Control Tree — the folder's own page — with Execution Page, Equipment Page and Tool House Page for the three consumers, and Program Branch, Step Variables Branch and Step Colors Branch for the NC-program, step-variable and color-tree item types and panels that live in this folder. The nineteenSoftNc*panels and their registry are a wave of their own, documented under Controller Branch: which of them the tree mounts at all is decided by Brand Matrix, and what they share is Editing Contract.wwwroot-src/src/components/controlTree/toolhouse/— the Tool House tree's panels. Easy to confuse withwwwroot-src/src/components/toolhouse/: these are the panels the registry mounts, that folder holds the content fragments those panels embed plus the page's tool canvas panel and its Gallery view (ToolHouseGallery.vuewith its placement maths intoolSilhouette.ts), and the dependency runs one way only.wwwroot-src/src/components/execution/— the run cockpit's own panels, plus itscharts/sub-folder, the uPlot charting layer, and itsblockInfo/sub-folder, the Block Info panel's CNC view. Not purely page-local:wwwroot-src/src/components/execution/ExecutionToolBar.vueis mounted by the Control Tree pane, which pins it above the Execution page's tree, and the spindle contours chart imports from the charts folder. Documented in Execution Page, Block Info Panel, Strip Charts and Cycle-Line Charts.wwwroot-src/src/components/geom/andwwwroot-src/src/components/topo/— structural twins: one editor per kind, the samemodelKeyprop andchanged/erroremits, and a single kind → editor map —wwwroot-src/src/components/geom/geometryEditors.tsandwwwroot-src/src/components/topo/transformerEditors.ts— that is the source of truth for both the switchboard and the Control Tree. A new kind must be registered there, not merely dropped in the folder. “topo” means coordinate transformers, not mesh topology. Documented in Geometry Panels and Transformer Select Panel.wwwroot-src/src/components/widgets/— the reusable input library: numeric, vector and matrix inputs, the file-path input and picker, the CodeMirror text editor, the display-options and object-management menus. Documented in Widgets.wwwroot-src/src/components/panels/— pure layout machinery with no domain: the collapsible expansion panel and the resizable stack whose registration contract produces the “rows collapse in place” behaviour the tree pages describe. Documented in Control Tree, whose two rows in the Execution page's left dock are both expansion rows, and Session State for the keep-mounted flag that decides whether a collapse unmounts its content.wwwroot-src/src/components/mission/,.../toolhouse/,.../spindle/,.../preference/and.../mech/— the domain and page folders named above. The*Div.vuesuffix inside the Tool House folder is a convention carried over from the legacy Blazor components: a Div is an embeddable content fragment with no panel chrome. Inside.../mech/,wwwroot-src/src/components/mech/EquipmentTopologyPanel.vueis the Equipment page's Topology column,wwwroot-src/src/components/mech/MechanismRolesPanel.vuethe Roles section each mechanism root panel ends with, andwwwroot-src/src/components/mech/MechBuilderGraph.vuethe graph view that column draws with — its name is historical. Documented in Equipment Topology.
State, Routing and Text
wwwroot-src/src/composables/— three different concerns in one folder: hub access, shared domain state, and UI mechanics.wwwroot-src/src/composables/useSharedHub.tsis the reference-counted connection manager behind every hub composable, so a hub opens only while something consumes it.wwwroot-src/src/composables/useToolHouse.tsandwwwroot-src/src/composables/useSpindleCapability.tsare module-level singletons, not per-component instances.wwwroot-src/src/composables/useViewPrefs.tsstores layout state in the browser only — it is neither in the project file nor in the server's user config. Documented in Session State.wwwroot-src/src/composables/useEquipmentTopology.tsis a module-level singleton too — the equipment graph, roles, selection and armed role the Topology column and the three Roles panels share. Documented in Equipment Topology.wwwroot-src/src/stores/— four Pinia stores.wwwroot-src/src/stores/index.tsis not a barrel; it is the Quasar factory. Most shared state lives incomposables/instead. Documented in Session State.wwwroot-src/src/router/—wwwroot-src/src/router/routes.tsis the table plus the legacy redirects, andwwwroot-src/src/router/treeRoutes.tsis the load-bearing file its name understates: it holds the accumulated chain of tree-id renames and the id → page resolver, plus the pair of functions that turns a Tool House URL's tool number and node path into a tree id and back, and the spindle segment list the legacy/spindle-capabilityredirect maps onto tree ids. A route'smeta.titleholds an i18n key, not a title. Documented in Tree Ids and Routes.wwwroot-src/src/i18n/— five locales shipped together, each a list of namespace files. English is the schema, not merely a locale: the other four bundles are typed against it, so a key present in English and missing there is a type error undernpm run lintand a lint finding that stopsnpm run build. Keys are split by UI region rather than by source file, so there is no one-to-one mapping between an i18n file and a components folder. Documented in Internationalization and Translation Remarks.wwwroot-src/src/pages/— one file per route, and page size is a poor guide to importance: the Equipment page is small because it delegates almost everything to the Control Tree panes, the canvas panel and the Topology panel, while the File Explorer page is a thin wrapper around a large shared component.wwwroot-src/src/utils/,wwwroot-src/src/directives/,wwwroot-src/src/css/— small and mostly presentational. Two severity scales exist and must not be conflated:wwwroot-src/src/utils/messageSeverity.tsmaps the engine's diagnostic scale, while the footer's routine severity is a separate, shorter toast scale. Three of the helpers hold for typed text in every language:searchFold.tsfor the type-to-filter boxes,imeKey.tsfor an Enter that must not commit while an IME converts, andnumberText.tsfor a number typed in full-width digits; documented in Internationalization.
See Also
- Anatomy by Source Directory — the other two source trees, and how this layer is meant to be entered
- Web Service Backend Source Tree — the process that serves this application and answers its REST and hub traffic