This repository contains the MedRush Agents Hub frontend. The checked-in app is a lightweight Preact single page application under portable/, with a small custom Node/esbuild toolchain and root-level shell wrappers for local development and CI.
The project is currently frontend-only. There is no runtime backend service, database, or deployed API client in this checkout. Several folders such as src/api, src/contexts, src/registry, and src/transformers exist as extension points.
.
+-- config.sh # Selects the active app directory for dev.sh
+-- dev.sh # Root command dispatcher: dev <command>
+-- scripts/ # Local command wrappers and help docs
+-- ci/ # GitHub/CI automation scripts
`-- portable/ # Preact app, build pipeline, assets, styles
+-- core/ # Custom build/server/resolver scripts
+-- public/ # HTML template, icons, fonts, preview image
+-- assets/ # Static app assets copied to dist/assets
+-- styles/ # Source CSS copied to dist/styles
+-- src/ # TypeScript/Preact source
`-- dist/ # Generated build output
config.sh sets DEV_APP="portable", so root commands operate on the portable/ app.
The browser loads portable/public/index.html, after the build step has replaced metadata placeholders from portable/meta.json. The page loads:
styles/index.cssfor global and component styles.app.js, the esbuild bundle generated fromsrc/main.tsx.- Static images, fonts, and assets from
public/andassets/.
At runtime, src/main.tsx mounts a Preact app into #app and renders HomePage. HomePage uses the small router in src/utils/router.tsx with path segments from src/utils/path.ts. The current route table is empty, so unknown or root paths fall back to the home layout, which renders HomeView.
The current product UI path is:
src/main.tsx
`-- routes/home.tsx
`-- components/view/home-view.tsx
`-- components/block/about.tsx
`-- components/kit/trip-info.tsx
About currently defines a hard-coded TripData[] and renders one delivery option through TripInfo.
portable/src/routes contains page-level routing entry points. home.tsx defines the HomePage route and a Layout component. Routing is intentionally simple:
useForwarded()splitswindow.location.pathnameinto path segments.useRouter()picks the first segment and checks it against a route map.- If no route matches, the layout receives a
dynamicvalue and can render fallback content.
The static server also falls back missing paths to index.html, so client-side routes can be loaded directly.
portable/src/components/view contains page-level view composition. HomeView wraps the home content in ScrollPop.
portable/src/components/block contains larger content blocks. About is the current primary block and owns the placeholder trip data displayed to agents.
portable/src/components/kit contains reusable product-level components:
TripInforenders a delivery payout summary fromTripData.Infolet,Textlet, andLinkletare reusable display/link components.SectionandScrollPopprovide layout primitives for composed sections.
These components depend on lower-level UI primitives and generated class-name helpers.
portable/src/components/ui contains small building blocks:
structure:Container,LimitWidth,Image,NodeBG.text:Heading,Text,LineBreak.interactive:Clickable,Link.
These primitives are intentionally thin wrappers around HTML elements and use CSS class names generated by the build pipeline.
portable/src/interfaces/trip-data.ts defines the current delivery data contract:
Location: name, latitude, longitude.TripData: pickup locations, drop location, scale, payout, and time/distance stats.
portable/src/data/index.tsx defines a generic DataProvider/useData context with per-API subscriptions, but it is not currently mounted by main.tsx. It appears to be scaffolding for future shared data refresh behavior.
portable/src/utils/subscription.ts provides the subscription primitive used by the data context. portable/src/utils/generators.ts provides randomId().
The app uses a custom build script in portable/core/build.mjs instead of a framework CLI.
Primary inputs are:
portable/src/main.tsxportable/public/portable/styles/portable/assets/portable/meta.jsonportable/src/components/
Build output is written to portable/dist/:
app.jsandapp.js.map- copied and processed
index.html - copied styles under
dist/styles - copied assets under
dist/assets - copied public files such as fonts, logo, and preview image
portable/dist is generated and should be treated as build output.
core/build.mjs creates an esbuild context with:
- entry point:
src/main.tsx - output:
dist/app.js - JSX runtime: Preact automatic JSX
- target:
es2020 - aliases matching
tsconfig.jsonpaths, such as@components,@routes,@utils,@styles, and@assets - minification enabled for production builds and disabled for dev builds
Before bundling, matchComponentsCssFiles() scans src/components for .tsx and .jsx files. It ensures matching CSS files and index.css import files exist under styles/app.
Then buildStyles() scans CSS class names from portable/styles and writes portable/src/styles/styles.ts. The generated module exports:
ClassNamePossibleClassNameuseClasses(...args)
Components import useClasses from @styles to avoid hand-typed class string assembly.
buildAssets() scans portable/assets and writes portable/src/assets/assets.ts. The generated module maps asset names to public URLs under [[url]]/assets/..., using the root URL from meta.json.
Components can import useAsset from @assets when they need asset URLs.
metaCopyDir() copies files from public/, styles/, and assets/ into dist/. For .html, .css, and .js files, it replaces [[key]] placeholders using values from meta.json.
The replacement loop runs twice so nested values such as "image": "[[url]]/preview.png" resolve after url is substituted.
Root-level development uses dev.sh:
source dev.sh
dev help
dev setup
dev run
dev build
dev startThe command dispatcher loads config.sh, finds a matching script in scripts/, and runs it against $DEV_APP.
Important commands:
dev setup: installs npm dependencies inportable/.dev run: runsnpm run dev, which starts watch mode and a dev server.dev build: runsnpm run build, which writesportable/dist.dev start: builds and starts a static server forportable/dist.dev install: forwards tonpm installinsideportable/.
The app-level npm scripts are:
{
"dev": "node core/build.mjs dev",
"start": "node core/build.mjs start",
"build": "node core/build.mjs build"
}The server defaults to port 3000 and can be overridden with PORT.
portable/core/server.mjs implements a small Node HTTP server:
- Serves files from
dist/. - Maps
/toindex.html. - Falls back missing paths to
index.htmlfor SPA routing. - Sets MIME types for common static files.
- Uses
Cache-Control: no-cachein dev andpublic, max-age=600in start mode.
portable/styles/index.css imports:
core/fonts.csscore/variables.csscore/base.cssapp/index.css
styles/app/index.css imports component-layer style indexes. Component styles are organized to mirror src/components, and the build script can create missing component CSS files and index imports automatically.
The ci/ directory contains shell automation intended for GitHub workflows:
ci/publish/main.sh: buildsportableand force-publishesportable/disttogh-pages.ci/summary/main.sh: creates an AI-generated PR summary using an external$URLendpoint,$TOKEN,gh,jq, and PR environment variables.ci/tagger/main.sh: suggests and applies labels through GitHub CLI using an external AI endpoint.ci/leaks/checker/__main__.py: early scaffolding for import/module boundary checks.ci/format/main.shandci/leaks/main.sh: currently empty placeholders.
These scripts assume a git repository and required CLI tools/environment variables. The current local workspace is not itself a git repository.
Runtime dependencies:
preact: UI rendering.@attaditya/iconoir-preact: icon components. This package is not fully ready for broader use in this app; only direct icon components are currently considered usable. Provider-level APIs from the package should not be relied on yet.
Development dependencies:
esbuild: bundling and watch mode.typescript: type checking and TypeScript support.
The app is configured as an ES module package through "type": "module".
- Trip data is hard-coded in
components/block/about.tsx; there is no API integration yet. DataProviderexists but is not mounted, so shared data subscription behavior is not active.- The router supports nested route forwarding, but no child routes are registered yet.
src/api,src/contexts,src/registry, andsrc/transformersare currently placeholders.@attaditya/iconoir-preactshould be treated as icons-only for now; package providers are not ready for use.scripts/version.shrefers to anappdirectory, while this repository usesportable; that script likely needs alignment before use.- The top-level README describes GraphScript, while
meta.jsonand UI content identify this app as MedRush Agents Hub.
For near-term product work, keep the existing layered structure:
- Add API clients under
portable/src/api. - Mount
DataProviderinsrc/main.tsxonce shared data refresh is needed. - Move hard-coded trip data out of
Aboutinto data/API modules. - Expand
TripInfoaround the existingTripDatainterface instead of introducing parallel trip shapes. - Register new pages through
routes/home.tsxor split route maps into dedicated route modules when the app grows.