All projects Fundus · Write-up
Everyday tools, nothing sentWerkzeuge für jeden Tag, nichts verschickt
Fundus files twenty everyday tools for photos, PDFs, text, numbers and time under article numbers, like a stock of parts, plus six for developers. Every one runs in the browser, HEIC and PDFs included, and the page may talk only to its own address, so what you put in never leaves the device.Fundus legt zwanzig Werkzeuge für jeden Tag, für Fotos, PDFs, Text, Zahlen und Zeit, unter Artikelnummern ab wie einen Bestand an Teilen, dazu sechs für Entwickler. Jedes läuft im Browser, HEIC und PDFs eingeschlossen, und die Seite darf nur mit ihrer eigenen Adresse sprechen, so verlässt nichts, was man hineingibt, das Gerät.
- Type
- Web appWeb-App
- Stack
- Svelte 5 · WebAssembly · Node
- Year
- 2026
- Code
- Public on GitHubÖffentlich auf GitHub
Filed by number
Fundus is a stock of everyday tools, the kind people search for when a photo is too big to upload or a PDF needs a signature: twenty of them, for photos, PDFs, text, numbers and time. Each one is filed like a part in an inventory, with an article number, a figure, its name, and what it takes and gives: F-102, Shrink a photo, any photo → JPG or WebP. The hundreds are its kind, so the number says where a tool belongs, and it never changes once the tool is out. Six more for developers, from Format JSON to Hashes, wait behind a switch in Settings, off by default, so the everyday ones stay in front; switched on, they are a sixth group, the 900s.
| 100 Photo | Convert photos, Shrink a photo, Resize & crop, Remove location, Blur parts, Photos to PDF |
|---|---|
| 200 PDF | Arrange a PDF, Sign a PDF, PDF to photos |
| 300 Text | Count words, Clean up text, Compare texts |
| 400 From scratch | Make a QR code, Make a password |
| 500 Numbers & time | Dates & weeks, Percent & VAT, Convert units, Time zones, Split a bill, Timers |
| 900 Developer | Format JSON, Base64, Encode URLs, Timestamps, UUIDs, Hashes, behind the switch |
Search reads the number, the name, the description and the words people use for a tool, in English and German: “502” finds Percent & VAT, and so does “mwst”; “verkleinern” finds Shrink a photo. Every tool has its own address, such as /shrink-a-photo, and the server writes its title and description into the page, so a search result or a link in a chat names the tool, not just Fundus.
What you have comes first
The home starts from what you have. The groups are chips, Photo, PDF, Text, From scratch and Numbers & time, a strip on a phone and a column on a computer. Drop, paste or pick something anywhere on the page, and the tools that take it come first, each with its reason, read from the thing itself: its real type from its first bytes rather than its name, its size, its pixels, whether it knows where it was taken. A HEIC gets “It’s a HEIC: make it a JPG”, a photo over a megabyte “3.8 MB: make it smaller”. Pasted text is sorted by its shape the same way: a link, a number, a date, a Unix time, JSON or Base64. Pinned and recent tools sit on top.
A result doesn’t end the work. Under it, “Go on with the result” offers the tools that take it, with the file already in, so a shrunk photo goes on to Remove location or Photos to PDF without being saved first. The handover stays in memory, like everything a tool is given.
Nothing leaves the device
The promise is the point, and it is enforced, not only written down. No tool fetches anything, not even public data, so there is no currency converter; Time zones, built on the browser’s own zone data, took its place. The page’s Content Security Policy allows connections to its own origin only, connect-src 'self', which serves the app’s files and counts the visit. A unit test scans every tool, every library and the shell for fetch, XMLHttpRequest, WebSocket, EventSource, sendBeacon and remote imports, and every end-to-end test, a real browser with real files, fails on any request to another origin, on anything sent but the visit count, and on a visit count that carries more than a visit.
Files live in memory only: close the tab and they are gone. What stays on the device is what you chose, not what you worked on: each tool’s last options, the pinned and recent tools and the shared settings, in the browser’s storage, and a signature, if you ask Sign a PDF to keep it. Saving is the only way out, and only onto the device: on an iPhone through the share sheet (Save Image, Save to Files), elsewhere as a download, and from five files on as one ZIP. Safari opens the share sheet only straight from the tap that asked for it, so every result is ready before Save is tapped.
Photos and PDFs in the browser
Every iPhone photo is a HEIC. Safari decodes it itself; other browsers get libheif, compiled to WebAssembly, the first time a HEIC needs it: about 2 MB, under the LGPL, in a file of its own. Each library loads when its tool opens and then stays in the cache, so the tools work offline too. pdf.js reads and draws PDFs, with its fonts, character maps and image decoders served from Fundus’s own origin, since the policy allows nothing else; pdf-lib writes them.
Metadata is read and removed byte by byte, without decoding the picture. The EXIF block is found wherever the format keeps it, in a JPEG, PNG, WebP or HEIC, and the tags people care about come out of it: the place, the camera, the time. A JPEG, PNG or WebP loses them without being encoded again, so the picture stays the same bit for bit. Removing the location empties the GPS directory and keeps the rest; removing everything keeps only the orientation, so the photo still stands the right way up. A photo drawn anew on a canvas keeps nothing at all, so with Remove location when saving switched off, the original’s EXIF goes back into the new JPEG.
One setting per idea
Some choices belong to more than one tool: the photo format and quality, removing the location when saving, the page size, the units, the decimal mark, the first day of the week, the home time zone, how a saved file is named (IMG_4127-small.jpg). Each is one setting, read by every tool that has it and gathered in the Settings sheet with the tools that use it. Changed inside a tool, it changes for all of them, so a toast says so and offers the way back: “Every photo tool now saves WebP”, with Undo. The defaults come from the device: Letter paper in the US and Canada, imperial units and US weeks in the US, A4, metric and ISO weeks elsewhere, a decimal comma in German. Only what you changed is stored, so a setting nobody touched keeps following the device.
Part of the family
The page is Svelte 5, built with Vite, and a small server with no dependencies serves it, each tool’s title and description written in. The tokens and components come from Folio, the family’s shared library, drawn here as a parts index: one highlighter yellow for the choice, Schibsted Grotesk and Martian Mono. Fundus works in English and German, light and dark, installs to the home screen and opens offline; on Android and in desktop Chrome the installed app also takes files from the share sheet, and its service worker hands them to the page without sending them anywhere. The visit counter, Census, works without cookies and never sees what goes into a tool. Fundus links to no other app: it stands on its own.
Nach Nummern abgelegt
Fundus ist ein Bestand an Werkzeugen für jeden Tag, solchen, nach denen man sucht, wenn ein Foto zu groß zum Hochladen ist oder ein PDF eine Unterschrift braucht: zwanzig davon, für Fotos, PDFs, Text, Zahlen und Zeit. Jedes ist abgelegt wie ein Teil in einem Lager, mit Artikelnummer, Abbildung, Namen und dem, was es nimmt und gibt: F-102, „Foto verkleinern“, jedes Foto → JPG oder WebP. Die Hunderter sind seine Art, so sagt die Nummer, wohin ein Werkzeug gehört, und sie ändert sich nicht mehr, sobald es draußen ist. Sechs weitere für Entwickler, von „JSON formatieren“ bis „Hashes“, warten hinter einem Schalter in den Einstellungen, der aus ist, damit die alltäglichen vorne bleiben; eingeschaltet sind sie eine sechste Gruppe, die 900er.
| 100 Foto | Fotos umwandeln, Foto verkleinern, Größe & Zuschnitt, Standort entfernen, Stellen verpixeln, Fotos zu PDF |
|---|---|
| 200 PDF | PDF ordnen, PDF unterschreiben, PDF zu Fotos |
| 300 Text | Wörter zählen, Text aufräumen, Texte vergleichen |
| 400 Ohne Vorlage | QR-Code erstellen, Passwort erstellen |
| 500 Zahlen & Zeit | Tage & Wochen, Prozent & MwSt., Einheiten umrechnen, Zeitzonen, Rechnung teilen, Timer |
| 900 Entwickler | JSON formatieren, Base64, URLs kodieren, Zeitstempel, UUIDs, Hashes, hinter dem Schalter |
Die Suche liest die Nummer, den Namen, die Beschreibung und die Wörter, mit denen Leute nach einem Werkzeug fragen, auf Englisch und Deutsch: „502“ findet „Prozent & MwSt.“, „mwst“ auch; „verkleinern“ findet „Foto verkleinern“. Jedes Werkzeug hat seine eigene Adresse, etwa /shrink-a-photo, und der Server schreibt seinen Titel und seine Beschreibung in die Seite, so nennt ein Suchergebnis oder ein Link im Chat das Werkzeug, nicht nur Fundus.
Was man hat, kommt zuerst
Die Startseite geht von dem aus, was man hat. Die Gruppen sind Chips, Foto, PDF, Text, Ohne Vorlage und Zahlen & Zeit, auf dem Handy eine Leiste, am Rechner eine Spalte. Etwas irgendwo auf der Seite ablegen, einfügen oder auswählen, und die Werkzeuge, die es nehmen, kommen zuerst, jedes mit seinem Grund, gelesen aus der Sache selbst: ihr echter Typ aus den ersten Bytes statt aus dem Namen, ihre Größe, ihre Pixel, ob sie weiß, wo sie aufgenommen wurde. Ein HEIC bekommt „Ein HEIC: mach ein JPG daraus“, ein Foto über einem Megabyte „3,8 MB: mach es kleiner“. Eingefügter Text wird genauso nach seiner Form sortiert: ein Link, eine Zahl, ein Datum, eine Unix-Zeit, JSON oder Base64. Angeheftete und zuletzt benutzte Werkzeuge stehen oben.
Ein Ergebnis ist nicht das Ende. Darunter bietet „Mit dem Ergebnis weiter“ die Werkzeuge an, die es nehmen, mit der Datei schon darin, so geht ein verkleinertes Foto weiter zu „Standort entfernen“ oder „Fotos zu PDF“, ohne erst gespeichert zu werden. Die Übergabe bleibt im Speicher, wie alles, was ein Werkzeug bekommt.
Nichts verlässt das Gerät
Das Versprechen ist der Kern, und es wird durchgesetzt, nicht nur aufgeschrieben. Kein Werkzeug lädt irgendetwas, nicht einmal öffentliche Daten, deshalb gibt es keinen Währungsrechner; „Zeitzonen“, gebaut auf den Zonendaten des Browsers, hat seinen Platz. Die Content Security Policy der Seite erlaubt Verbindungen nur zum eigenen Ursprung, connect-src 'self', der die Dateien der App liefert und den Besuch zählt. Ein Unit-Test durchsucht jedes Werkzeug, jede Bibliothek und die Hülle nach fetch, XMLHttpRequest, WebSocket, EventSource, sendBeacon und Imports von außen, und jeder End-to-End-Test, ein echter Browser mit echten Dateien, schlägt fehl bei jeder Anfrage an einen anderen Ursprung, bei allem, was außer dem Besuchszähler gesendet wird, und bei einem Besuchszähler, der mehr trägt als einen Besuch.
Dateien leben nur im Speicher: Tab zu, und sie sind weg. Auf dem Gerät bleibt, was man gewählt hat, nicht, woran man gearbeitet hat: die letzten Optionen jedes Werkzeugs, die angehefteten und zuletzt benutzten Werkzeuge und die gemeinsamen Einstellungen, im Speicher des Browsers, und eine Unterschrift, wenn man sie in „PDF unterschreiben“ behalten lässt. Speichern ist der einzige Weg hinaus, und nur auf das Gerät: auf dem iPhone über das Teilen-Menü („Bild sichern“, „In Dateien sichern“), sonst als Download, und ab fünf Dateien als ein ZIP. Safari öffnet das Teilen-Menü nur direkt aus dem Tippen, das danach gefragt hat, deshalb ist jedes Ergebnis fertig, bevor man auf Speichern tippt.
Fotos und PDFs im Browser
Jedes iPhone-Foto ist ein HEIC. Safari dekodiert es selbst; andere Browser bekommen libheif, kompiliert zu WebAssembly, sobald ein HEIC es zum ersten Mal braucht: etwa 2 MB, unter der LGPL, in einer eigenen Datei. Jede Bibliothek lädt, wenn ihr Werkzeug aufgeht, und bleibt dann im Cache, so arbeiten die Werkzeuge auch offline. pdf.js liest und zeichnet PDFs, mit seinen Schriften, Zeichentabellen und Bilddecodern vom eigenen Ursprung von Fundus, weil die Policy nichts anderes erlaubt; pdf-lib schreibt sie.
Metadaten werden Byte für Byte gelesen und entfernt, ohne das Bild zu dekodieren. Der EXIF-Block wird gefunden, wo das Format ihn ablegt, in einem JPEG, PNG, WebP oder HEIC, und heraus kommen die Angaben, die Leute interessieren: der Ort, die Kamera, die Zeit. Ein JPEG, PNG oder WebP verliert sie, ohne neu kodiert zu werden, so bleibt das Bild Bit für Bit dasselbe. Den Standort zu entfernen leert das GPS-Verzeichnis und lässt den Rest; alles zu entfernen behält nur die Ausrichtung, damit das Foto weiter richtig herum steht. Ein Foto, das auf einem Canvas neu gezeichnet wird, behält gar nichts, deshalb kommt bei ausgeschaltetem „Standort beim Speichern entfernen“ das EXIF des Originals zurück ins neue JPEG.
Eine Einstellung pro Idee
Manche Entscheidungen gehören zu mehr als einem Werkzeug: Fotoformat und Qualität, den Standort beim Speichern entfernen, die Seitengröße, die Einheiten, das Dezimalzeichen, der erste Tag der Woche, die eigene Zeitzone, wie eine gespeicherte Datei heißt (IMG_4127-small.jpg). Jede ist eine Einstellung, gelesen von jedem Werkzeug, das sie hat, und in den Einstellungen gesammelt mit den Werkzeugen, die sie nutzen. In einem Werkzeug geändert, ändert sie sich für alle, deshalb sagt ein Hinweis das und bietet den Weg zurück: „Jedes Foto-Werkzeug speichert jetzt WebP“, mit „Zurück“. Die Voreinstellungen kommen vom Gerät: Letter-Papier in den USA und Kanada, imperiale Einheiten und US-Wochen in den USA, sonst A4, metrisch und ISO-Wochen, auf Deutsch ein Dezimalkomma. Gespeichert wird nur, was man geändert hat, so folgt eine Einstellung, die niemand angefasst hat, weiter dem Gerät.
Teil der Familie
Die Seite ist Svelte 5, gebaut mit Vite, und ein kleiner Server ohne Abhängigkeiten liefert sie aus, mit dem Titel und der Beschreibung jedes Werkzeugs darin. Tokens und Komponenten kommen aus Folio, der gemeinsamen Bibliothek der Familie, hier als Teileverzeichnis gezeichnet: ein Textmarker-Gelb für die Wahl, Schibsted Grotesk und Martian Mono. Fundus gibt es auf Englisch und Deutsch, hell und dunkel, es lässt sich auf den Home-Bildschirm legen und öffnet offline; auf Android und in Chrome am Rechner nimmt die installierte App auch Dateien aus dem Teilen-Menü an, und ihr Service Worker reicht sie an die Seite weiter, ohne sie irgendwohin zu schicken. Der Besuchszähler Census kommt ohne Cookies aus und sieht nie, was in ein Werkzeug geht. Fundus verlinkt auf keine andere App: Es steht für sich.