{"id":"216d19b8-1174-4a94-a73a-3c1e5c9e44d8","slug":"oel-studio","kind":"skill","name":"oel-studio","summary":"Plateforme d'outils pour les étudiants, par les étudiants.","owner":"EaglesView","repoUrl":"https://github.com/EaglesView/oel-studio","license":"MPL-2.0","licenseTier":"weak-copyleft","trust":"community","stars":2,"match":null,"fewStars":true,"format":"skill","createdAt":"2026-10-06T19:47:08.000Z","addedAt":"2026-10-22T00:00:06.029Z","logoUrl":"https://avatars.githubusercontent.com/u/146263595?u=8a1910c581a6b006617edb717bdc9f9c9dba31d0&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["writing"],"tags":[],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-26T05:00:21.623Z","sample":false,"url":"https://conduits.dev/tools/oel-studio","language":"TypeScript","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"<div align=\"center\">\n\n<img src=\"apps/web/public/favicon.svg\" width=\"72\" height=\"72\" alt=\"\" />\n\n# Bureau · OutilsEnLigne\n\n**Every file of a project on one desk — documents, spreadsheets, presentations and images — edited in the browser,\nwith Word, Excel and PowerPoint files kept intact.**\n\n[![Licence: MPL-2.0](https://img.shields.io/badge/licence-MPL--2.0-7759c5)](LICENSE)\n![Rust](https://img.shields.io/badge/engines-Rust%20%E2%86%92%20WebAssembly-34333d)\n![TypeScript](https://img.shields.io/badge/app-TypeScript%20%C2%B7%20React%20%C2%B7%20Astro-34333d)\n![UI in French and English](https://img.shields.io/badge/UI-fr--CA%20%C2%B7%20en-14ad5c)\n\n<img src=\"apps/web/public/captures/desk.png\" alt=\"The Bureau: a spreadsheet, a presentation, an image and a document side by side on a desk, joined by threads.\" width=\"900\" />\n\n</div>\n\nThe Bureau lays the files of a project side by side, like paper on a table. Double-click a paper to open it in\nplace; the tools follow what you touch. A chart can be linked into a slide and a picture into a document, and the\ncopies follow their source. Everything runs in the browser: the file formats are handled by Rust engines compiled to\nWebAssembly, and in this release your files never leave your device.\n\nMade in Québec for students, from high school to university. The interface is in French (fr-CA) or English (asked on the\nfirst visit, changed in « Paramètres »); the site and the documentation are in French and English.\n\n## Highlights\n\n- **Lossless Office round trips.** `.docx`, `.xlsx` and `.pptx` go through codecs that rewrite only what you changed;\n  untouched parts, styles, themes, charts and anything not modelled yet (fields, SmartArt, animations…) come back as\n  they were.\n- **Real editors.** A Word-like document editor (styles, lists, tables, footnotes, headers, pagination), an\n  Excel-compatible spreadsheet (IronCalc: `XLOOKUP`, `MINIFS`, `RANK.EQ`…, charts), a PowerPoint editor (layouts,\n  shapes, notes, presenter view), and a non-destructive image workshop (wgpu: WebGPU → WebGL2 → CPU).\n- **Linked copies (« fils de liaison »).** Put a chart, a range or an image in a slide or a document; it stays up to\n  date (live, manual or frozen), and a thread on the desk shows where it comes from.\n- **Accessible desk.** A DOM canvas that is a real listbox: every gesture has a key, moves are announced, a list view\n  is always one click away. Built on react-aria.\n- **Private by default.** The single-user release keeps the desk and every file in IndexedDB, with a lossless\n  « Exporter le bureau (.zip) » backup.\n\n## Try it\n\nYou need **Node 24+** and **Rust** (stable, edition 2024) with the `wasm32-unknown-unknown` target; `wasm-pack`\ncomes from npm.\n\n```bash\nrustup target add wasm32-unknown-unknown\nnpm install\nnpm run dev        # http://localhost:4321 — the site, /bureau (the editor), /docs\n```\n\n`npm run dev` builds the Rust engines to WebAssembly first when they are stale. Then open\n<http://localhost:4321/bureau>: a new desk holds a demo (a lap-times spreadsheet, a welcome deck whose chart is linked\nto it, a logo and a document).\n\n| Command | What it does |\n|---|---|\n| `npm run dev` | Single-user Bureau + site (no server) |\n| `npm run dev:equipe` | Team edition: web + collaboration server on :8787 |\n| `npm test` | `cargo test --workspace`, then every vitest suite |\n| `npm run typecheck` | Regenerates the Rust → TS contract types, then `tsc` per package |\n| `npm run build` | Static site in `apps/web/dist` (`PUBLIC_EDITION=equipe npm run build` for the team build) |\n| `npm run build:wasm` | Rebuilds every crate's WASM (web + Node targets) into `packages/wasm/` |\n| `bash scripts/build-site.sh` | Hosting build: installs Rust if missing, browser WASM only, then the site (DigitalOcean: `.do/site.Dockerfile` + `.do/app.yaml`) |\n\n## Editions\n\nOne switch, `PUBLIC_EDITION` (`apps/web/src/edition.ts`), decides what the front end shows. Packages never read it;\nthe app passes flags down as props.\n\n| | `solo` (default, this release) | `equipe` (built, not shipped yet) |\n|---|---|---|\n| Storage | Desk and files in this browser (IndexedDB), `.zip` backup | Plus the collaboration server (`apps/collab`) |\n| Sharing, presence, version history | Hidden | Share links with roles, live avatars, named and automatic versions |\n| Forms | Hidden | Builder, linked response spreadsheet, public respondent page (local stub backend) |\n| Projects and members | One desk, « Mon bureau » | Projects, four roles, settings cascade (local stub backend) |\n\n## Repository map\n\n```\ncrates/                 Rust workspace — file formats and computation only (no UI)\n  oel-opc/              lossless XML DOM + OPC package (zip, rels, content types)\n  oel-docx/             .docx ⇄ ProseMirror JSON\n  oel-xlsx/             .xlsx / .csv ⇄ workbook JSON, IronCalc calculation\n  oel-pptx/             .pptx ⇄ deck JSON\n  oel-chart/            DrawingML charts ⇄ ChartSpec, shared by the three codecs\n  oel-img/              non-destructive image pipeline (CPU reference + wgpu)\npackages/               TypeScript, shipped as source and compiled by the app\n  engine/   @oel/engine     file detection, engine contract, Web Worker host, WASM adapters, generated types\n  emboss/   @oel/emboss     blind-emboss UI kit on react-aria-components, Figma tokens (light/dark)\n  desk/     @oel/desk       accessible infinite desk: framework-free core + React DOM renderer\n  docs/     @oel/docs       document editor (Tiptap/ProseMirror + Yjs)\n  sheets/   @oel/sheets     spreadsheet editor (canvas grid, IronCalc in a worker)\n  slides/   @oel/slides     presentation editor, slideshow, presenter view\n  charts/   @oel/charts     Office chart renderer (every chart type) and chart UI\n  img/      @oel/img        image engine host, recipes, originals by content hash\n  links/    @oel/links      linked copies: model, states, desk threads\n  fonts/    @oel/fonts      fonts of opened files, open substitutes (Fontsource, OFL)\n  collab-client/            Yjs session base, offline storage, sync / share / version UI\n  forms/    @oel/forms      forms builder and respondent page (team edition)\napps/\n  web/      @oel/web        Astro site: home, /docs (fr + en), /bureau (the editor)\n  collab/   @oel/collab     collaboration server: Hocuspocus (Yjs), share links, versions, exports (team edition)\nfixtures/               shared test corpus (docx, xlsx, pptx, charts, images, the demo Bureau)\ndocs/                   plans (docs/plans/) and package details (docs/packages.md)\n```\n\n## How it fits together\n\n```mermaid\nflowchart LR\n  subgraph Rust[\"crates/ (Rust)\"]\n    opc[oel-opc] --> docx[oel-docx]\n    opc --> xlsx[oel-xlsx]\n    opc --> pptx[oel-pptx]\n    chart[oel-chart] --> docx & xlsx & pptx\n    img[oel-img]\n  end\n  Rust -- wasm-pack --> wasm[\"packages/wasm/*\"]\n  wasm --> worker[\"@oel/engine<br/>Web Worker\"]\n  worker -- \"JSON + bytes\" --> editors[\"@oel/docs · sheets · slides · img\"]\n  editors -- \"Yjs (live model)\" --> idb[(IndexedDB)]\n  editors --> bureau[\"apps/web /bureau<br/>(@oel/desk + @oel/links)\"]\n```\n\nFiles are import/export; the live model of every open file is a Yjs document, saved on the device (and synced to\nthe server in the team edition). The editor shell never parses a file: it asks the engine worker. Layer rules and the\nreasoning are in [`ARCHITECTURE.md`](ARCHITECTURE.md); each package in detail in\n[`docs/packages.md`](docs/packages.md).\n\n## The Rust crates\n\nThe most reusable part of the project: lossless OOXML in Rust is rare. Each crate builds natively and, with its\n`wasm` feature, for the browser and Node.\n\n| Crate | Library | What it does |\n|---|---|---|\n| `oel-opc` | `oel_opc` | XML DOM that keeps what it doesn't understand, OPC packages (parts, relationships, content types) |\n| `oel-docx` | `oeldocx` | `.docx` → editor JSON → `.docx`, rewriting only what changed |\n| `oel-xlsx` | `oelxlsx` | `.xlsx` and `.csv` ⇄ workbook JSON, formulas computed with IronCalc |\n| `oel-pptx` | `oelpptx` | `.pptx` ⇄ deck JSON (layouts, themes, DrawingML) |\n| `oel-chart` | `oelchart` | every Office chart type read to a `ChartSpec`, charts written back |\n| `oel-img` | `oelimg` | recipe-based image retouching, CPU reference and wgpu (parity-tested) |\n\n```bash\ncargo test --workspace\ncargo run -p oel-xlsx --example recalc -- in.xlsx out.xlsx   # compute formulas and chart caches of any workbook\n```\n\n## Status\n\nWorking: the desk (selection, zoom, notes, galleries, list view, saved on the device, `.zip` backup), documents,\nspreadsheets with charts, presentations with slideshow and presenter view, the image workshop, linked copies\n(charts, ranges, images) written into exports. Not yet: PDF viewing and annotation (a PDF keeps its page count only),\nediting charts inside slides and documents, animations and SmartArt (kept, not editable), a translated Bureau UI.\nThe full table is in [`docs/packages.md`](docs/packages.md#whats-real-and-whats-stubbed); what users see is in the\nsite's documentation (`/docs`, `/en/docs`).\n\n**Next:** the team edition on a Canadian-hosted server (accounts, sharing, forms backend —\n`docs/plans/2026-10-backend-mvp.md`), a mobile layout, the PDF engine, a desktop app (Tauri).\n\n## For AI agents\n\nStart with [`AGENTS.md`](AGENTS.md): commands, conventions, the edition switch and where things live. Task-specific\nguides are in `.claude/skills/oel-*/SKILL.md` (plain Markdown, usable by any agent): `oel-architecture` first, then\n`oel-rust-engine`, `oel-file-kind`, `oel-editor-feature`, `oel-charts` or `oel-collab-backend`, and `oel-verify` to\nfinish. Plans with their status live in `docs/plans/`.\n\n## Contributing, security, licence\n\n- How to contribute: [`CONTRIBUTING.md`](CONTRIBUTING.md). Reporting a vulnerability: [`SECURITY.md`](SECURITY.md).\n- Licensed under the [Mozilla Public License 2.0](LICENSE): use the crates and packages in your own projects; changes\n  to these files stay open.\n- Third-party code, fonts and icons: [`THIRD_PARTY.md`](THIRD_PARTY.md).\n"}