Lightweight, open-source document management for construction and engineering teams.
No build tools. No backend. Pure vanilla JavaScript.
Live Demo: https://davras5.github.io/open-docs/
OpenDocs is a zero-build, single-page web application for storing, previewing, sharing, and collaborating on office and construction documents directly in the browser. Think of it as a lightweight, open-source alternative to SharePoint or Google Drive, purpose-built for construction, architecture, and engineering workflows.
It runs entirely as static files (HTML + CSS + JS) and can be deployed on GitHub Pages, any static host, or served from a local folder. Document storage uses the browser's IndexedDB via localForage, with files fetched from a configurable file directory.
Status: This is a working prototype / proof of concept. It demonstrates the UX, document viewing capabilities, and metadata architecture. Production use would require a backend for multi-user access, authentication, and persistent storage.
- File browser with grid and list views, folders, breadcrumb navigation, drag-and-drop upload
- In-browser document preview for 9+ file formats (see Supported Formats)
- DWG/DXF CAD viewer with pan, zoom, and full entity rendering via LibreDWG WASM
- IFC 3D BIM viewer with orbit controls, element picking, and property inspection via Three.js + web-ifc
- Confluence-style document viewer with dark overlay, left/right navigation, and image zoom
- Document metadata following Dublin Core and construction standards (see Metadata)
- URL routing with shareable links for folders and documents (
/#/d/projektbeschrieb,/#/s/pB7xK2) - Search across file names and metadata
- Share modal with copy-to-clipboard short URLs and permission display
- Dark theme with full design token system
- Responsive layout for desktop, tablet, and mobile
- Accessible with WCAG AA focus indicators, proper ARIA, and contrast-compliant colors
OpenDocs follows a deliberately simple architecture: no frameworks, no build steps, no server dependencies.
graph TB
subgraph "Browser (Client)"
UI["index.html — SPA Shell"]
Tokens["tokens.css — Design System"]
Styles["style.css — Components"]
App["app.js — Core Application"]
DWG["dwg-viewer.js — CAD Viewer"]
IFC["ifc-viewer.js — IFC 3D Viewer"]
end
subgraph "Storage Layer"
IDB[("IndexedDB via localForage")]
Meta["metadata.json — Document Catalog"]
Files["demo-files/ — Static Files"]
end
subgraph "CDN Libraries"
LF["localForage 1.10"]
Mammoth["Mammoth.js 1.6"]
SheetJS["SheetJS 0.20"]
PDFJS["PDF.js 3.11"]
LibreDWG["LibreDWG-Web 0.6 (WASM)"]
Lucide["Lucide Icons 0.468"]
end
UI --> App
UI --> Tokens --> Styles
App --> IDB
App --> Meta
App --> Files
App --> DWG
App --> IFC
App --> LF & Mammoth & SheetJS & PDFJS
DWG --> LibreDWG
IFC --> ThreeJS["Three.js 0.155 + web-ifc (WASM)"]
UI --> Lucide
graph LR
subgraph "app.js Modules"
Storage["Storage Engine\n(IndexedDB CRUD)"]
UImod["UI Renderer\n(File list, breadcrumbs)"]
FileOps["File Operations\n(Upload, download, delete)"]
Viewer["Document Viewer\n(Dark overlay modal)"]
Editor["Rich Text Editor\n(contenteditable)"]
Router["URL Router\n(Hash-based navigation)"]
Metadata["Metadata Loader\n(metadata.json)"]
Search["Search\n(Debounced name matching)"]
CtxMenu["Context Menu\n(Right-click actions)"]
DragDrop["Drag & Drop\n(File upload)"]
end
Router --> UImod
Router --> Viewer
Router --> Metadata
UImod --> Storage
FileOps --> Storage
Viewer --> Storage
Editor --> Storage
Search --> Storage
open-docs/
├── index.html # Single-page application shell
├── css/
│ ├── tokens.css # Design tokens (CSS custom properties)
│ └── style.css # Component styles
├── js/
│ ├── app.js # Core application logic
│ ├── dwg-viewer.js # Standalone DWG/DXF CAD viewer
│ └── ifc-viewer.js # IFC 3D BIM viewer (Three.js + web-ifc)
├── data/
│ └── metadata.json # Document metadata database
├── demo-files/ # Static demo files (Swiss construction project)
│ ├── 01 Planung/ # .docx, .xlsx, .dwg files
│ ├── 02 Bewilligungen/ # .pdf, .docx files
│ ├── 03-08 .../ # Various office and construction files
│ └── ...
├── assets/ # README images
└── generate_demo_v2.py # Python script to regenerate demo files
- No build step -- open
index.htmlin a browser and it works. Deploy by copying files. - Read from storage -- documents and folders are read from a configurable storage layer (currently IndexedDB, designed for file system or S3-compatible backends).
- Metadata-driven -- a structured
metadata.jsondefines the document catalog with Dublin Core fields, construction metadata, version history, and sharing information. - Progressive enhancement -- the app works without any specific library; CDN failures degrade gracefully.
- Security by default -- all external HTML is sanitized. CDN scripts use SRI hashes where supported.
| Format | Library | Capabilities |
|---|---|---|
| .docx (Word) | Mammoth.js | Formatted HTML: headings, tables, lists, images |
| .xlsx (Excel) | SheetJS | First sheet as HTML table with headers |
| PDF.js | All pages rendered to canvas, scrollable | |
| .dwg / .dxf (AutoCAD) | LibreDWG-Web (WASM) | Full 2D rendering with 20+ entity types, pan/zoom |
| .ifc (BIM) | Three.js + web-ifc (WASM) | 3D orbit viewer with element picking & properties |
| .jpg .png .gif .svg .webp | Native browser | Zoom (scroll, double-click, drag-to-pan) |
| .md (Markdown) | Built-in renderer | Headings, tables, lists, code blocks, bold/italic |
| .txt .json .csv .js .html .css .xml | Native TextDecoder | Monospace preformatted text |
LINE, LWPOLYLINE, POLYLINE2D/3D, CIRCLE, ARC, ELLIPSE, SPLINE, TEXT, MTEXT, ATTRIB, POINT, SOLID, 3DSOLID, TRACE, HATCH (solid fill), DIMENSION (block-based + fallback), LEADER, MLINE, 3DFACE, RAY, XLINE, INSERT (recursive block expansion with OCS extrusion and mirroring).
OpenDocs uses a structured metadata model inspired by established standards:
| Standard | Scope |
|---|---|
| Dublin Core (ISO 15836) | Title, creator, description, type, language, rights |
| eCH-0160 | Swiss records management: classification, retention, access |
| DCAT (W3C) | Data catalog vocabulary for document discovery |
| SIA 2051 / ISO 19650 | Construction: discipline, SIA phase, revision, status, scale |
{
"id": "doc-001",
"slug": "projektbeschrieb",
"shareToken": "pB7xK2",
"title": "Projektbeschrieb Ueberbauung Seefeld",
"creator": "Arch. ETH Laura Brunner",
"description": "Detaillierte Projektbeschreibung...",
"type": "Bericht",
"language": "de-CH",
"rights": "Vertraulich",
"discipline": "Architektur",
"phase": "32 Bauprojekt",
"revision": "2.0",
"status": "Freigegeben",
"tags": ["Planung", "Architektur"],
"versions": [
{ "version": 1, "date": "2025-11-20", "author": "brunner@be-arch.ch", "comment": "Erstversion" }
]
}| URL Pattern | Destination |
|---|---|
/#/ |
Root file browser |
/#/f/ueberbauung-seefeld/01-planung |
Folder navigation (nested slugs) |
/#/d/projektbeschrieb |
Document viewer (by slug) |
/#/s/pB7xK2 |
Share link (short token) |
/#/settings |
Settings view |
All URLs are bookmarkable and shareable. Hash-based routing works on GitHub Pages without server configuration.
The prototype ships with a realistic Swiss construction project:
Ueberbauung Seefeld, Zurich -- 7-storey mixed-use building, 48 apartments, CHF 62.8M, Minergie-P-ECO.
- 28 documents across 8 folders with full metadata
- Real
.docxwith formatting (python-docx),.xlsxwith headers (openpyxl), multi-page.pdf(fpdf2) - Real
.dwgAutoCAD files, construction photos (Unsplash) - Swiss terminology: BKP costs, SIA phases, VKF fire safety, SIBE
Regenerate: python generate_demo_v2.py (requires python-docx, openpyxl, fpdf2).
git clone https://github.com/davras5/open-docs.git
cd open-docs
# No build -- just open it
open index.html
# Or serve locally
npx serve .For GitHub Pages: Settings > Pages > Deploy from branch main, folder / (root).
Built on a CSS custom property token system (css/tokens.css):
- Color primitives (Slate-based neutrals) mapped to semantic tokens
- Dark theme via token reassignment (single
.dark-themeclass) - 7-step typography scale (rem-based)
- 4px-base spacing scale (12 steps)
- 5 elevation levels, 3 motion durations
- WCAG AA compliant: 40px touch targets, 4.5:1 contrast ratios
OpenDocs today runs entirely in the browser. The next step is a backend API that turns it into a real multi-user platform -- focused on what project stakeholders actually need: finding, viewing, and sharing documents.
%%{init: {'theme': 'base', 'themeVariables': {
'primaryColor': '#93C5FD',
'lineColor': '#999',
'textColor': '#1a1a2e',
'cScale0': '#93C5FD',
'cScale1': '#C4B5FD',
'cScale2': '#FDBA74',
'cScale3': '#5EEAD4',
'cScale4': '#A5B4FC',
'cScale5': '#FDE047',
'cScale6': '#F9A8D4',
'cScale7': '#67E8F9',
'cScale8': '#FCA5A5',
'cScale9': '#BEF264'
}}}%%
mindmap
root((OpenDocs API))
**Documents**
Upload & download
Metadata schemas per project
Revision control & status workflow
Naming conventions
Comparison & diff
Trash & retention policies
**Intelligence**
Auto-enrichment on upload
Text & metadata extraction
OCR
Auto-tagging
Embedding & indexing
Question answering across documents
Summarization
Smart suggestions
Related documents
Missing metadata
Duplicates
**Relations**
Document to document links
Document to model links
Spatial references
Element-level bindings
Typed links
References / Supersedes
Depends on / Derived from
Auto-discovered relations
Knowledge graph queries
**Processing**
Format conversion
Office to PDF
CAD to SVG
IFC to glTF
Thumbnails
Visual diff between revisions
**Projects**
Hierarchy & folders
Templates
Multi-tenant isolation
Phase & status tracking
**Auth & Permissions**
OAuth2 / OIDC
Role-based access
Inheritable folder & document permissions
API keys
**Collaboration**
Sharing with expiry & watermarking
Comments & threads
Approval workflows
Transmittals
**Search**
Full-text & semantic search
Metadata & tag filters
Spatial queries
Faceted results
**Events & Audit**
Immutable event log
Audit trail with export
Activity feed
Webhooks & notifications
**Storage & Sync**
Pluggable backends
Desktop folder sync
Offline-first with conflict resolution
- Document versioning & backup -- metadata schema supports it; needs backend storage for binary diffs
- IAM (Identity & Access Management) -- no authentication; hardcoded mock user
- Multi-user collaboration -- single-browser only; no real-time sync
| Feature | Complexity | Notes |
|---|---|---|
| Document versioning & history | Medium | Version metadata exists; needs diff storage backend |
| Comments & annotations | Medium | Per-document threads, PDF annotation layers |
| IAM & role management | High | Per-folder/document permissions, audit trail |
| Third-party IAM (OAuth2/OIDC) | High | Azure AD, Keycloak, Auth0 |
| i18n / multi-language | Medium | Externalize UI strings, language switcher |
| Improved search & indexing | High | Full-text index (Meilisearch), faceted filters, tag search |
| REST / GraphQL API | High | Document CRUD, metadata management, file upload |
| Storage backends (S3, WebDAV) | Medium | Replace IndexedDB with server-side storage |
| Multi-tenant / project management | High | Tenant isolation, project-level access |
| Backend automation | Medium | Webhooks, approval workflows |
| Automatic metadata extraction | Medium | Parse Office metadata, classify by content |
| RAG (Retrieval-Augmented Generation) | High | Vector embeddings of documents for LLM-powered Q&A |
| Live collaborative editing | Very High | CRDT (Yjs) or OT; requires WebSocket server |
| IFC viewer (BIM models) | Client-side via Three.js + web-ifc; server-side conversion needed for large files | |
| Point cloud viewer (.las/.laz) | High | Potree; needs backend tiling for large scans |
| 360-degree photo viewer | Medium | Pannellum; feasible client-side |
| Office tool plugins | Medium | Microsoft 365 / Google Workspace add-ins |
| Windows folder sync plugin | Medium | Desktop tray app or shell extension to sync a local folder with OpenDocs |
| Wiki & project management | Very High | Kanban, backlog, issues, markdown wiki |
| PDF annotation & markup | Medium | Draw, highlight, comment as separate layer |
| Offline-first with sync | High | Service Worker + CRDTs for eventual consistency |
| Audit trail & compliance | Medium | eCH-0160 / ISO 15489 access logging |
- HTML sanitization -- external HTML from document renderers is sanitized (strips scripts, iframes, event handlers)
- SRI hashes -- CDN scripts pinned with Subresource Integrity where supported
- XSS escaping -- user-facing strings use
textContentassignment or_esc()helpers - Client-side only -- no server attack surface, but also no authentication
| Layer | Technology |
|---|---|
| UI | Vanilla HTML5, CSS3, JavaScript (ES2017+) |
| Icons | Lucide 0.468.0 |
| Storage | localForage 1.10.0 (IndexedDB) |
| Word preview | Mammoth.js 1.6.0 |
| Excel preview | SheetJS 0.20.1 |
| PDF preview | PDF.js 3.11.174 |
| CAD preview | LibreDWG-Web 0.6.6 (WASM) |
| BIM preview | Three.js 0.155 + web-ifc 0.0.66 (WASM) |
| Design system | CSS custom properties (tokens.css) |
| Deployment | GitHub Pages (static files) |
Built with vanilla JS and open-source libraries. No frameworks were harmed.

