A plain-language history of how Posku has grown since launch on May 21, 2026. Newest week at the top — scroll down to read back through the project diary.
The week the presold path came together. When a Wayfair load matches a standing deal (its location + load type), the SKU is created inactive, the invoice draft defaults to the agreed customer at their negotiated price, and the salesrep auto-fills to that customer's account manager. Perigold became a real load type, the pricing matrix became editable in Settings, and load types are now read purely from the email — nothing is forced.
A new rules table maps location + load type to a customer and a price. When a matching load is invoiced, that customer is pre-filled, the line is priced at the deal, and the pushed SKU is created inactive (it's presold, not for open sale). The current Wayfair list (Aberdeen / Romeoville / Jacksonville / Perris across LQ, Salvage, Aged, HDO, QC) ships loaded and editable.
A location + type can list several customers. The invoice draft defaults to the first, shows the others in a "Deal customer" dropdown, and keeps the free customer search for anyone not on the list. Switching customer reprices every line to that customer's deal automatically.
Each deal carries its own price — either a percent of retail or a flat whole-load $ (Salvage). The invoice line uses the deal price when one exists, otherwise it falls back to the SKU's listed price.
Customer search now returns the account manager (sales_rep_id from the warehouse customers_flat table), and picking a customer sets the invoice salesrep to their AM — no more typing it in.
Perigold (code PG, 12.5% of retail) is now a real type with its own condition trait, product name ("Liquidation Returns – Larger Items"), and detection. It's recognized straight from the facility name in the email, and an explicit Perigold mention wins over any other type guess.
The Wayfair recovery-rate matrix (our sell as a % of retail, by location × type, plus the per-type default and the flat salvage $) is now a grid you can edit and save in Settings — no redeploy to change a rate.
Removed the rule that forced certain locations to a fixed type (City of Industry / Portland → HDO) regardless of the email. The type is now parsed purely from the message text; if it isn't stated, the load is flagged for review instead of guessed.
Sam's loads whose club ships via a Direct method (Direct Truckload / Direct LTL) are now created inactive (active=0), so they aren't listed for open sale until reviewed.
Wayfair manifests arrive as a mix — some locations send CSV, others real .xlsx. Verified the server-side unzip-and-parse path handles xlsx end-to-end (shared strings, inline strings, numbers), so both formats attach cleanly. Corrected stale notes that claimed xlsx still needed a parser.
The big feature: Posku can now bill customers for presold loads. After a SKU is pushed, you select one or more loads, the app pre-fills a customer from a rule or lets you type-ahead one from the warehouse, and the invoice goes to the ERP via the same env-aware proxy. Plus a stack of smaller polish items.
Selected pushed SKUs become draft invoices, grouped automatically by customer. Each draft is fully editable — header dropdowns, line qty/price, shipping cost, tax rate, notes — and pushes to POST /api/orders via the existing env-aware proxy. Successful pushes trigger the gamification HUD with a "+N invoiced" floater.
Each pushed load has a per-row checkbox (default checked). Checked → that load gets its own invoice. Unchecked → it clusters with other un-unique loads going to the same customer. The header shows the predicted draft count live as you toggle, so you know exactly how many cards you'll get before clicking Generate.
Type 2+ characters of an email or name → results dropdown with email, name, company, customer id. Matches ranked by exact email > prefix > contains > name > company. Picking auto-fills the billing + shipping address blocks. Recent picks are cached as one-tap chips. Temporary bridge over BigQuery customers_flat until the ERP team exposes a REST endpoint.
Sam's rules editor gained a "Default invoice customer per location" table. Wayfair's gained "per location + type". Fill in a row, save → next time you generate an invoice draft from a matching load, the customer field is pre-filled.
Successfully pushed loads now show a three-segment status strip — [ SKU ✓ | PO ✓ | INV — ] — so a glance tells you exactly how far each load has progressed through the pipeline. Icons: ✓ done · … in flight · ✗ failed · — not started.
Detected loads, PO drafts, and Invoice drafts each have a chevron in their header — click to collapse or expand independently. The action buttons in each header stay clickable; only the title triggers the toggle.
The picker used to swallow every failure and show "no matches" no matter what. Now a failed lookup shows the actual reason inline — auth, IAM, network, whatever — so it takes seconds to tell "no customers matched" apart from "needs IAM grant" apart from "Pages function not deployed yet".
A huge debug push. We learned that the ERP was silently dropping several fields because we were sending the wrong key names — and we fixed every one of them. Drive fetches got smarter, the sidebar got a collapse toggle and zoom buttons, and the diagnostic page can now reveal exactly why an inbox fetch missed an attachment.
The ERP was accepting our pushes with HTTP 201 but quietly ignoring several keys because they were named wrong. Corrected: store_id → store, qty → unit_qty, price_per_unit → unit_price, packing now takes the real trait id, productType matches the dropdowns id, and 56 (Load Center) moved out of categories into the new groups array. PRODUCTS_API.md in the repo root captures all of this for future-us.
When fetching ~30 emails, Cloudflare Workers' hard 50-subrequest cap was silently killing about 20 of the CSV downloads. Split the attachment fetch into a separate endpoint and now each request stays well under the cap. All manifests come through.
Each Drive-fetched manifest now shows whether its SKU is already in the detected-loads table (so you can tell if email + Drive view the same load) and whether the SKU already exists in the ERP database (so duplicates don't get pushed).
For Drive manifest filenames the parser couldn't decode, you can now type a SKU in line. It's validated against the ERP — only SKUs that already exist are accepted, so you can't accidentally create a typo product.
The picker is labelled "Upload date" but was actually filtering on Drive's modified-time. Fixed to use createdTime so a freshly uploaded file shows up where you'd expect it.
Filenames like "Liquidation Load 50653 PerrisSmallParcel.xlsx" used to flag as unknown because the location parser only did exact matches. Now strips warehouse-type suffixes (SmallParcel, LargeParcel, SP, LP, DC) and falls back to a prefix match — so the warehouse variants all map to the right city code.
When "no manifests found" comes back empty, the message now tells you WHY: did Drive see no files at all (access issue), did it see files but the filter dropped them (filename mismatch), or did it see the right files but none matched a known tree (parser blind spot).
Some Sam's CSVs include a "Taxes and Linked Fees" line item that isn't real inventory. It's now filtered out of the sheet output, the load totals, and the SKU push.
Tiny toggle in the sidebar top-left shrinks the menu to a 64-pixel icon strip. Every button now visibly responds to taps with a press animation and a brief ring flash — no more "did that click register?" moments on async actions.
When tables got wide enough to scroll horizontally, the whole sidebar used to scroll off-screen with the content. It's now position-fixed to the left edge.
Three buttons in the sidebar — −, percentage, + — zoom the whole page in 10 steps from 60% to 200%. Persists across reloads. Ctrl/Cmd + and Cmd + 0 also work.
If a load's SKU already exists in the ERP, the row now shows a red "✗ duplicate in ERP" chip and no Push button. You can still Edit or remove it.
Card titles switched to Inter with a left-side gradient accent bar. The "Paste or drop email" card is now collapsible and starts collapsed each session, since most workflows use Inbox or Drive fetch instead.
The diagnostic now shows the last push request/response, a follow-up GET of the saved product, a known-good reference SKU for diffing, the ERP dropdown lists, AND the last inbox-fetch summary (which loads got their CSV auto-attached and why the others didn't).
The "Load Center" workflow showed up this week — Sam's CSV manifests auto-attach to their loads from inbox fetches, then bulk-append to a Google Sheet. Wayfair gained a Drive-based manifest browser. And the whole app got a UI redesign: dark navy sidebar, brand-colored titles per supplier, the Vicki Intelligence badge in the footer.
The CSV attached to each Sam's email gets parsed, the items get transformed into Load Center rows, and one click appends them to the shared Sheet. Per-load button or bulk send-all.
New panel that searches Google Drive for Wayfair manifest spreadsheets by upload date and derives a SKU per filename.
Button that rewrites the Load Center sheet's header row — fixes the recurring "columns got out of sync" issue.
Dark navy sidebar, cleaner main area, brand color tinting the page title per supplier (Wayfair purple, Sam's blue), favicon + Via Trading mark up top, Vicki Intelligence credit at the bottom.
The Gmail before:date filter is exclusive — the picker now shows inclusive labels and uses the right boundary so "today through today" actually returns today.
Posku grew teeth this week. Moved to Cloudflare Pages so the API key lives server-side instead of in browsers. Added the Sam's Club supplier with auto-assigned SEQ numbers fetched from the ERP. And the first version of Gmail inbox fetching — no more pasting emails by hand.
The browser no longer sees the ERP API key. All /api calls go through a Cloudflare Pages Function that injects the key server-side. Same-origin, so no CORS headaches.
Toggle in the sidebar lets you point the app at the test ERP (viatrading.biz) or the live one (ops.viatrading.com). Test SKUs get a "-test" suffix automatically.
Sam's joins Wayfair as a fully wired supplier. Tabs in the sidebar let you switch between them.
When a Sam's email is parsed, the app fetches the current max SKU per club from the ERP and assigns the next sequence number. No more typing them in.
Instead of copy-pasting emails, point the app at a Gmail label and date range — it pulls every matching message, runs the parsers, and pre-fills the loads table.
Per-supplier rules moved out of each browser's localStorage and into Cloudflare KV — a single shared source of truth across all users.
Dark navy interface ships as the default look.
More visibility per load: an expanded edit row that shows every field being pushed, an always-visible chip strip beneath each row, and a browser-local rules editor so power users can tweak Wayfair defaults without redeploying.
The edit row expanded to show every field that would be pushed. Below each load row, a compact chip strip shows the same info inline.
Tweak Wayfair-side defaults (supplier ID, store, condition mappings, etc.) directly in the browser. Saved locally so each user can override safely.
After a SKU is pushed, you can draft a matching PO and push it in the same flow. Every "need PO" field from the official spec is supported.
The real Wayfair flow landed: parse emails, preview SKUs, push them. Outlook .msg support, supplier-aware architecture (so other suppliers could be added later), and the first diagnostic page for debugging bad pushes.
Phase 1 of the real flow: parse Wayfair load emails, preview the generated SKU, push to the ERP. FOB state, packing, condition, and manifest traits all start landing on the product.
Native .msg parser reads the full subject + body from Outlook files. .eml decoder added too, plus better detection of binary file payloads.
Reorganized internally as a registry pattern so each supplier is its own isolated bundle of rules. This is what later made Sam's, Harbor Freight, and Amazon possible as tabs.
Full debug page for ERP push issues. Has gone through many shapes since — the current version shows the last push, what the server saved, and a known-good reference SKU for diffing.
Calls the ERP's dropdowns endpoint and validates that the trait IDs we send actually exist on that environment.
Failed or duplicate loads now show their error under the row instead of vanishing silently.
Posku started as a single-page tool: paste an email, see loads, push SKUs to the ERP. The first commits set up the dark theme, the drag-and-drop surface, and a configurable ERP target.
Replaced an earlier builder UI with one big paste / drag-and-drop area. You can paste an email body or drop a file (.eml, .txt) and it goes from there.
Dark theme bumped for contrast, and a light off-white theme added for users who want it.
You can point pushes at different ERP environments instead of hard-coding one.