Production-ready BIM viewer for web applications. Load, inspect, and interact with IFC files in the browser with measurements, clipping, AI visualization, and more.
npm install @ifc-viewer/coreA production-ready, feature-rich BIM viewer that lets you load, inspect, and interact with Building Information Model (IFC) files directly in the browser. Built on top of Three.js and the That Open Company ecosystem with zero native installations required.


- šļø Full IFC Support - Load and render IFC 2x3 and IFC4 files
- š Measurement Tools - Volume, length, area, angle measurements
- šŗļø Interactive Minimap - Real-time overhead navigation view
- āļø Clipping Planes - Section cuts with transform gizmos
- šØ AI Visualizer - Transform BIM views into photorealistic renders (powered by HuggingFace)
- šø Screenshots - Capture high-resolution images
- šÆ Element Selection - Click to inspect IFC properties
- š³ Relations Tree - Navigate spatial structure (Sites ā Buildings ā Storeys)
- š® Multiple Navigation Modes - Orbit, First-Person, Plan view
- š± Mobile Friendly - Touch-optimized controls
- šØ Customizable - Theme, appearance, and feature flags
- ā” High Performance - Optimized for large models with fragment streaming
``bash`
npm install @ifc-viewer/core
`javascript
import { createIFCViewer } from '@ifc-viewer/core';
import '@ifc-viewer/core/styles';
const viewer = createIFCViewer({
container: document.getElementById('viewer-container'),
onModelLoaded: (meta) => console.log('Model loaded!', meta),
onError: (error) => console.error('Error:', error)
});
`
`html
`
`typescript
import { createIFCViewer } from '@ifc-viewer/core';
import '@ifc-viewer/core/styles';
const viewer = createIFCViewer({
// Required: Container element
container: document.getElementById('viewer-container'),
// Optional: Customize appearance
appearance: {
world: {
backgroundColor: '#050816',
directionalLightColor: '#f1f5f9',
directionalLightPosition: [20, 35, 10],
},
grid: {
enabled: true,
color: '#10b981',
primarySize: 6,
secondarySize: 1,
distance: 250,
},
},
// Optional: Load a model on startup
initialModel: {
url: '/models/demo-project.ifc',
// OR use a File/Blob:
// file: myIfcFileBlob
},
// Optional: Enable/disable features
features: {
minimap: true,
measurement: true,
clipping: true,
floorplans: true,
aiVisualizer: false, // Requires HuggingFace API token
},
// Optional: Callbacks
onModelLoaded: (meta) => {
console.log('Model loaded:', meta);
},
onObjectSelected: (selection) => {
console.log('Selected objects:', selection);
},
onError: (error) => {
console.error('Viewer error:', error);
},
// Optional: Custom theme
theme: {
'--primary-color': '#667eea',
'--background-color': '#1a1a1a',
}
});
`
The createIFCViewer function returns a handle with the following methods:
#### loadModelFromUrl(url: string): Promise
Load an IFC model from a URL:
`javascript`
await viewer.loadModelFromUrl('/path/to/model.ifc');
#### loadModelFromFile(file: File): Promise
Load an IFC model from a File object:
`javascript`
const fileInput = document.getElementById('file-input');
fileInput.addEventListener('change', async (e) => {
const file = e.target.files[0];
await viewer.loadModelFromFile(file);
});
#### captureScreenshot(): Promise
Capture a screenshot as a base64 data URL:
`javascript`
const screenshot = await viewer.captureScreenshot();
// Use as image src or download
const img = document.createElement('img');
img.src = screenshot;
#### getCameraState(): Promise
Get current camera position and target:
`javascript`
const cameraState = await viewer.getCameraState();
console.log('Position:', cameraState.position);
console.log('Target:', cameraState.target);
#### setCameraState(state: CameraState): Promise
Set camera position and target:
`javascript`
await viewer.setCameraState({
position: { x: 10, y: 20, z: 30 },
target: { x: 0, y: 0, z: 0 }
});
#### unmount(): void
Cleanup and unmount the viewer:
`javascript`
viewer.unmount();
`html
`
When embedding the viewer in a page section (not full-page), you need to override some default styles:
`html
`
`html
`
`javascript
const viewer = createIFCViewer({
container: document.getElementById('viewer'),
// Custom colors and lighting
appearance: {
world: {
backgroundColor: '#0b1120',
directionalLightColor: '#f8fafc',
directionalLightPosition: [25, 40, 10],
},
grid: {
color: '#22d3ee',
enabled: true,
primarySize: 8,
secondarySize: 1,
},
},
// Pre-load a model
initialModel: {
url: '/models/showroom.ifc',
},
// Minimal UI - disable some features
features: {
minimap: false,
aiVisualizer: false,
measurement: true,
clipping: true,
},
// Handle events
onModelLoaded: async (meta) => {
console.log('Model loaded with metadata:', meta);
// Capture initial view
const screenshot = await viewer.captureScreenshot();
console.log('Initial screenshot captured');
},
onObjectSelected: (selection) => {
// selection is a Map: fragmentID -> Set
for (const [fragmentId, expressIds] of selection.entries()) {
console.log(Fragment ${fragmentId}: Selected ${expressIds.size} elements);`
}
},
});
`tsx
import { useEffect, useRef } from 'react';
import { createIFCViewer, ViewerHandle } from '@ifc-viewer/core';
import '@ifc-viewer/core/styles';
function IFCViewerComponent() {
const containerRef = useRef
const viewerRef = useRef
useEffect(() => {
if (!containerRef.current) return;
const viewer = createIFCViewer({
container: containerRef.current,
onModelLoaded: (meta) => {
console.log('Model loaded:', meta);
},
features: {
minimap: true,
measurement: true,
}
});
viewerRef.current = viewer;
return () => {
viewer.unmount();
};
}, []);
const handleLoadModel = async () => {
if (viewerRef.current) {
await viewerRef.current.loadModelFromUrl('/model.ifc');
}
};
return (
$3
`html
`š¤ AI Visualizer Setup (Optional)
The AI Visualizer feature transforms your BIM views into photorealistic architectural renders using HuggingFace models.
1. Get a free HuggingFace API token: https://huggingface.co/settings/tokens
2. Create a
.env file in your project:
`
VITE_HUGGINGFACE_TOKEN=your_token_here
`
3. Enable the feature:
`javascript
createIFCViewer({
container: document.getElementById('viewer'),
features: {
aiVisualizer: true
}
});
`š Type Definitions
Full TypeScript support with exported types:
`typescript
import type {
CreateViewerOptions,
ViewerHandle,
SelectionMap,
ViewerFeatureFlags,
ViewerAppearanceConfig,
InitialModelConfig,
} from '@ifc-viewer/core';
`š ļø Browser Support
- ā
Chrome/Edge 90+
- ā
Firefox 88+
- ā
Safari 14+
- ā
Mobile browsers (iOS Safari, Chrome Android)
Requirements:
- WebGL 2.0
- ES2020 support
- WebAssembly support
š Common Issues
$3
Solution: When embedding in a page section, apply these CSS overrides:
`css
#your-container .ifc-viewer-library-container.layout {
height: 100% !important;
width: 100% !important;
}#your-container .sidebar-slot,
#your-container .sidebar-toggle {
position: absolute !important;
}
`$3
Solution: The viewer uses
position: fixed by default for full-page mode. Override to absolute for embedded mode (see example above).$3
Troubleshooting:
1. Check browser console for errors
2. Verify IFC file is valid (not corrupted)
3. Ensure file is accessible (CORS headers if loading from URL)
4. Check file size - very large models (>100MB) may take time
$3
Solution: Ensure
web-ifc.wasm is accessible. If serving from a subdirectory, set:`javascript
import { Components } from '@thatopen/components';Components.config.webIfcPath = '/path/to/web-ifc.wasm';
``Check out our live examples:
- Full-page viewer
- Embedded viewer
- React integration
- Modal viewer
- Full Documentation
- Integration Guide
- API Reference
- Changelog
Contributions are welcome! Please read our Contributing Guide.
MIT Ā© IFC Viewer Contributors
Built with:
- Three.js - 3D rendering engine
- That Open Company - BIM components ecosystem
- web-ifc - IFC parser
---
Questions? Open an issue or start a discussion
Need help integrating? Check out our detailed integration guide with complete examples.