Bookstore OS / Indie Retail Platform — State Survey
Snapshot 2026-05-01. Sources cited inline by note filename. Vault is at docs/.
Platform Architecture
- Two production codebases plus one peripheral service:
- Guild (
guild/): Payload CMS 3.x + Next.js (App Router) + PostgreSQL + Redis. Source of truth for membership, loyalty, tiers, XP, check-ins. Live at dungeon.club. ([guild.md], [membership-platform.md]) - Emporium (
emporium/): Medusa v2 backend + Next.js storefront forked from Solace + Payload CMS for editorial + MeiliSearch + PostgreSQL 16 + Redis 7. Replaces the legacy Square Online (Weebly) shop. Phase 1 shipped 2026-04-29 as a 4-PR Graphite stack; 5 follow-on PRs in flight. ([emporium.md], [journal/2026-04-29.md], [journal/2026-04-30.md], [journal/2026-05-01.md]) - Marty (
marty/): Python 3.13 + FastAPI + Claude API + Hardcover (GraphQL) + Sinch SMS + Discord.py + PostgreSQL + Redis. SMS/Discord book-recommendation chatbot. “Development slowed.” ([references/marty.md], [references/projects.md])
- Guild (
- Hosting is uniform on Railway. Cloudflare for DNS/CDN. R2 for media.
- Multi-tenancy in Guild is shipped, not aspirational. Uses
@payloadcms/plugin-multi-tenantwith Organization as the tenant boundary (e.g. “Script Wizards” org owns “Dungeon Books JC” shop). Branchfeat/multi-tenant-plugin, April 2026. Hierarchy: Organization → Shop → Member; Members are org-scoped, implicitly shop-scoped via tier. Per-tenant roles:adminvsstaff; globalsuper-adminvsuser. Domain routing (hostname → shop → org) is planned, not implemented. Per-shop Square location IDs and per-shop Stripe price IDs (under one Stripe account per org) are configured. Points never transfer between shops by design. ([plans/guild-multitenancy.md]) - Cross-merchant identity layer is designed, not built. A schema in [references/cross-merchant-identity.md] proposes
players,player_merchant_links,guilds,transactions,xp_events,achievementstables to unify Square’s per-location customer IDs under one player. This is the OutsideRPG network thesis — currently single-tenant in code. - Agent layer: Marty is the only deployed AI agent; it is not in the auth chain. Authentik is the planned SSO hub (see Integrations). PostHog is wired for product analytics. ([plans/discord-integration.md], [references/guild-posthog-setup.md])
- Deployment topology: All services on Railway. Self-hosted infra (Cosmos box) is planned for Authentik, HedgeDoc, Kavita, Calibre Web, Nextcloud, Affine — exposed via Cloudflare Tunnel under
*.dungeon.club. ([plans/discord-integration.md]) - Kiosk architecture: Currently a Next.js route group
(kiosk)/inside the Guild monolith. Decision logged to keep it in the monolith ([plans/guild-kiosk-architecture.md]). V2 design ([plans/guild-kiosk-v2.md]) decouples input/server/display via SSE + a PC/SC NFC daemon (Nodenfc-pcscon systemd) instead of HID-keyboard emulation. V2 is designed, partially implemented — triggered by an overnight Pi crash on 2026-04-09 that lost taps because the browser input field was unfocused.
Integrations
- Square POS (live, bidirectional state sync, no inventory sync yet for new stack):
- APIs in use across projects: Catalog, Inventory, Orders, Payments (Web Payments SDK), Locations, Customers, Customer Custom Attributes, Terminal API (planned). ([references/square-integration.md])
- Custom attributes pushed:
guild_tier,guild_points,guild_status,guild_member_id— namespaced to avoid clobbering staff notes. Triggered on Stripe webhook (tier change), Square webhook (purchase points), redemption. - Square Loyalty deliberately not used. Decision logged 2026-04-02 ([references/square-loyalty-decision.md]). Reasons: API is dashboard-only for program config, one program per seller (breaks multi-tenancy), tier model is spend-thresholds not paid subscriptions, redemption restricted to order discounts.
- Auto-discount at register is a known gap. Square does not expose an API to auto-create/update discounts; staff manually applies tier discount based on Square customer attribute. ([plans/auto-discounts.md])
- Sync architecture for Emporium ↔ Square: in-process Medusa module (no separate service); ISBN as shared key (Square
gtin↔ Medusa variantsku); Redis 30s TTL for sync-loop prevention; nightly reconciliation job; dead-lettersync_logtable. Not yet implemented in the new emporium stack — Phase 3 briefs were superseded 2026-04-29 byextended-catalog-and-preorders.mdwhich narrows the sync to in-stock SKUs only. ([references/rebuild-spec.md], [plans/extended-catalog-and-preorders.md])
- Edelweiss Omnibus (relationship live; integration is CSV + manual):
- Procurement brain. Carrie owns the workflow. Dave Lucey contact noted in [journal/2026-04-03.md].
- Plan ([plans/extended-catalog-and-preorders.md], approved by Carrie 2026-04-29): customers can pre-order titles not on shelf; orders captured in Medusa, batched into Omnibus by staff; shipment received into Square; Medusa orders flip to “ready to ship.” Ingestion = Omnibus CSV → Medusa import script (manual/weekly). API integration deferred to “later” (when Bookshop.org API ships or Omnibus exposes data).
- Medusa v2 (live):
- Phase 1 shipped 2026-04-29: Solace storefront ported,
[countryCode]segment removed (US-only), Stripe checkout end-to-end with 3DS verified (PR #5), MeiliSearch instant-search via server proxy at/api/search(PR #3, no master key in client), Strapi → Payload swap (PR #4) with custom Lexical → React renderer (~150 LOC). - Follow-on PRs #10–13: real Open Library cover ingestion, related-products on blog posts, native Next sitemap + branded 404, fully Payload-driven footer (
Footerglobal with address/hours/social/affiliate links). Established rule: anything staff would change without a deploy lives in Payload; Medusa is pure ecommerce. ([journal/2026-04-30.md]) - Pinned: React 19 forced via
pnpm.overrides; Tailwind kept at 3.4 because Medusa UI Preset is a v3 preset;meilisearch@0.57.0exports lowercaseMeilisearch. - Failure modes encountered: Solace seed script is non-idempotent (region creation collides on re-run); new products silently invisible to storefront if landed on
Default Sales Channelinstead ofOnline Store; Open Library has near-zero coverage for indie RPGs / zines (Mörk Borg, Mausritter — structural gap, no ISBN). One-shot idempotent scripts underbackend/src/scripts/are the workaround pattern (add-product-thumbnails.ts).
- Phase 1 shipped 2026-04-29: Solace storefront ported,
- Payload CMS (live in both projects):
- Guild: Members, Tiers, Purchases, LoyaltyTransactions, CheckIns, Shops, Organizations, ActiveBuffs, Kiosks (9+ collections per [roadmap.md]).
- Emporium: Pages, BlogPosts, Homepage global, Footer global. Dual-validation pattern (schema-side + render-side
sanitizeUrlfor hrefs). Lexical → React renderer is hand-rolled. - Auth incident:
payload-authplugin was incompatible with Payload 3.80.0 admin panel (form-state server action re-rendered on every keystroke, resetting inputs). Reverted. Current architecture is dual auth: native Payload for admin/staff (Users), Better Auth standalone for members (Members). Discord OAuth via Better Auth shipped in PR #87. ([plans/payload-auth-next-session.md], [plans/discord-integration.md])
- Twenty CRM: Nothing in vault.
- MeiliSearch (live in Emporium): Product index with Medusa price enrichment at proxy time. 150ms debounce + AbortController per-keystroke cancel. Subscribers auto-index on product CRUD. ([journal/2026-04-29.md], [references/rebuild-spec.md])
- Hi.Events (live SaaS, custom integration):
- SaaS at app.hi.events. Auth via JWT (no long-lived API keys; refresh ~7 days). Endpoints used:
POST /auth/login,/auth/refresh,GET /organizers/{id}/events,/events/{id}/attendees,/events/{id}/check_in_stats. Pagination is Laravel-style. Webhook integration uses HMAC-signedcheckin.createdandorder.created; matched to Payload Member by email;hiEventsAttendeeIdpopulated on first link. Webhook testing via Tailscale funnel. ([references/hi-events-api.md], [references/hi-events-webhook-testing.md], [plans/guild-hi-events-integration.md])
- SaaS at app.hi.events. Auth via JWT (no long-lived API keys; refresh ~7 days). Endpoints used:
- Stripe (live): Subscriptions for tiers (Bronze 25, Gold 100). Webhook handler updates tier/status, then fans out to
syncMemberToSquare()and (planned)syncMemberToAuthentik(). 3DS verified 2026-04-29 in Emporium. - Authentik (planned, not deployed): Will be the OIDC provider for selfhosted apps (HedgeDoc as POC at
write.dungeon.club, then Kavita, Calibre Web, Nextcloud, Affine). Tier → group mapping (guild-silver,guild-gold,guild-mithril). Guild pushes tier directly via API; Discord is not in the auth chain. ([plans/discord-integration.md]) - Discord (live as login): Better Auth Discord OAuth (PR #87).
discordId/discordUsernameon Member. Marty bot exists for chat; a Phase 3 cosmetic role-sync via Marty is planned, optional. - Idempotency / sync patterns observed:
- Square webhook → unique constraint on
square_transaction_id([cross-merchant-identity.md]). - Hi.Events webhook → HMAC signature verification (env
HI_EVENTS_WEBHOOK_SECRET). - Sync-loop prevention: short-lived Redis key
(ISBN, ts)TTL 30s ([rebuild-spec.md]). - Check-in dedup: 4-hour window, dedup key varies by method (
member+shopfor nfc/phone/manual/purchase;member+qrCodeIdfor QR;member+externalEventIdfor events). ([references/guild-checkin-cooldowns.md]) - Stripe webhook → fire-and-forget downstream syncs with
console.warnon failure; nightly reconciliation for inventory drift > 2 units, auto-correct on 1-unit drift.
- Square webhook → unique constraint on
AI/Agent Layer
- Marty (Python/FastAPI). “Martinus Trismegistus” persona. Claude API for generation, Hardcover GraphQL for book metadata, Bookshop.org for affiliate links, Sinch for SMS, Discord.py for Discord. Status: SMS fully functional; Discord bot implemented, needs token for production. Stack matches the [plans/manapool-seller.md] microservice. Square-API in-chat purchase, analytics — not built. ([references/marty.md])
- PostHog (live in Guild): client init via
instrumentation-client.ts; server viaposthog-nodesingleton insrc/lib/posthog-server.ts;/ingestreverse proxy to dodge ad-blockers. 12 events instrumented includingsignup_submitted,login_succeeded,subscription_activated,purchase_points_earned,points_redeemed. Six dashboards/insights built (signup→sub funnel, subscription health, tier upgrade funnel, loyalty activity, DAU). PostHog project ID 370533. ([references/guild-posthog-setup.md]) - AI DB access pattern documented but not confirmed deployed: [references/ai-db-access.md] (2026-04-06) prescribes a
ai_readonlyPostgres role with 30sstatement_timeout, 5-conn limit, RLS for sensitive rows, MCP Postgres server for Claude. Whether currently provisioned: unclear from notes. - Cernel evaluation ([journal/2026-04-23.md]): Concluded that AI product-data ingestion is the wedge for GTIN-less long tail (indie RPGs, zines, small-press) — not trade books. Trade books are owned by ONIX/Ingram/Hardcover incumbents. Image-gen explicitly rejected as “worse-than-useless” because indie RPG/zine art is core identity and the community rejects AI art.
- Indie ingest tool: Phase 1 designed (supplier registry + manual entry + URL/PDF/ISBN ingest + Claude enrichment for system, tropes, safety tools, content warnings, shelf-talker copy + Medusa+Meili write-through). Designed, not built. New plan file
plans/indie-ingest-tool.md(renamed fromrpg-zine-ingest-tool.md) referenced in the journal but not yet present in vault. - Coding agent infra: Vault contains a CLAUDE.md instructing Claude Code to use Obsidian rather than its own auto-memory directory. PostHog wizard left an “agent skill folder.” No evals, no formal prompt library captured in vault.
- Eval approaches: Nothing in vault.
Multi-Tenancy Readiness
Guild’s data model is multi-tenant. The gap is everywhere downstream of the schema:
- Configuration-driven, today: organization, shop, kiosk API key, Square location ID, Stripe price IDs per tier, NFC card UIDs per member, Hi.Events organizer ID. ([plans/guild-multitenancy.md])
- Top 5 places Dungeon-specific assumptions are baked in (gleaned across notes):
- Tier definitions and benefits. Bronze/Silver/Gold/Mithril, 25/100, 1×/1.5×/2×/3× multipliers, 100 pts = $1, are presented as global product decisions in [membership-platform.md] rather than per-shop config. Per-shop tiers exist in the schema but the marketing/portal copy and the
iron/bronze/silver/gold/mithrilenum are hardcoded. - Brand/visual direction. “Cassette futurism + 80s sword & sorcery” for Guild and “Indie Publisher” for Emporium are baked into Tailwind preset (
preset/plugins/colors.js), font choices, and component copy. The 2026-04-30 footer PR established the rule that “shop voice” should live in Payload globals — but most copy is still hardcoded. - Domain routing. Each shop is supposed to have a
domainfield with Next.js middleware doing hostname→shop→org. Not implemented. Today everything resolves to dungeon.club / dungeonbooks.com. ([plans/guild-multitenancy.md]) - Email/notification templates. Resend module pattern from Agilo Fashion is the porting target; templates in [rebuild-spec.md] reference Dungeon Books address, hours, footer literally.
- NFC card format and kiosk hardware assumptions. WalletMate II in HID mode typing
0450CF01635713↵; NTAG215 cards;KIOSK_API_KEY+KIOSK_SHOP_IDenv per device. Lite Kiosk (phone-as-reader) is the partner-shop scaling pattern but not yet built ([plans/guild-kiosk-v2.md]).
- Tier definitions and benefits. Bronze/Silver/Gold/Mithril, 25/100, 1×/1.5×/2×/3× multipliers, 100 pts = $1, are presented as global product decisions in [membership-platform.md] rather than per-shop config. Per-shop tiers exist in the schema but the marketing/portal copy and the
- Onboarding a new org is documented but manual: create Org in admin, create Shop with Square location, create Tiers with Stripe price IDs, create User with
tenants: [{ tenant: orgId, roles: ['admin'], shop: shopId }]. ([plans/guild-multitenancy.md])
Observability & Ops
- Product analytics: PostHog (Guild). 12 instrumented events; 6 dashboards. ([references/guild-posthog-setup.md])
- Logs: Pino structured logging mentioned for Square sync ([references/square-integration.md]). Nightly reconciliation job emits structured logs.
- Traces / APM: Nothing in vault.
- Dashboards: PostHog only. Stripe dashboard for payment monitoring. No Grafana/internal dashboards in vault.
- Alerts: Nightly reconciliation alerts on inventory drift > 2 units (email/Slack — destination not specified). No on-call rotation, paging, or SLO docs.
- Runbooks: [references/hi-events-webhook-testing.md] is the only formal runbook. Tailscale funnel pattern recurs.
- Incidents handled:
- 2026-04-09 Pi overnight crash ([plans/guild-kiosk-v2.md]): WiFi didn’t autoreconnect, Tailscale didn’t autostart, browser input lost focus → all NFC taps dropped until staff intervention. Triggered the V2 decoupled-input architecture. Mitigations: NetworkManager headless,
systemctl enable tailscaled, Chromium kiosk auto-launch, NFC daemon as systemd service withRestart=always, hardware/systemdwatchdog under consideration. - payload-auth admin panel breakage (Payload 3.80.0): documented and reverted. ([plans/payload-auth-next-session.md])
- WSL Docker port-forwarding fight during MeiliSearch wiring: resolved by moving Meili call server-side. ([journal/2026-04-29.md])
- Dark Reader extension hydration mismatches in dev (false-positive bug attribution).
- 2026-04-09 Pi overnight crash ([plans/guild-kiosk-v2.md]): WiFi didn’t autoreconnect, Tailscale didn’t autostart, browser input lost focus → all NFC taps dropped until staff intervention. Triggered the V2 decoupled-input architecture. Mitigations: NetworkManager headless,
- Square webhook reliability is flagged as tier-dependent ([extended-catalog-and-preorders.md] open question), with polling fallback planned.
Operator Persona & UX
- Operator persona (Carrie + retail staff): not engineers, but tech-comfortable. Carrie corrects architecture mid-conversation (caught the Omnibus-already-does-batching error in extended-catalog plan). Staff is expected to:
- Use Square POS for walk-in sales and discount entry (manual tier discount lookup via
guild_tiercustom attribute on customer profile). - Use Payload admin to edit Footer, BlogPosts, Pages, Members, manually adjust points/tiers.
- Approve member↔Square linking requests (anti-abuse) per [plans/guild-onboarding-rethink.md].
- Plan Omnibus batches by scanning the “awaiting distributor” Medusa worklist.
- Tap NFC cards into Payload admin’s
nfcCardUidtext field for v1 card registration.
- Use Square POS for walk-in sales and discount entry (manual tier discount lookup via
- Day-to-day surfaces:
- NFC kiosk (Pi + WalletMate II + touchscreen at 115 Brunswick St): idle/welcome/duplicate/not-found states. Welcome screen shows character sheet — name, tier, class, XP bar with tick-up animation, level, points + dollar value. 5s auto-return.
- Member portal at dungeon.club ([plans/guild-portal-ui-implementation.md]): redesigned to RPG character sheet pattern — Character Sheet (
/dashboard), Adventure Log (/dashboard/activity), Quest Log (/dashboard/quests), Rewards (/dashboard/rewards), Guild Hall (/dashboard/tiers). Sidebar nav with shadcnsidebarprimitives. - Emporium storefront at dungeonbooks.com: shop, blog, staff picks (deferred), reading lists, events.
- SMS / Discord chatbot Marty ([references/marty.md]): persona-driven, lowercase casual style; book recs.
- Manapool seller microservice ([plans/manapool-seller.md]): personal MTG card sales — Gmail polling, TCGTracking labels, Discord webhook to
#orders. - Staff dashboard ([references/guild-staff-dashboard.md]): three-layer design (Glance / Conversation / Admin) — designed, partially built. Glance card on check-in surfaces tier, points-as-dollars, subscription status, active buff, Square customer link.
- Discord as community surface; Authentik will gate the selfhosted app suite (HedgeDoc/Kavita/CWA/Nextcloud/Affine) when deployed.
- POS gap is the kiosk’s reason for being. Square’s native register has no way to inject loyalty UI; the kiosk is the second-screen workaround. ([references/square-loyalty-decision.md])
Distribution & Community
- Jersey City canvassing plan ([plans/jc-canvassing-plan.md]): walk every event-hosting Square-using small business in JC. Target ≥3 of ~30 to pilot. Pitch is “real-world MMORPG with your shop as a quest hub.” Demo on phone, NFC card live tap. Known leads: Victory Point (warm), Sarap Shop (warm), Pixel Labs, Call Me Mia.
- Phil at Victory Point Cafe ([people/phil-victory-point.md] referenced; [plans/platform-pricing.md]): top pilot candidate. Software engineer, failed prior annual membership program. Pricing signal: would pay 500–1k/yr for allocation coordination alone, said $1k/yr is too low if value’s real (Bookmanager comp).
- Memory: project_phil-pilot-candidate, project_guild-traction (12 launch members, NJ pilot for 3 shops).
- Withfriends sunset (2026-04-23) ([journal/2026-04-23.md]): Carrie chose dungeon.club over Ko-fi migration. Withfriends being decommissioned within 2 days; existing paid terms honored. Public landing + tier cards + Stripe replacing invite-gating. Special migrations for Sean Buckley (20 with $5 credit) and Allan (100% off coupon removal, 26th-of-month anchor).
- Facebook group of Square bookstore owners: not mentioned in vault.
- Edelweiss / Omnibus relationship: Dave Lucey/Omnibus call 2026-04-03 ([journal/2026-04-03.md]). No formal partnership doc.
- Indie RPG / zine supply thesis ([journal/2026-04-23.md]): Faire structurally can’t serve indie RPG/zine; Exalted Funeral is a retailer not a distributor. Bookcon validated: suppliers split between Faire and direct wholesale. Dungeon Books positioned to be the supply layer between them. Phase 3 trigger = Guild pilot shops asking to source from us → regional East Coast wholesale.
- Bookstore-developer peers in references: Kunal Gupta (Withfriends → pivoting toward Guild’s model per memory), Leonard Scheidemantel, Maggie Tang (Loyalist, fine dining vertical, $10M raised), Jason at Diesel Books.
- Press shipped ([references/expansion-strategy.md]): Shelf Awareness, Patch.com, JCity Times, NewPages, NJ.com / Jersey Journal, IndieBound Featured Bookstore (2026-02-18).
- Talks given: None captured in vault.
- Blog posts: Emporium blog system shipped 2026-04-29; “first blog post” listed as a Phase 4 launch task. No prior posts captured.
Open Questions & Tech Debt
Explicit “figure out later” / “won’t scale past N” flags in vault:
- Domain routing for multi-tenant. Designed, not built. ([plans/guild-multitenancy.md])
- SSO across dungeonbooks.com ↔ dungeon.club. Open. ([references/ecosystem-architecture.md])
- Tier discount automation at Square POS. Manual today; “breaks at scale (~40+ members).” ([plans/auto-discounts.md])
- Free-tier vs paid-tier point conversion. Free members can earn but not convert to store credit; carrot logic. ([plans/guild-onboarding-rethink.md])
- Auth identity vs store identity decoupling. Open: do we self-serve Square link with verification, or always staff-approve? ([plans/guild-onboarding-rethink.md])
- SSE single-process limit. “Fine for current scale. If we move to multiple server instances later, swap the in-memory map for Redis pub/sub.” ([plans/guild-kiosk-v2.md])
- Sitemap pagination. Current
limit: 1000per collection. Add when any of {pages, posts, products, categories} crosses ~500. ([journal/2026-05-01.md]) - Vercel SSE long-lived connection limits. Open. ([plans/guild-kiosk-v2.md])
- Apple Wallet / Google Wallet pass provisioning. Designed; pipeline TBD. ([plans/guild-kiosk-v2.md])
- Hi.Events SaaS limitations. Auth requires storing login credentials and refreshing JWT every ~7 days; no long-lived API key. ([references/hi-events-api.md]) Self-hosting flagged as “future option” in [references/ecosystem-architecture.md].
- Square inventory webhook reliability depends on Square subscription tier; polling fallback planned. ([plans/extended-catalog-and-preorders.md])
- Pre-existing typecheck errors from Solace port were cleared in commit
4217469on 2026-05-01 — flag that “don’t merge a green PR on top of a red baseline.” - Indie RPG cover-image gap. Open Library has near-zero coverage for itch/Free League/etc. Plan: drop covers in
backend/seed-assets/covers/<handle>.jpgor upload via admin. ([journal/2026-04-30.md]) - Seed script non-idempotent. Region creation collides on re-run. Workaround: one-shot scripts under
backend/src/scripts/(template:add-product-thumbnails.ts). - E2E in CI deferred. Three explicit thresholds for adding it: pre-launch (1 happy-path checkout test), second contributor (5-test smoke), or a regression that escaped. ([journal/2026-04-29.md], [journal/2026-05-01.md])
- Catch-all
/[slug]/page.tsxfor arbitrary Payload Page slugs is unsafe-by-omission today (sitemap advertises slugs that 404). - Auth incident debt: payload-auth plugin removed; native Payload + Better Auth dual stack is the resolved-not-yet-stabilized architecture. ([plans/payload-auth-next-session.md])
- Contradictions in vault:
- [references/projects.md] still lists store stack as “Saleor 3.22 · Payload 3.x · Next.js · Stripe” — outdated. The 2026-03-12 platform pivot in [references/rebuild-spec.md] and live work in [emporium.md] are on Medusa v2.
projects.mdneeds a refresh. - [plans/membership-platform.md] non-goals say “Multi-location support… is a product concern for later,” but [plans/guild-multitenancy.md] (April 2026) shipped multi-tenant with org/shop/member. Non-goals doc is stale.
- [plans/membership-platform.md] presents tiers (Bronze/Silver/Gold/Mithril, fixed prices) as global; [plans/guild-multitenancy.md] places Tiers under Shop. Reconciliation unclear.
- [references/projects.md] lists
webshopas Drizzle ORM;webshopis being sunset. [journal/2026-04-23.md] says the Withfriends sunset, not webshop, was happening that week — different system. Worth confirming webshop’s actual sunset date.
- [references/projects.md] still lists store stack as “Saleor 3.22 · Payload 3.x · Next.js · Stripe” — outdated. The 2026-03-12 platform pivot in [references/rebuild-spec.md] and live work in [emporium.md] are on Medusa v2.
Business Model State
- Consumer-facing tiers: Bronze 25 / Gold 100/mo. Iron is the internal label for non-member Square customers (no Payload record). Welcome gift, store discounts (0/10/20/25%), event discounts (10/10/15/50%), free monthly ARC at Silver+, yearly tote at Silver+, private event annually at Mithril, etc. Loyalty multipliers 1×/1.5×/2×/3×. Points = 1/1 store credit. Points never expire (no dark patterns, no breakage by design). ([plans/membership-platform.md])
- B2B platform pricing for partner shops ([plans/platform-pricing.md], current recommendation):
- Small (<99/mo
- Medium (750K): $179/mo
- Large (299/mo
- Comp: Bookmanager ~2K/yr ongoing / 1% online transaction fee. Medium tier ($2,148/yr) is “right in that range.”
- Switch to variable pricing when Dungeon Books becomes the tier-2 distributor (margin on inventory replaces subscription).
- Napkin: 30 shops at 61.2k/yr (≈ one salary + infra); 100 shops = 1.14M.
- Customer pricing experiments in journal:
- 2026-04-23 Withfriends sunset: invite-gating removed; price drop from old 20 (Sean Buckley individually credited).
- Allan: 100% off coupon removed, billing cycle anchor reset to 26th, $10 charge on 26th.
- Phil’s pricing signal ([plans/platform-pricing.md]): would pay 500–1k/yr for allocation alone, $1k/yr “too low if value is real.”
- Customer conversations / SOWs:
- Wednesday call with Kunal Gupta 2026-04-01 — exit from WithFriends (CTO offer turned down per memory). [plans/wednesday-prep.md], [journal/2026-04-01.md].
- JC canvassing: known warm leads above.
- No formal SOWs / retainers in vault.
- Unit economics modeling: Napkin only. ~1,188/yr; comparable to Bookmanager.
- Memory items relevant: project_brian-buyout (Brian leaving Leica mid-May 2026 — buyout vs cofounder pending, retail + game producer background), project_guild-priority (Guild is Panat’s founder bet, chosen over WithFriends CTO), user_panat-context (E-2 visa cannot lead nonprofit; long-term: vertical integration for indie bookstore industry).
- Nonprofit / capital strategy ([references/expansion-strategy.md]): Lease ends July 2027 (16-month deadline). Dungeon Arts 501(c)(3) targeted Q2 2026 (Carrie leads). Funding landscape mapped: JCACTF (up to 17.5k program), Hudson County LAP, NJ State Council GOS/GPS (3-year operating), NJEDA A.R.T. (Phase II disbursed; Phase III TBD), NJ Cultural Trust. Most require 501(c)(3) status.
- Research lab framing ([plans/research-lab.md]): The platform work is positioned as the commercial application of network-coordination-dynamics research. “5 people with agents operate like 30.” Phase 0 is now (lab=1, Guild=first tool, bookstore=first dataset). Post-WithFriends-exit (late 2026) → 2–3 people. Mana/Jimmy Lee called out as potential aligned funder.
Five Clarifying Questions
- Scope of “platform”: Are you treating Marty (SMS/Discord chatbot), the Manapool seller microservice, and the planned RPG/zine ingest tool as part of the bookstore-OS surface area for the strategy conversation, or only Guild + Emporium? The vault treats them as adjacent but separately deployed.
- Tenant boundary intent: Multi-tenancy is shipped at the Org→Shop level, but tier definitions, tier copy, brand/visual direction, and most operator UX are still hardcoded as Dungeon Books. For the strategy conversation, should I be assuming the next pilot shop runs as another Org under your Stripe account (per [guild-multitenancy.md] onboarding steps) or as a fully separate deployment? The plan accommodates both but they imply very different roadmaps.
- Authentik / selfhosted-app suite is designed but not deployed. Is that POC live yet, or should I treat the entire OIDC tier-gating layer (HedgeDoc, Kavita, etc.) as “designed only” for the strategy conversation?
- Withfriends sunset and Guild PMF question ([journal/2026-04-23.md]) flagged Guild as “largely a novelty” pending data analysis to separate migration-failure from PMF-failure. Has that activity-data pull happened? It changes how to read the 12-member traction signal.
- The cross-merchant identity layer in [references/cross-merchant-identity.md] is the most architecturally consequential piece in the vault that hasn’t been built (player schema as primary entity, not loyalty record). Is that the next platform-tier build, or is it parked behind the indie-supplier ingest tool ([journal/2026-04-23.md] Phase 1) and continued Emporium launch work?