Bun workspace monorepo for the Ark ERP frontend: 7 Vike SSR portals plus shared UI, API, type, and design-system packages. Current: v1.2.1 (CHANGELOG)
apps/ one Vike SSR app per ERP portal
├── main/ → portal.arkinstitutebc.com login, SSO hub, /learn manuals
├── training/ → training.arkinstitutebc.com batches, students, attendance
├── procurement/ → procurement.arkinstitutebc.com PR approval, PO workflow
├── inventory/ → inventory.arkinstitutebc.com receiving, stock take, movements
├── finance/ → finance.arkinstitutebc.com disbursements, GL, RR, assets
├── billing/ → billing.arkinstitutebc.com TESDA billing, receivables
└── hr/ → hr.arkinstitutebc.com trainers, attendance, payroll
packages/ shared, edit once
├── ui/ Sidebar, TopBar, PageHeader, StatCard / InfoCard, DataTable, StatusBadge,
│ Modal / ModalFooter / ConfirmDialog, Input, Select, Button, BackLink,
│ AttachmentUploader, TutorialShell, AuthGate, QueryBoundary, createCrudHooks,
│ theme + categoryTone helpers, Icons (lucide-solid)
├── api-client/ api(), useCurrentUser, useLogin, performLogout, queryClient, validateForm
├── data-types/ Bank, Batch, Student, Transfer, PR, PO, RR, GlAccount, etc.
└── design-system/ globals.css, Tailwind theme, semantic tokens
Backend: ark-services.
bun install # one-time, links workspaces
bun run dev:main # local main portal on :3000
bun run dev:training # :3001 (procurement :3002, inventory :3003, finance :3004, billing :3005, hr :3006)
bun run lint # biome
bun run test:unit # Bun unit tests for shared API/form helpers
bun run typecheck # tsc per workspace
bun run build # Vike production build for every app/package with a build script
bun run test:e2e # Playwright portal smoke + focused E2E (LOCAL ONLY, NOT in CI)
bun run test:e2e:update # update snapshots after intentional UI changesYou also need the backend running locally — see ark-services/README.md.
Copy an app's .env.example when you need local portal-link overrides. Production
uses each app's tracked .env.production for public URLs and systemd PORT.
- Token system in
packages/design-system/src/globals.css—:root[data-theme="dark"]overrides--color-background,--color-foreground,--color-surface,--color-surface-muted,--color-border,--color-muted. Brand colors (--color-primary,--color-accent) are identical in both themes. <ThemeProvider>from@ark/uiwraps every app's+Layout.tsx; trackslight | dark | auto(defaultautofollows OS) inlocalStorage["ark-theme"].- A no-FOUC inline script in each
+Head.tsxsetsdata-themeBEFORE first paint. <ThemeToggle />lives in the sharedTopBar(sub-portals) and the main app'sNavbar.- Use semantic utilities:
bg-surface,bg-surface-muted,text-foreground,text-muted,border-border. Avoidbg-white,bg-gray-*,text-gray-*,border-gray-*in new code.
- Pull requests run install, Biome, unit tests, and workspace typecheck through
.github/workflows/deploy.yml. - Pull requests that touch
apps/**orpackages/**also run.github/workflows/bundle-size.yml, building every portal and commenting bundle sizes for visibility. - Pushes to
mainpass the same quality gate, then SSH toark-api, pull/opt/ark-portals/repo, and runinfra/deploy.sh. infra/deploy.shpath-filters changed files:apps/<name>/**rebuilds one portal, whilepackages/**rebuilds all 7 because shared code changed.- Production is Vike SSR behind Caddy and systemd. Vercel project metadata is not part of the active deploy path.
| Portal | Local dev | Production systemd |
|---|---|---|
| main | 3000 | 3001 |
| training | 3001 | 3002 |
| procurement | 3002 | 3003 |
| inventory | 3003 | 3004 |
| finance | 3004 | 3005 |
| billing | 3005 | 3006 |
| hr | 3006 | 3007 |
cp -r apps/training apps/<name>and rename inpackage.json- Edit
apps/<name>/components/layout/sidebar.tsx(setbrandIcon,brandTitle,navItems) - Provision a new systemd unit
ark-portal-<name>on the VPS + add Caddy reverse-proxy block - Add the app to the path-filter in
.github/workflows/deploy.yml - Add DNS +
.env.productionvalues forPORT,VITE_API_URL, and portal URLs
- SSO: cookie set with
Domain=.arkinstitutebc.com→ log in once, all 7 portals work - Auth: each app's
+Layout.tsxwraps with<AuthGate>→ 401 redirects toportal.arkinstitutebc.com/login - Test logins: production seeded users are listed in
ark-services/src/db/seed-prod.ts; ask Matt for current passwords.