Easy-to-manage touch screens
Free, open-source touch screens. Guided USB setup, a drag-and-drop editor and local control. Made for Home Assistant.
Understand German official letters in plain English. Your letter never leaves your device.
Translation pending
LifestyleHTML · JavaScriptGitHub @adityashukla55OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Briefly Description
Translation pending
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
German letters, explained. Take a photo of an official German letter and understand it in plain English: who sent it, what they want, the deadline, the amount, and what to do next.
Try it: brieflyapp.pages.dev — no sign-up, nothing to install.
Everything runs in your browser. The letter is never uploaded — not to a server, not to an AI company. It works offline and can be installed like an app.Read the full README ↗Official letters, explained. Take a photo of an official letter from Germany, Austria, Switzerland, France, Spain, Portugal, Italy, the Netherlands, Belgium, Poland, Sweden, Denmark, the United Kingdom, Ireland, the United States or Canada and understand it in plain English: who sent it, what they want, the deadline, the amount, and what to do next.
Try it: brieflyapp.pages.dev — no sign-up, nothing to install.
Everything runs in your browser. The letter is never uploaded — not to a server, not to an AI company. It works offline and can be installed like an app.
| No server sees your letter | A static site. The only backend is a tiny feedback function that receives what a visitor types into “Report a problem” — never a letter. |
| Locked down | The Content Security Policy only allows connections to the site itself (connect-src 'self'), so the page cannot send your letter anywhere. |
| Saved only if you choose | Nothing is saved unless you press Keep this letter. Kept letters are encrypted with your password (AES-256-GCM, key from PBKDF2-SHA-256 with 600,000 rounds and a random salt) and stay in the browser’s IndexedDB on this device. The password and the key are never stored. |
| Offline | A service worker keeps the app, the text reader and the translator on the device after first use. |
photo / PDF ──► text reader (Tesseract, WebAssembly) ──► country rules ──► dates, money, steps, replies
pdf.js for text PDFs │
└──► translator (Bergamot, WebAssembly) ──► English
web/src/languages/) knows dates, deadline phrases, amounts and reply letters. Each country (web/src/countries/) knows its offices, letter types, legal delivery rules, office words and example letters. The engine is web/src/analyze.js. Rules are predictable and testable, which matters when the result is a legal deadline.web/src/redact.js groups the words into lines and blocks by their position, so a second column next to the address stays apart, and then finds what to hide with rules: the address block (a title like “Herrn” or “Mr”, or a name over a street and a postcode line in the format of each country), names after greetings, IBANs checked with their checksum, the country’s own reference number labels, ID formats like the Swiss AHV number or the Italian codice fiscale, birth dates, phone numbers and emails. A name found once is hidden on every page. The black boxes are drawn into the pixels of a canvas and the pages are saved from that canvas, so the hidden text is really gone and no photo data (like location) is kept.Showing “To pay: €58” on a bank statement is worse than showing nothing. So Briefly only says To pay when the letter itself asks for money: a sentence like “Bitte überweisen Sie … bis …”, “Please pay by …” or a label like “Montant à payer”, in each of the 10 languages (web/src/requests.js, asks in web/src/languages/). It shows that sentence next to the amount. Letters that say “you don’t need to do anything” or that the money is taken by direct debit never get a “To pay”.
This is measured on 22 made-up documents with known answers (test/fixtures/documents.js): tax bills and refunds, reminders, fines, bank statements, payslips, direct-debit bills, a rent increase, an appointment, a school letter and a job offer, in 7 languages.
| “To pay” right | Deadline right | Wrong “To pay” shown | Time per letter | |
|---|---|---|---|---|
| Earlier rules | 15 / 22 | 20 / 22 | 7 | instant |
| On-device AI: Qwen3.5 0.8B picking from the amounts and dates Briefly found (Transformers.js, WebGPU) | 11 / 22 | 16 / 22 | 11 | ~13 s, 450 MB download |
| On-device AI: LFM2.5 350M answering freely | 14 / 22 | 11 / 22 | 5 | ~9 s, 280 MB download |
| On-device AI: Cactus Needle 3 filling a fixed form (grammar-constrained JSON) | 10 / 22 | 13 / 22 | 5 | ~6 s, 29 MB download |
| Current rules | 22 / 22 | 22 / 22 | 0 | instant |
The current rules were improved with these same documents, so 22 / 22 is the best case: new kinds of documents will show new gaps, and each one becomes a new test document. Small language models that fit in a browser did worse than the rules at deciding what someone must pay, so Briefly uses AI only where it is strong — finding names to hide and translating — and keeps the test documents to check every change.
scripts/pages.mjs generates static, search-friendly pages from the same country files the app uses, so they always match:
sitemap.xml, robots.txt, structured data (breadcrumbs, FAQ, web app)After changing a country or language file, run npm run pages and commit the result. It also rebuilds web/src/countries/meta.js, the small country list the app loads first (each full country file is loaded only when needed). A test fails if anything is out of date.
You need Node.js 20 or newer.
npm install
npm run dev
Then open http://localhost:8150. npm install also copies the libraries into web/vendor and downloads the translation models (checked with SHA-256).
Run the tests:
npm test
With Git (recommended): connect the GitHub repository to a Cloudflare Pages project (Workers & Pages → Create → “Looking to deploy Pages? Get started”, or Settings → Build → Connect on an existing project) and use these build settings. Every push to main then deploys by itself, up to 20,000 files, including the feedback function in functions/:
| Setting | Value |
|---|---|
| Build command | npm run vendor |
| Build output directory | web |
| Root directory | (empty) |
| Environment variable | NODE_VERSION = 22 |
Uploading the web folder by hand in the dashboard is limited to 1,000 files and can’t run the feedback function, so use Git or Wrangler instead.
From your computer:
npx wrangler pages deploy web --project-name brieflyapp
Security headers come from web/_headers.
Every page has a Report a problem button. Under a result there is also a Report it link, which adds what Briefly found (kind of letter, office, country), never the letter itself. The form posts to functions/api/feedback.js, a Cloudflare Pages Function on the same site, so the page’s lock (connect-src 'self') stays as it is. The function emails the report to you through Resend. Your address is kept as a secret in Cloudflare and never appears on the site.
Set it up once:
RESEND_API_KEY = the key from step 2FEEDBACK_EMAIL = the email you used for ResendSpam protection: a hidden field that only bots fill in, a minimum time before sending, size limits, and — once you add a KV namespace — at most 5 reports per sender per hour and 50 per day in total. To turn the limit on: in Cloudflare go to Storage & Databases → KV → Create (any name, for example briefly-feedback), then in the brieflyapp project open Settings → Bindings → Add → KV namespace, name the binding FEEDBACK_LIMITS, pick the namespace, save and deploy again. Only a hashed IP address is stored, for about an hour. When you run it locally without RESEND_API_KEY, reports are printed in the terminal instead of being sent.
Works in the latest Chrome, Edge, Firefox and Safari on phones and computers. Tested with Chrome 155 and WebKit 18 (the engine inside Safari) using photos, normal PDFs, scanned PDFs and the translators.
If something goes wrong, Briefly shows a plain explanation and what to try next. Technical details are hidden under “Technical details” for bug reports.
Tesseract.js (Apache-2.0), pdf.js (Apache-2.0), Bergamot translator and models (MPL-2.0). Example letters are made up.
Briefly is free and has no ads. If it helped you, you can buy me a coffee.
MIT
web/src/vault.js encrypts with the browser’s Web Crypto, web/src/folder.js stores the encrypted letters in IndexedDB, and web/src/letters.js is the screen. The key lives only in memory while the folder is open. The tests run the same code in Node with a small in-memory stand-in for IndexedDB.