OpenFile is a static single-page app. Every one of its 590 tools runs inside the user's browser tab; the build output (dist/) is plain HTML, JS, CSS and WASM loaders that any static host can serve.
%%{init: {'theme':'base','themeVariables':{'fontFamily':'system-ui, sans-serif','lineColor':'#F5A524','primaryTextColor':'#F5F3EE','clusterBkg':'#050505','clusterBorder':'#F5A524','titleColor':'#FFB224'}}}%%
flowchart TB
subgraph TAB["🌐 Browser tab"]
direction TB
MAIN["main.tsx · App.tsx<br/>React Router routes"]:::ui
PAGES["pages/<br/>Home · Tools · ToolPage · Workspace · Status"]:::ui
REG["tools/registry.ts<br/>TOOLS + CATEGORIES"]:::ui
CHUNK["tools/category/slug.tsx<br/>one lazy chunk per tool"]:::ui
LIB["lib/<br/>files · pdf · ffmpeg · handoff · store"]:::lib
ENG["Engines loaded on demand<br/>pdf-lib · PDF.js · ffmpeg.wasm · Tesseract · Transformers.js · ONNX"]:::eng
LOCAL["IndexedDB + localStorage<br/>favorites · recents · prefs · recipes"]:::store
MAIN --> PAGES --> REG --> CHUNK --> LIB --> ENG
PAGES --> LOCAL
end
SW["Service worker sw.js<br/>network-first pages · cache-first assets"]:::sw -.-> TAB
API["Optional Vercel functions<br/>/api/health · /api/fetch-page · /api/meta"]:::api -. "URLs only, never files" .- TAB
classDef ui fill:#F5A524,stroke:#FFE3A3,color:#050505
classDef lib fill:#111418,stroke:#22D3EE,color:#F5F3EE,stroke-width:2px
classDef eng fill:#111418,stroke:#14B8A6,color:#F5F3EE,stroke-width:2px
classDef store fill:#111418,stroke:#10B981,color:#F5F3EE,stroke-width:2px
classDef sw fill:#0B0D10,stroke:#A8A29E,color:#F5F3EE,stroke-dasharray:4 3
classDef api fill:#0B0D10,stroke:#FFB224,color:#FFE3A3,stroke-dasharray:6 4
src/App.tsxdeclares the routes:/,/tools,/category/:id,/workspace,/about,/privacy,/status,/docsand/docs/*,/changelog,/history,/settings,/blogand/blog/:slug,/install(and/download),/open, and the catch-all/:slugthat rendersToolPage.src/tools/registry.tsis the single source of truth. It holds the core tools and spreads in the entries fromsrc/tools/batches/b1.tstob5.ts, so parallel work on new tools never touches the same file. EachToolMetahas aslug,name,desc,category, Lucideicon, optionalbadge(NEW/AI/HOT/PRO),popularflag and optionalpipelinemode (image/pdf) for the Workspace.loadTool(slug)resolves./<category>/<slug>.tsxthroughimport.meta.glob, so Vite emits one chunk per tool. Adding a tool never makes the homepage heavier.
| Category | Tools |
|---|---|
| 📄 PDF Tools | 63 |
| 🔄 Convert | 35 |
| 🖼️ Image | 60 |
| 🎬 Video | 40 |
| 🎧 Audio | 26 |
| 🧑💻 Developer | 65 |
| 📝 Text & Data | 47 |
| 🖌️ Design | 21 |
| 📊 Data | 15 |
| 🤖 AI | 21 |
| 🧊 3D | 9 |
| 🗜️ Archives | 8 |
| 📚 eBooks | 8 |
| 🔤 Fonts | 7 |
| 📐 CAD | 6 |
| 💬 Subtitles | 10 |
| 🔐 Security & Privacy | 15 |
| 🗺️ Maps & GPS | 15 |
| 🗂️ Office & Sheets | 19 |
| 🧪 Science & Education | 15 |
| 🎙️ Creator Studio | 14 |
| 🎓 Study & Classroom | 12 |
| 🌐 Web & SEO | 13 |
| 📅 Calendar & Time | 12 |
| 💰 Money & Finance | 10 |
| ❤️ Health & Fitness | 6 |
| 🧠 AI Builder | 9 |
| 📦 Data Exports | 9 |
| Total | 590 |
| Engine | Used for | How it loads |
|---|---|---|
| pdf-lib, @cantoo/pdf-lib | Create / modify PDFs, encryption | Dynamic import in the tool |
PDF.js (pdfjs-dist) |
Rendering, thumbnails, text extraction, rasterising | Dynamic import, worker |
| ffmpeg.wasm | Video and audio transcode, trim, merge, GIF | Single-threaded core served by OpenFile itself from public/ffmpeg (public CDNs as a fallback), then cached |
| Tesseract.js | OCR | Language data fetched per language, cached |
| Transformers.js / ONNX Runtime | Whisper transcription, super-resolution, chat, summaries, translation, neural voices | Model weights fetched on first use in a Web Worker, WebGPU when available, WASM otherwise. See AI.md |
| @imgly/background-removal | Background removal | Model fetched on first use |
| Canvas / OffscreenCanvas | All image tools and PDF rasterising | Built into the browser |
| docx, mammoth, SheetJS, pptxgenjs, jsPDF | Office conversions | Dynamic import |
| MediaRecorder, Web Audio, Speech Synthesis | Recorders, audio editor, text-to-speech | Built into the browser |
%%{init: {'theme':'base','themeVariables':{'fontFamily':'system-ui, sans-serif','actorBkg':'#0B0D10','actorBorder':'#F5A524','actorTextColor':'#F5F3EE','actorLineColor':'#A8A29E','signalColor':'#14B8A6','signalTextColor':'#A8A29E','noteBkgColor':'#F5A524','noteTextColor':'#050505','noteBorderColor':'#FFB224'}}}%%
sequenceDiagram
autonumber
actor U as You
participant H as Home smart drop
participant T as Tool component
participant E as Engine
U->>H: Drop any file
H->>H: Detect type and suggest tools
H->>T: Hand the File over in memory via lib/handoff
T->>E: Dynamic import, then process bytes
E-->>T: Progress and output bytes
T-->>U: Blob URL download or ZIP
Note over U,E: No network request carries the file.
src/pages/workspace/steps.ts defines pipeline steps (each a pure run(items, params, onProgress) over { name, blob } items) and presets.
%%{init: {'theme':'base','themeVariables':{'fontFamily':'system-ui, sans-serif','lineColor':'#F5A524','primaryTextColor':'#F5F3EE'}}}%%
flowchart LR
IN["Files"]:::a --> S1["Step 1"]:::b --> S2["Step 2"]:::b --> SN["Step n"]:::b --> Z["ZIP via fflate / JSZip"]:::c
R["Saved recipe"]:::d -.-> S1
classDef a fill:#F5A524,stroke:#FFE3A3,color:#050505
classDef b fill:#0B0D10,stroke:#F5A524,color:#F5F3EE,stroke-width:2px
classDef c fill:#10B981,stroke:#A7F3D0,color:#050505
classDef d fill:#0B0D10,stroke:#22D3EE,color:#F5F3EE,stroke-dasharray:5 4
- Image steps: resize, convert, compress, rotate / flip, filter, watermark, rounded corners, rename.
- PDF steps: merge all, rotate, page numbers, watermark, clean metadata, compress (rasterise), grayscale.
- Presets: Web-ready photos, Product catalog, Social avatars, Share-safe PDF pack, Confidential drafts, Shrink scans.
%%{init: {'theme':'base','themeVariables':{'fontFamily':'system-ui, sans-serif','lineColor':'#F5A524','primaryTextColor':'#F5F3EE'}}}%%
flowchart LR
P["git push main"]:::g --> A["GitHub Actions<br/>deploy-pages.yml"]:::c
A --> B["npm run build:pages<br/>VITE_BASE=/OpenFile/"]:::c
B --> PB["postbuild.mjs<br/>404.html + .nojekyll"]:::c
PB --> GP["gh-pages branch → GitHub Pages"]:::l
P --> V["Vercel<br/>npm run build"]:::v --> VL["openfile-studio.vercel.app"]:::l
classDef g fill:#0B0D10,stroke:#A8A29E,color:#F5F3EE
classDef c fill:#111418,stroke:#38BDF8,color:#F5F3EE,stroke-width:2px
classDef v fill:#050505,stroke:#F5A524,color:#F5F3EE,stroke-width:2px
classDef l fill:#F5A524,stroke:#FFE3A3,color:#050505
- GitHub Pages has no server-side rewrites, so
scripts/postbuild.mjscopiesindex.htmlto404.html, making deep links like/OpenFile/merge-pdfwork. - Vercel uses
vercel.jsonfor SPA rewrites (excluding/api/,/assets/,/media/), immutable caching of hashed assets, and security headers (nosniff, strict referrer policy, camera / mic / display-capture limited to self).
- No code path sends user file bytes over the network.
- The three optional API routes accept a URL string only.
- Preferences, favorites, recents and saved recipes live in the browser's own storage and can be cleared from the browser at any time.
- Contributions that upload user files are not accepted (see CONTRIBUTING.md).
%%{init: {'theme':'base','themeVariables':{'fontFamily':'system-ui, sans-serif','lineColor':'#F5A524','primaryTextColor':'#F5F3EE'}}}%%
flowchart TD
R["Request"]:::a --> N{"Page navigation?"}:::b
N -- yes --> NF["Network first, 6 s timeout"]:::c --> SC["Cached page, app shell, offline.html"]:::c
N -- no --> A{"Tool code, engine, font, wasm?"}:::b
A -- yes --> CF["Cache first: openfile-assets"]:::d
A -- no --> M{"Model or CDN host?"}:::b
M -- yes --> MC["Cache first: openfile-models"]:::d
M -- no --> SW["Stale while revalidate: shell cache"]:::c
SH["OS share sheet POST /share-target"]:::e --> SHC["openfile-share cache"]:::d --> UI["Drop anything sheet"]:::a
classDef a fill:#F5A524,stroke:#FFE3A3,color:#050505
classDef b fill:#0B0D10,stroke:#F5A524,color:#F5F3EE,stroke-width:2px
classDef c fill:#111418,stroke:#38BDF8,color:#F5F3EE,stroke-width:2px
classDef d fill:#111418,stroke:#10B981,color:#F5F3EE,stroke-width:2px
classDef e fill:#0B0D10,stroke:#22D3EE,color:#F5F3EE,stroke-dasharray:5 4
public/sw.jsprecaches the app shell at install (scripts/postbuild.mjswrites the build id and the precache list), and waits for the page to say "reload" before a new version takes over.public/manifest.webmanifestdeclaresfile_handlers(Open with OpenFile, handled at/open), ashare_target(/share-target, received by the service worker) and app shortcuts.desktop/(Tauri v2) andmobile/(Capacitor) wrap the samedist/build..github/workflows/release-apps.ymlbuilds every platform on av*tag. See INSTALL.md.
%%{init: {'theme':'base','themeVariables':{'fontFamily':'system-ui, sans-serif','lineColor':'#F5A524','primaryTextColor':'#F5F3EE'}}}%%
flowchart LR
SRC["registry · Overlays shortcuts · sketch shortcuts<br/>AI model ids · manifest · CHANGELOG · README roadmap"]:::a --> GEN["scripts/gen-docs.mjs<br/>(prebuild)"]:::b
GEN --> J["src/pages/docs/generated.json"]:::c
GEN --> MD["docs/SHORTCUTS.md and gen blocks in docs/*.md"]:::c
J --> SITE["/docs site<br/>src/pages/Docs.tsx + src/pages/docs/"]:::a
REG["TOOLS, formats, Workspace steps, prefs<br/>(imported at runtime)"]:::d --> SITE
SITE --> PB["postbuild.mjs<br/>pre-renders every /docs route"]:::b
classDef a fill:#F5A524,stroke:#FFE3A3,color:#050505
classDef b fill:#111418,stroke:#38BDF8,color:#F5F3EE,stroke-width:2px
classDef c fill:#111418,stroke:#10B981,color:#F5F3EE,stroke-width:2px
classDef d fill:#0B0D10,stroke:#22D3EE,color:#F5F3EE,stroke-dasharray:5 4
Nothing that counts or lists things in the docs is typed by hand. The docs site reads the registry, src/lib/formats.ts, the Workspace steps and the preferences at runtime, and reads everything else from generated.json, which scripts/gen-docs.mjs rebuilds before every build.
OpenFile has 590 tools in 28 categories. PDF Tools 63, Convert 35, Image 60, Video 40, Audio 26, Developer 65, Text & Data 47, Design 21, Data 15, AI 21, 3D 9, Archives 8, eBooks 8, Fonts 7, CAD 6, Subtitles 10, Security & Privacy 15, Maps & GPS 15, Office & Sheets 19, Science & Education 15, Creator Studio 14, Study & Classroom 12, Web & SEO 13, Calendar & Time 12, Money & Finance 10, Health & Fitness 6, AI Builder 9, Data Exports 9.
Back to the README · Writing a tool: TOOL_GUIDE.md · AI.md · PRIVACY.md · TROUBLESHOOTING.md · SHORTCUTS.md