Architecture
Architecture
Purpose: describe the current stable technical map of the system.
Instructions:
- Document the system as it currently exists in stable form.
- Focus on major components, boundaries, interfaces, data flow, storage, external dependencies, and invariants.
- Update this file when implemented changes alter the stable technical shape of the system.
- Keep this file descriptive of current reality, not speculative.
- Do not use this file as a task log, scratchpad, or decision diary.
- Additional documents may be created when describing the details of major components. For example, the documentation for an API may be linked to an OpenAPI specification at
docs/api.yaml.
System Overview
Hermeticus is a static Jekyll site deployed on GitHub Pages at https://hermeticus.org. Most pages are fully static, but the /books/ page now depends on a separate Cloudflare Worker to read live book data from Square and create hosted checkout sessions. The site itself never stores Square secrets and never handles payment card entry.
Major Components and Boundaries
- GitHub Pages Jekyll site
Stores page content, layouts, styles, and browser-side catalog code. It renders the page shell for
/books/, loadsassets/js/main.js, and points that code at the deployed worker URL through_config.yml. - Cloudflare Worker
Lives in
integrations/square-catalog-worker/. It exposes:GET /catalogfor public catalog readsPOST /checkoutfor server-validated cart checkout creation The worker is the only component that talks to Square APIs.
- Square Catalog API
Source of item, category, image, variation, and seller-visible custom-attribute data. A number custom attribute named
Shipping weight (lb)bridges product weights into the Worker because Square does not expose its native Dashboard shipping-weight field through this API. - Square Inventory API Source of the current stock count for each published book at one configured Square location.
- Square Checkout API Creates Square-hosted payment links for validated multi-item carts.
Interfaces and Data Flow
- A visitor opens
/books/onhermeticus.org. - The static page shell from
pages/books.mdand_includes/square-catalog.htmlloads. assets/js/main.jsreadssquare_catalog_api_basefrom_config.yml, restores any previously saved cart lines from browserlocalStorage, and requestsGET <worker>/catalog.- The worker checks Cloudflare edge cache.
- On a cache miss, the worker:
- paginates through Square
ListCatalogforITEM,CATEGORY,IMAGE, andCUSTOM_ATTRIBUTE_DEFINITION - extracts items that are publishable for v1
- retrieves inventory counts for candidate variation IDs at
SQUARE_LOCATION_ID - returns a compact JSON array with short keys
- caches that response at Cloudflare
- paginates through Square
- The browser renders cards with category, image links, Square description content, price, stock count, browse controls, and add-to-cart controls.
- Client-side search, category filtering, and sorting run entirely against the already loaded catalog array without further network requests.
- The browser persists cart lines in
localStorage, reconciles them against the freshly loaded catalog on page load, and silently drops lines that are no longer valid. - When the buyer checks out,
assets/js/main.jssendsPOST <worker>/checkoutwith variation IDs and requested quantities. - The worker bypasses the cached public payload, rebuilds current live availability from Square, validates the cart, calculates shipping from the trusted quantities and weights using
shipping-rates.json, and creates a Square-hosted payment link with required address collection. - The browser redirects the buyer to Square’s checkout page. Square stores the paid buyer’s address in a
SHIPMENTfulfillment. On a?checkout=successreturn, the client clears the saved cart and shows a payment-complete message. - The shop ships the books and manually completes the paid fulfillment in Square Orders Manager.
The public catalog payload uses these keys:
iitem IDvvariation IDnnamepprice in minor unitsddescription. This contains Squaredescription_htmlwhen available, otherwise Square plaintext description data.ccategory namemimage URL listwshipping weight in pounds, ornullwhen no valid custom weight is specifiedqquantity available
The checkout payload returns { "u": "<square-checkout-url>" } on success.
Storage and External Dependencies
- No database is used by the site or worker.
- Catalog browse results are cached at Cloudflare edge with a short TTL.
- Shipping rules are bundled from
integrations/square-catalog-worker/shipping-rates.json; no rate environment variable or database is used. - The
/books/page stores cart state in browserlocalStorageunder a repo-owned key. This storage is client-side only and is treated as disposable convenience state, not a source of truth. - Secrets are stored only in Cloudflare Worker secrets:
SQUARE_ACCESS_TOKEN
- Non-secret worker configuration currently includes:
ALLOWED_ORIGINSSQUARE_ENVSQUARE_LOCATION_IDCATALOG_TTL_SECONDSSQUARE_VERSION
- Site-side worker location is configured in
_config.ymlthroughsquare_catalog_api_base. - External runtime dependencies:
- GitHub Pages / Jekyll
- Cloudflare Workers
- Square Catalog, Inventory, and Checkout APIs
Invariants
- The public Git repository contains no Square or Cloudflare secrets.
- Payment card entry never happens on
hermeticus.org; buyers complete payment on Square-hosted checkout. - Customer shipping addresses remain in Square and are not stored by Hermeticus.
- Shipping configuration must pass structural and currency validation when the Worker module loads.
- Missing, negative, or malformed catalog weights become
nulland use per-item shipping; weights from 0 through 0.1 lb are excluded from shipping. - Null-weight-only carts use the configured quantity table. Weighted-only carts use the rounded-up per-pound result with its free and minimum thresholds. Mixed carts use the higher of the weight result and the quantity-table result for all non-free items.
- The current quantity table charges $5 for one qualifying item, adds $1 per item through $28 for 24, and charges $30 for 25 or more. Weight pricing is $2 per pound, calculated amounts below $1 are free, and amounts from $1 through $5 use a $5 minimum.
- Square collects any shipping country and no custom confirmation field is used. The shop cancels and refunds non-US orders during fulfillment review.
- Only items with exactly one sellable variation and positive tracked inventory at the configured Square location are published on
/books/. - Items with zero inventory or archived state disappear from the public catalog after cache refresh.
GET /catalogis cacheable;POST /checkoutmust validate against fresh Square data before creating a checkout link.- Browser code must sanitize Square description HTML before rendering it. Other catalog fields are rendered as text.
- Browser-stored cart lines must be reconciled against the latest live catalog payload before rendering or checkout.