Native IFC collaboration tools: a git-aware IFC viewer integrated into an IFC-aware forgejo mod. Tied together with an ifc:// URL scheme that allows sharing exact IFC versions and viewpoints as persistent links
Find a file
Bruno Postle a1fc88e59d Collaboration review: 14 new issues filed
Covers the full collaboration lifecycle — designer commits, reviewer
inspects, feedback created, designer fixes, reviewer verifies.
Key gaps: element selection/properties, share URL button, create
Forgejo issue from viewer, BCF import, PR diff renders, private repo
auth, workflow documentation, CDN dependency, model metadata panel.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-24 12:07:37 +01:00
.beads Collaboration review: 14 new issues filed 2026-04-24 12:07:37 +01:00
.claude bd init: initialize beads issue tracking 2026-04-23 06:41:01 +01:00
dev Switch from gitea to forgejo 2026-04-16 00:56:46 +01:00
forgejo Fix 7 issues from deep review 2026-04-24 11:57:06 +01:00
ifcurl Fix 7 issues from deep review 2026-04-24 11:57:06 +01:00
tests Fix 7 issues from deep review 2026-04-24 11:57:06 +01:00
.gitignore bd init: initialize beads issue tracking 2026-04-23 06:41:01 +01:00
AGENTS.md bd init: initialize beads issue tracking 2026-04-23 06:41:01 +01:00
CLAUDE.md Remove PLAN.md (tasks now in beads), add syncCameraUrl to viewer 2026-04-23 07:18:28 +01:00
LICENSE Python core library and ifcurl CLI 2026-04-15 21:24:35 +01:00
pyproject.toml Fix 7 issues from deep review 2026-04-24 11:57:06 +01:00
README.md Fix 7 issues from deep review 2026-04-24 11:57:06 +01:00
SPECIFICATION.md Initial commit 2026-04-15 20:08:52 +01:00

ifcurl

ifcurl is a URL scheme, tools, and server integration for addressing shareable views of IFC building models stored in git repositories.

ifc://github.com/brunopostle/simple-ifc@heads/main?path=building.ifc&selector=IfcWall&fov=60

An ifc:// URL encodes everything needed to reproduce a specific model view: the git source, the file, which elements to show, and the camera position. Like a permalink for BIM — paste it, share it, embed it in documentation.


Architecture

Four interlocking components:

Component Language What it does
Python library + CLI Python Parse ifc:// URLs, fetch IFC from git, render PNG
Preview service Python HTTP server — PNGs on demand
Forgejo integration Go + assets Inline markdown previews, "View in 3D" button
Browser viewer JavaScript Interactive WebGL viewer, served as a Forgejo asset
Markdown source:
  [Section cut](ifc://host/org/repo@heads/main?path=building.ifc&clip=0,0,3,0,0,-1)
                                      │
Forgejo renders (via Go patch):        │
  <figure>                             │
    <img src="/preview?url=..."> ──────┤── preview service renders PNG
    <a href="/assets/viewer.html?url=…">   browser viewer (WebGL, interactive)
  </figure>

The viewer is also reachable directly — paste or type an ifc:// URL into its toolbar, or drag one onto the page.


ifc:// URL scheme

Full specification: SPECIFICATION.md

ifc://[user@]host/org/repo@<ref>?<parameters>

Transport is inferred from the URL structure — no prefix needed:

URL form Transport
ifc://host/org/repo HTTPS
ifc://git@host/org/repo SSH
ifc:///path/to/repo Local file

Refs follow git namespace form to avoid branch/tag ambiguity:

Form Meaning
@heads/main Branch tip
@tags/v1.2 Tag
@abc123def Commit hash
@HEAD Default branch

Key query parameters:

Parameter Description
path= IFC file path within the repository
selector=IfcWall IfcOpenShell selector — filter elements; + for union
camera=px,py,pz,dx,dy,dz,ux,uy,uz Camera position, direction, up in IFC world coordinates
fov=60 Perspective field of view in degrees
scale=50 Orthographic view-to-world scale
clip=px,py,pz,nx,ny,nz Clipping plane — point + normal in IFC coords (repeatable)
visibility= highlight · ghost · isolate

Python library and CLI

Fetch an IFC file from a git repository and render it to PNG.

pip install "ifcurl[render]"
ifcurl render "ifc://github.com/brunopostle/simple-ifc@heads/main?path=_test_simple.ifc"
ifcurl render "ifc://..." -o output.png

Use as a library:

from ifcurl import IfcUrl, fetch_ifc
from ifcurl.render import render

url = IfcUrl.parse(
    "ifc://example.com/org/repo@heads/main"
    "?path=models/building.ifc&selector=IfcWall&visibility=ghost"
)
hexsha, ifc_bytes = fetch_ifc(url)   # hexsha is stable even for mutable refs
model = ifcopenshell.open(...)       # write ifc_bytes to tmp file first

png = render(model, selector=url.selector, clips=url.clips or None,
             camera=url.camera, fov=url.fov, visibility=url.visibility)

Remote repositories are cloned as bare repos to the OS cache directory (~/.cache/ifcurl/ on Linux) on first use. Mutable refs (@heads/, @HEAD) trigger a git fetch; immutable refs (commit hashes, tags) use the cache as-is.

For private repositories, configure tokens per host in ~/.config/ifcurl/tokens.json:

{ "hosts": { "github.com": "ghp_…", "gitlab.example.com": "glpat_…" } }

Preview service

An HTTP service that renders ifc:// URLs to PNG, intended for co-location with a Forgejo/Gitea instance.

pip install "ifcurl[service]"
ifcurl serve --allowed-hosts git.example.com     # restrict to your Forgejo host
ifcurl serve --host 0.0.0.0 --port 9000 --allowed-hosts git.example.com

Pass --allowed-hosts as a comma-separated list of hostnames (with optional :port) the service is allowed to fetch from. This prevents the preview endpoint from being used to reach internal services. Omitting it allows all non-private remote hosts.

Endpoints

Endpoint Description
POST /preview Render an ifc:// URL to PNG
GET /preview?url=ifc://… Same, via query string (used by Forgejo <img> tags)
POST /bcf Generate a BCF 2.1 zip from an ifc:// URL viewpoint

Caching

Tier Key Contents Notes
2 commit hash + path IFC bytes In-memory LRU
3 commit hash + path + selector Resolved element set In-memory LRU
4 SHA-256 of full URL Rendered PNG Filesystem; immutable refs only

Tier 4 is never written for mutable refs (@heads/, @HEAD).


Forgejo integration

A source patch for Forgejo that adds:

  • Inline markdown preview[label](ifc://…) and bare ifc://… in markdown render as <figure> preview images linked to the browser viewer.
  • "View in 3D" button — appears on .ifc file view pages alongside Raw / Permalink / History.
  • Browser viewer assetviewer.html + viewer-url.js served at /assets/viewer.html.

See forgejo/README.md for full apply, build, and deployment instructions.

Quick summary

# Apply the Go source patch
cp forgejo/modules/markup/markdown/ifc_url{,_test}.go /path/to/forgejo/modules/markup/markdown/
cd /path/to/forgejo && git apply /path/to/ifcurl/forgejo/go.patch

# Build Forgejo
go build -tags 'sqlite sqlite_unlock_notify' \
  -ldflags "-X 'forgejo.org/modules/setting.StaticRootPath=/usr/share/forgejo'" \
  -o forgejo . && sudo cp forgejo /usr/bin/forgejo

# Deploy assets (no rebuild needed)
sudo cp forgejo/custom/public/assets/viewer*.* /etc/forgejo/public/assets/
sudo cp forgejo/templates/custom/footer.tmpl /var/lib/forgejo/custom/templates/custom/
sudo systemctl restart forgejo

# Install and start preview service as a systemd unit
sudo cp forgejo/server-config/ifcurl-preview.service /etc/systemd/system/
# edit ExecStart --allowed-hosts to match your Forgejo hostname, then:
sudo systemctl enable --now ifcurl-preview

Add to /etc/forgejo/conf/app.ini:

[ifcurl]
PREVIEW_SERVICE_URL = http://localhost:8000

Browser viewer

A self-contained WebGL IFC viewer (viewer.html) built on @thatopen/components. No build step — loads dependencies from CDN.

Features:

  • Toolbar with raw ifc:// URL input and structured fields (repo, ref, path, selector) — editing any field reloads the model
  • Selector filtering — IfcWall, IfcWall+IfcSlab, etc.
  • Clipping planes — ✂ clip button, double-click on model surface to place; drag handles to adjust; planes serialised back into the URL
  • FOV control, camera sync — the URL in the browser bar always reflects the current view and is shareable
  • Drag-and-drop ifc:// URLs onto the page

Development

git clone https://github.com/brunopostle/ifcurl
cd ifcurl
pip install -e ".[service]"

# Python tests
python -m pytest tests/

# JavaScript tests (Node 18+)
node --test tests/test_viewer_url.mjs

# Go tests (requires Forgejo source tree with patch applied)
cd /path/to/forgejo
go test ./modules/markup/markdown/ -run TestIfcURL -v

Roadmap

Phase Status Description
1 — Python core ✓ done URL parsing, git fetch, render
2 — Preview service ✓ done HTTP service with caching
3 — Forgejo integration ✓ done Go patch, viewer, markdown extension
4 — Bonsai integration planned Protocol handler + "Copy view URL"
5 — IFC Viewer integration planned Plugin for the open-source IFC Viewer
6 — Federation planned IFCDOCUMENTREFERENCE cross-repo links

Development tasks are tracked with beads: bd ready.


Licence

LGPL-3.0-or-later