An inbound control tower for warehouses. DockFlow follows every inbound shipment from dock booking to client invoice:
- You book it into a dock door.
- It checks the documents against each other.
- It records what was actually counted at the dock, plus damage photos.
- It runs the demurrage and detention clocks on the container.
- It turns receipts, releases and services into monthly storage invoices.
Live demo: https://datawithdon.github.io/dockflow/ (open Settings → Data → Load demo data)
DockFlow is a fully static web app. There's no backend, no account and no tracking, and your data never leaves your browser. The one optional exception is AI document reading, which sends the document you choose to the Claude API using your own key.
- Exceptions feed, worst first:
- containers in demurrage or detention, or about to be
- empties not yet returned
- shipments past their ETA
- document mismatches
- shortages or damage with no claim
- late or missed trucks
- claims left unsubmitted
- Free-time board: every container on a running clock, sorted by days left, with the cost so far and the extra cost if it waits three more days.
- Today's dock appointments with their live status.
- One lane per door, in 30-minute rows, with a now-line and a utilisation bar for each door.
- Booking checks for:
- overlaps on the same door
- bookings outside the door's hours
- reefer loads at doors without a plug-in
- dangerous goods at doors not approved for them
- equipment the door isn't set up for
- Suggest free slots lists the doors and times that fit the load.
- Check-in → unloading → done, plus no-show and cancel. Trucks show as late after a grace period you set, and as missed once their slot has passed.
- Printable daily schedule.
- Four document slots: purchase order, packing list, commercial invoice and bill of lading.
- Three ways to get lines in:
- AI reading of a PDF or photo, with a review step before anything is saved
- CSV import, which recognises common column names (Item No, Qty, CTNS, Gross Weight, HTS Code…)
- manual entry
- Three-way match by SKU flags:
- missing lines and quantity differences, with a tolerance you set
- over-shipment
- HS codes that differ between the packing list and the invoice
- HS codes that are too short or don't exist in HS 2022
- B/L and packing list disagreeing on gross weight or package count
- a container or seal number that doesn't match the shipment
- a container number that fails its ISO 6346 check digit
- Count screen that works on a tablet: expected vs. received vs. damaged for each line, plus unexpected items.
- Seal check at arrival, pallets put away, receiver name.
- Photos taken with the device camera, downscaled and stored in the browser.
- Printable receiving / OS&D report with photos and signature lines.
- One-click claim that values shortages and damage at invoice (or PO) unit prices.
- Tariffs per shipping line with free days and tiered daily rates (e.g.
1:95, 5:165, 10:260). - Demurrage and detention as separate clocks, or merged into one combined clock.
- Days counted inclusively. The app shows each clock's last free day, days left, chargeable days and cost.
- A "what waiting costs" table for the next 7 days.
- A register of claims with open, submitted, settled and rejected states, the amounts claimed and recovered, and a printable notice of claim with photos.
- Rates per client:
- handling in and out, per pallet
- storage per pallet per day, with free days
- devanning per 20' and 40' container
- a monthly minimum
- Storage is counted from receipts and releases. A pallet is charged on the day it's received but not on the day it's released.
- Extra services (relabelling, shrink wrap…) logged against each shipment.
- Monthly draft invoices for each client. You can issue, print, mark paid or void them, and export to CSV.
- Carrier on-time arrival rate, with no-shows and average time at the door.
- Door utilisation over the last 14 days.
- D&D cost by shipping line.
- Receiving accuracy by supplier.
- Every chart has a table view.
ES modules need to be served over HTTP. Opening index.html as a file won't work.
python3 -m http.server 8000 --bind 127.0.0.1
# open http://127.0.0.1:8000Run the tests (Node 20+, nothing to install):
npm testDockFlow can read a PDF or a photo of a packing list, invoice, purchase order or bill of lading into line items.
- Get an API key from the Claude Console. Setting a spend limit on it is a good idea.
- Paste the key into Settings → AI.
- On a shipment's Documents tab, click Read PDF/photo (AI).
How it works:
- The browser calls
https://api.anthropic.com/v1/messagesdirectly, using structured outputs so the reply is JSON in a fixed schema. - The default model is Claude Opus 5.5. Sonnet 5.5 and Haiku 5.5 are cheaper options.
- Whatever the model returns is treated as untrusted data. Every field is type-checked and length-limited, and you check the extracted lines before they're saved.
- By default the key is held in
sessionStorageand forgotten when the tab closes. Remember on this device moves it tolocalStorage. Only use that on a computer you trust. - The key is never written to IndexedDB, backups or exports.
The header row needs an item column and a quantity column. All other columns are optional. Names are matched case-insensitively.
| Field | Accepted headers (examples) |
|---|---|
| SKU | sku, item no, part number, article, style |
| Description | description, product name, goods description |
| Quantity (units) | qty, quantity, units, pcs |
| Cartons | cartons, ctns, packages, cases |
| Gross weight (kg) | gross kg, gross weight, gw, weight |
| HS code | hs, hs code, hts, tariff code |
| Unit price | unit price, price, unit value |
Rows with no SKU or a non-numeric quantity are skipped and reported.
- All data lives in your browser's IndexedDB: doors, clients, tariffs, shipments, appointments, claims, invoices and photos. Use Settings → Data → Download backup to move it or keep a copy. Photos are optional in the backup.
- Data in IndexedDB is not encrypted. Anyone who can use your computer's browser profile can read it.
- Content-Security-Policy: only the app's own files can load, and the only network calls allowed are to
api.anthropic.com. There are no third-party scripts, fonts, analytics or service workers. - No markup injection: everything is displayed through
textContent, neverinnerHTML. That covers text from documents, CSVs, backups and AI output. - Backups and stored data are untrusted input. Every record is rebuilt from a fixed schema when you restore a backup and each time the app loads. Unknown keys (including
__proto__), wrong types and oversized values are dropped. Images must be base64 PNG, JPEG, WebP or GIF data URLs. - Clickjacking: the app refuses to run inside another site's frame. GitHub Pages can't send
frame-ancestorsheaders, so the app enforces this itself. - Fail-safe: if a screen ever fails to render, you get a link to Settings → Data instead of a blank page.
- Photos: they're re-encoded in the browser, which strips EXIF metadata, including GPS location.
- CSV exports: spreadsheet formulas are neutralised to block formula injection.
- AI reading: documents you send are processed by Anthropic under your API account's data policy. Documents read by AI are marked read by AI, check it until a person saves the lines.
- Shared origin: GitHub Pages serves every project site of one account from the same origin (
<user>.github.io). Those sites share storage, so any of them could read DockFlow's data and a remembered API key. Either keep that account free of untrusted pages, host DockFlow on its own domain or subdomain, or run it locally. - Settings → Data → Erase all data removes everything, including the saved API key.
index.html app shell + CSP
css/styles.css styles (light/dark, print layouts)
js/engine/ pure logic, unit-tested in Node
dates.js date arithmetic
container.js ISO 6346 check digit
freetime.js demurrage & detention clocks, tiered costs
schedule.js dock conflicts, live state, free slots, utilisation
match.js PO / packing list / invoice / B/L matching
receiving.js expected lines, OS&D
billing.js pallet-days and invoice drafts
exceptions.js the exceptions feed
analytics.js metrics
csv.js CSV parse/export
extract.js Claude request + response validation
sanitize.js schema rebuild for backups and stored data
js/views/ one file per screen
js/ai.js Claude API call
js/db.js IndexedDB storage
js/state.js app state, API key handling, backup/restore
js/sample.js demo data (fictional companies)
data/hs-codes.json WCO HS 2022 6-digit subheadings
tests/ node:test suites
- D&D is calculated in calendar days. Some lines exclude weekends or public holidays, so check your tariff.
- The Incoterm, customs and duty side of a shipment is out of scope here. See QuoteCraft and HS Code Finder.
- One browser means one dataset. DockFlow doesn't sync between users or devices.
MIT