施工
GitHubA project-centered construction operations workspace: projects, work fronts, jobs, workers and their permits, quality defects, RFIs, payment claims, handover documents, and a BIM reference matrix for cost and embodied-carbon baselines — with a server-enforced rule that a worker is only assigned to a work front when a currently valid permit covers every certification the linked job requires. It provides the operations model and safety checks for project delivery; it does not replace an ERP, a BIM authoring tool, or a regulatory permit authority.
This is an executable Bolt template, not a production-operations manual. Start with the operating model below, then use the collections, apps, automations, and verification sections when changing it.
Operating model
- Establish a project, its site locations (work fronts), and BIM reference context.
- Configure certification types and issue permits to work that prove a worker's currently valid authority and the certifications it covers.
- Define jobs (work packages), link them to work fronts and required certifications, then create worker assignments — every assignment passes a server compliance check before it exists.
- Run delivery in the project record: review the IFC coordination model, track RFIs and defects per project, and allocate manpower per work front.
- Track commercial work through payment claims and keep the documents supporting each claim.
- Review the four scheduled daily exports for permits, defects, RFIs, and claim readiness.
The data model keeps these concerns separate: jobs describe work packages; site locations describe work fronts; permits prove a worker's currently valid authority; and assignments connect a worker to work only after the compliance check passes.
projects ─┬─ site_locations ── job_assignments ── workers ── permits_to_work ── certification_types
├─ jobs ────────────┘ │ └── permit ↔ certification join
├─ rfis · defects · payment_claims └── permit ↔ worker join
└─ asset_documents · bim_reference_matrix jobs ↔ certifications / site_locations (joins)Collections
| Collection | Purpose |
|---|---|
projects |
Construction projects and operating context. |
jobs |
Work packages linked to site locations and BIM references. |
workers |
Worker roster used for assignment and compliance. |
certification_types |
Certification library defining workforce requirements. |
site_locations |
Work fronts and delivery zones within a project. |
defects |
Quality issues and closeout items. |
rfis |
Design and coordination questions. |
payment_claims |
Commercial claims with readiness and submission state. |
permits_to_work |
Permit and competency validity records. |
asset_documents |
Handover and asset-linked documents. |
bim_reference_matrix |
BIM item master sheet for cost and carbon estimation. |
job_assignments |
Worker assignments to jobs and site locations (compliance-gated). |
jobs_certification_types |
Join: jobs ↔ certification_types. |
jobs_site_locations |
Join: jobs ↔ site_locations. |
permits_to_work_certification_types |
Join: permits_to_work ↔ certification_types. |
permits_to_work_workers |
Join: permits_to_work ↔ workers. |
Relationships: permits_to_work ↔ certification_types and ↔ workers (many-to-many through the
join tables); jobs ↔ certification_types and ↔ site_locations (same); job_assignments →
workers / jobs / site_locations (direct foreign keys). Every RFI, defect, claim, permit,
document, site location, and job belongs to a project.
Job assignment compliance
job_assignments/+hooks.ts validates create and update:
- Load the worker's active permits (via
permits_to_work_workers+permits_to_work) and collect the certification ids they cover. - Load the jobs linked to the assignment's site location (via
jobs_site_locations+jobs) with their required certifications. - Require at least one site job whose required certifications are all covered by an active, in-validity permit.
The rule is enforced in both create and update hooks, not just in the assignment UI. Empty requirements do not pass the guard: every assignment requires a site-location job with an explicit qualification set.
Apps and policies
| App | What a user does |
|---|---|
construction_project_workspace |
Browse the project catalogue; open a project record for the delivery detail. |
construction_settings_workforce |
Manage workers, certification types, and job requirements. |
construction_settings_reference_matrix |
Maintain the BIM reference matrix: codes, units, rates, carbon factors. |
The project workspace app is deliberately just the projects table: the depth lives in the project record itself. Its representation opens three tabs — Model & coordination (the IFC viewer next to the project's RFIs and defects), Manpower allocation (one lane per work front with worker cards), and Commercial & controls (contract value against claimed/certified amounts, payment claims, project documents, and current permits to work). Site locations, asset documents, and permits to work have no tab of their own anywhere and are reached only through a project — the only context in which any of them means much.
Four files split one policy contract: +construction_read.ts owns the twelve unconditional read
grants, and the three app policies carry only capabilities — they open an application, and the
application opens the grants. The narrowing is apps, not where. That is deliberate rather
than lazy — construction carries no requestor-bearing column on any of these collections, so there
is nothing for a where clause to scope to, and what actually separates a delivery user from a
settings administrator is which application they can open. The shared grant list lives in one file
(src/access/policies admits only +<name>.ts) so the whole set stays readable where it is named.
Daily operational watches
Four server automations run at 06:00 each day. They produce bounded JSON exports for operational
review; they do not send messages, escalate records, or mutate business state.
| Automation | Subject | Export file |
|---|---|---|
permit_expiry_watch |
permits_to_work |
permit-expiry-watch.json |
defect_closeout_digest |
defects |
defect-closeout-digest.json |
rfi_followup_watch |
rfis |
rfi-followup-watch.json |
payment_claim_readiness_watch |
payment_claims |
payment-claim-readiness-watch.json |
All four share one shape: read at most 25 rows, report that number as the summary count, and export the same rows as the file body. The bounds hold a review a reviewer can read — the sweep is a morning digest, not a full table in a JSON blob. If a deployment needs alerts, an integration or delivery facility must be added explicitly; these read-only watches notify no one on their own.
Under the hood
Bolt discovers the workspace from the filesystem; vite.config.ts is the only root entry point.
All source lives under src/; the compiler derives the registry, workspace, client, and types
under .norbital/.
src/apps/ the three applications (+<app>.svelte)
src/access/policies/ one shared read authority + one per application (+<name>.ts)
src/collections/ models (+model.ts), relations (+relationship.ts),
the compliance hook, and form/detail representations
src/automations/ the four daily review watches (+<name>.ts)
src/datatypes/ project address, site coordinates,
emergency contact, permit signatures (+definition.ts + renderer)
src/i18n/ English and Chinese copy, same key sets (messages.en/zh.json)
src/collections/projects/ifc-viewer/ the embedded IFC viewer and its converter worker
assets/ thumbnail and record media; the sample IFC model under assets/ifc/How the pieces work:
- Representations. Every collection ships a
+representation.sveltethat overrides the schema-derived form where the auto form would be two uuid boxes (join tables, relationship fields). Fields that point at another collection render throughRelationshipRendererwith a humancode · namelabel; no system id is ever painted. The project's representation is the one genuinely bespoke surface (the IFC viewer, manpower lanes, commercial rollups) and lives asproject-representation.sveltebeside it. - The IFC viewer.
src/collections/projects/ifc-viewer/holds a lazy-loaded WebGL viewer (ifc_viewer.svelte) plus a converter that runs web-ifc in a worker (ifc_viewer.converter.worker.ts) and a typed surface for the esm.sh-loaded viewer libraries (ifc_viewer.types.ts). It is mounted inside the project record when a linkedasset_documentsrow carries anifc_modeldocument (or a.ifcURL); the sample model underassets/ifc/is what a freshly seeded tenant shows. - Custom types. Structured values that cannot be plain columns:
project_address,site_coordinates,emergency_contact, andpermit_signatures. Each has a definition (the only schema) and a renderer (display and edit). Money follows the same custom-type contract and access pattern, but its definition is injected by the platform: usecustom('money', { allowedCurrencies })from@norbital-ai/bolt/authoring. - i18n. The workspace ships English and Chinese catalogs with exactly the same keys. App
metadata in
<svelte:head>stays static English; the sidebar label and page copy localize via the catalogs. - Seed data. The workspace ships no
+seed.ts. Fixture rows (projects, jobs, workers, permits, RFIs, defects, claims, the BIM matrix, documents) are loaded by the host's construction seed plan from the seed bank, while the committedassets/files — including the sample IFC model — ship inside the compiled artifact and are served at/__bolt/request/api/template-seed-assets/construction/..., which is what the project record's viewer uses.
Use collection hooks for non-negotiable server rules, a custom type when a reusable field needs its
own validation and renderer, and a collection representation only when schema-derived UI is
insufficient. Keep large BIM artefacts in a file-storage facility; the bim_reference_matrix is
the reference and baseline model, not a replacement for native BIM files.
Changing the template
A template is a normal Bolt workspace: install once, then sync and lint inside this directory.
pnpm sync # derive assembly/migrations and emit .norbital/artifact/bundle.mjs
pnpm lintThere is no separate build command: the portable deployment artifact is a sync output. Commit
authored source and .norbital/migrations/ with your change, but do not edit or commit other
generated .norbital output. Publish a template revision before provisioning a new tenant from that
release; existing tenants remain on the revision they adopted. See the
template lifecycle for the full release flow.