尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Briefly Description
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
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.檢視完整 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.