9.1 KiB
IFC URL — Development Plan
Overview
IFC URL requires work across four distinct areas:
- A Python core library and CLI tool
- A preview service with Gitea integration
- Desktop app integration (Bonsai, IFC Viewer)
- The federation extension to
IFCDOCUMENTREFERENCE
The Python core is the foundation for all other work. The Gitea integration and desktop app work can proceed in parallel once the core exists.
Language ownership
| Component | Language | Rationale |
|---|---|---|
| URL parsing, git fetch, selector execution, rendering | Python | Built on IfcOpenShell |
| Bonsai plugin | Python | Bonsai is a Blender/Python addon |
| CLI tool | Python | Wraps the core library |
| Preview service | Python | Wraps the core library |
| Gitea plugin | Go | Gitea is written in Go; the plugin only calls an HTTP endpoint |
| Web viewer integration | JavaScript | Future, not in current scope |
The Python core is a strong candidate for eventual contribution to IfcOpenShell, but this is not a prerequisite for any phase.
Phase 1 — Python core and CLI tool
Build a Python library that resolves an ifc:// URL and produces a rendered
PNG. This validates the spec against real IFC files and is the foundation for
all subsequent work.
Library responsibilities
- Parse an
ifc://URL into its components - Infer git transport from URL structure (SSH, HTTPS, local)
- Fetch the IFC file from the repository at the specified ref
- Execute the IfcOpenShell selector against the loaded model
- Apply camera (perspective and orthographic), clipping planes, and visibility mode
- Render a static PNG
CLI interface
ifc-url render "ifc://example.com/org/repo@abc123?path=model.ifc&selector=IfcWall&fov=60"
ifc-url render "ifc://example.com/org/repo@heads/main?path=model.ifc&camera=0,0,8,0,0,-1,0,1,0&scale=50"
Notes
- IfcOpenShell handles selector execution, model parsing, and geometry
- Rendering requires a headless approach; options include IfcOpenShell's own geometry processing with a software or headless OpenGL renderer
- Git access uses the platform credential store for HTTPS and ssh-agent or key files for SSH
- The CLI accepts the URL as a plain string so it can be called from non-Python contexts
Phase 2 — Preview service
Wrap the Phase 1 library in an HTTP service for use by Gitea and other consumers.
Endpoint
POST /preview
body: { url: "ifc://..." }
response: image/png
Caching
| Tier | Cache key | Contents | Notes |
|---|---|---|---|
| 2 | commit hash | Parsed model structure | Shared across requests |
| 3 | commit hash + selector | Resolved GUID set | |
| 4 | full URL hash | Rendered PNG | Not applied to mutable refs |
Mutable refs (@heads/, @HEAD) must not be cached at tier 4 since the
underlying commit may change. Commit hash refs are immutable and can be
cached indefinitely at all tiers.
Authentication
- Co-located with Gitea — uses the requesting user's Gitea session token, passed from the Gitea plugin
- Standalone — sideloaded token configuration per git host
Phase 3 — Gitea integration
Add ifc:// link detection and preview embedding to Gitea.
Go plugin responsibilities
- Detect
ifc://links in post and comment content - Call the preview service with the URL and the current user's session token
- Embed the returned PNG inline with a link that opens the URL
- Degrade gracefully when the preview service is unavailable (show the raw URL rather than failing)
Notes
- The plugin has no IFC awareness; all IFC logic lives in the preview service
- Repeated embeds of the same URL across different posts do not trigger re-renders — the preview service cache handles deduplication
- The preview service may run as a companion process on the same host or as a separately configured external service
Phase 3b — Web IFC viewer
Add a 3D viewer that opens in a separate browser window when viewing an .ifc
file in Forgejo.
Architecture
-
Forgejo Go patch: when rendering the file view for a
.ifcfile, inject a "View in 3D" button that openshttp://localhost:8000/viewer?url=ifc://...in a new tab. The ifc:// URL encodes the current host, repo, ref, and file path. -
/viewerendpoint in the ifcurl preview service: returns a self-contained HTML page. No server-side IFC processing — the browser does all rendering. -
Browser rendering: the viewer page loads
@thatopen/components(and itsweb-ifc+ Three.js peer dependencies) from a CDN via an ES module importmap. It constructs the Forgejo raw file URL from the ifc:// URL parameters and fetches the IFC bytes directly from Forgejo.
Current scope (Phase 3b)
- Display the full model for whatever ref is shown in Forgejo.
- Basic orbit/pan/zoom camera controls.
- No filtering or selection UI yet.
Future scope
- Element filtering and selection using
@thatopen/componentsclassifier and highlighter APIs. - Camera state serialised to an
ifc://URL so the user can copy a view link (feeds into Phase 4 Bonsai "Copy view URL"). - Diff highlighting driven by ifcmerge output (see Phase 3c).
Phase 3c — ifcmerge integration
ifcmerge is a git custom merge driver that resolves conflicts in .ifc files
that git's built-in 3-way merge cannot handle. Where two branches have both
modified an IFC file (a fork), git would report an unresolvable conflict;
ifcmerge performs a semantics-aware merge and produces a valid merged IFC file.
Git merge driver configuration
Register ifcmerge as the git merge driver for .ifc files on the Forgejo
server:
# /etc/gitconfig or ~forgejo/.gitconfig
[merge "ifcmerge"]
name = IFC merge driver
driver = ifcmerge %O %A %B %L
# .gitattributes in each repo, or server-side gitattributes
*.ifc merge=ifcmerge
With this in place, Forgejo's existing "merge automatically" path will invoke
ifcmerge via git when merging .ifc files, and the PR merge button will work
without any Go-side changes for the common case.
Forgejo integration
- Verify that Forgejo's merge-ability check (the "these branches can be merged
automatically" indicator) correctly reflects ifcmerge's ability to merge
.ifcfiles — investigate whether the check runs a trial merge via git or uses a heuristic. - If needed, patch Forgejo to run a trial
git merge --no-committo get an accurate result for IFC files.
3D diff view (future)
- After a merge completes, surface a "View merge in 3D" button in the PR using the Phase 3b viewer.
- Use
@thatopen/componentshighlighter to colour added, removed, and modified elements differently, driven by comparing the merged IFC against either parent.
Phase 4 — Bonsai integration
Add ifc:// handling to Bonsai.
Protocol handler
Register ifc:// as an OS protocol handler on installation (Windows,
macOS, Linux). On receiving a URL, resolve the git source, load the model,
and apply the view state from the URL parameters.
"Copy view URL"
A button that generates an ifc:// URL from the current Bonsai state:
- Git remote, ref, and file path of the open model
- Active selection converted to an IfcOpenShell selector
- Current camera converted to the
camera+fovorscaleformat, in IFC world coordinates - Active clipping planes as
clipparameters - Current visibility mode
The button always generates a commit hash ref by default. Generating a
@heads/ ref is a secondary option for authoring links intended to track
a branch.
Federation
When opening a model via ifc://, Bonsai resolves IFCDOCUMENTREFERENCE
locations using the repo and ref from the root file's URL as context.
ifc:// locations in linked model references are resolved recursively.
Phase 5 — IFC Viewer integration
Equivalent to Phase 4 for the IFC Viewer desktop application.
Phase 6 — Federation extension
Extend the IFCDOCUMENTREFERENCE location field in Bonsai to accept
ifc:// URLs, enabling cross-repo and cross-server federation.
Tasks
- When saving a linked model reference, offer the option to write the
location as an
ifc://URL rather than a relative path - When a relative path would traverse above the repository root, prompt
the user to convert it to an
ifc://URL - Resolve
ifc://location fields through the Phase 4 URL resolver
The transformation matrix in IFCDOCUMENTREFERENCE is unaffected by this
change. Phase 4 must be complete before this phase begins.
Future work
BCF export
An additional preview service endpoint returning a BCF file:
POST /bcf
body: { url: "ifc://..." }
response: application/zip
Resolves the selector to a GUID set and constructs a BCF viewpoint from the camera, clipping planes, and visibility state. No implementation is planned before Phase 2 is complete.
Web viewer integration
JavaScript integration with web-based IFC viewers (IFC.js, xeokit) and browser-side forum embedding. Not in current scope.
IfcOpenShell contribution
Once the Python core is stable, the URL parsing and resolution logic is a candidate for contribution to IfcOpenShell as a shared utility. This is not a prerequisite for any phase.