GGP
Master ledger — every system, one page.
Owner: Will (mindfulcrumb@gmail.com) · Updated 2026-04-25 · Vault: ~/.claude/.env
9 live
1 built · not deployed
1 vendor
1 retired
Status board tap a row to jump to detail
Daily ops five systems · the employee operations stack
01 Clock App live
Employee clock-in/out, geofenced to two shop locations.
URL clock.gadgetgeekspro.com
Code /root/clock-app/index.html on Hetzner; APIs at /opt/kimai/public/*.php in kimai container.
Stack Vanilla JS + Kimai PHP APIs + MySQL.
Vault keys None on client. Server reads KIMAI_DB_PASSWORD from /Users/research/payroll-setup/.env.
Last touched 2026-04-23 (leave-balance UI added)
Issues / next Steady. Next: pay-stub PDF emailer; time-off request workflow.
Geofence radii 200 m around (32.229003, −110.876589) and (32.220943, −110.839048). Auto clock-out cron every 15 min closes any entry >12 h. Pay period 14 days, OT FLSA per-week >40 h at 1.5×, timezone America/Phoenix −07:00.
02 Timesheet (Kimai) live
Full timesheet admin UI — view, edit, export, audit time entries. Source of record for hours.
URL time.gadgetgeekspro.com/en/timesheet/
Code kimai container, /opt/kimai/
Stack Kimai 2 (PHP / Symfony)
Vault keys KIMAI_ADMIN_EMAIL, KIMAI_ADMIN_PASSWORD, KIMAI_DB_PASSWORD in /Users/research/payroll-setup/.env
Last touched 2026-03 (steady)
Issues / next Steady. Watch DB size; backup cadence already set in payroll-backups/.
03 Payroll Admin live
Pay-period summaries, payroll readiness, NACHA generation, tax liability view, employee onboarding status.
URL clock.gadgetgeekspro.com/admin.html
Code /root/clock-app/admin.html + APIs /opt/kimai/public/clock-admin-api.php, clock-generate-nacha.php, clock-leave-log.php, clock-leave-balance.php
Stack PHP + MySQL + ERPNext API. bcrypt + 24h session tokens. CORS locked to gadgetgeekspro.com.
Vault keys ERPNEXT_URL, ERPNEXT_API_KEY, ERPNEXT_API_SECRET. Static admin token ggp_admin_dashboard_2026 accepted only from 127.0.0.1 / ::1.
Last touched 2026-04-23 (leave system verified live)
Issues / next None. Next: MFA for admin, pay-stub PDF emailer, "Adjust Balance" UI on Leave card (currently API-only).
Federal 2026 brackets per IRS Rev Proc 2025-32 / OBBBA. AZ flat 2.5% with optional A-4 election (8 rates 0%–5.1%). SS 6.2% (cap $184,500), Medicare 1.45% (no cap). Employer FUTA 0.6% on first $7,000, AZ SUTA 2.0% on first $8,000, AZ Job Training 0.1% on first $7,000.
04 Onboarding live
New-hire flow — W-4 wizard, AZ A-4 election, direct deposit, address, emergency contact, e-sig + perjury cert.
URL onboard.gadgetgeekspro.com
Code /root/onboard-app/index.html + /opt/kimai/public/onboard/save.php
Stack Vanilla JS + PHP. Audit log at /data/onboarding/audit.log (IP + timestamp per change).
Vault keys ERPNEXT_URL, ERPNEXT_API_KEY, ERPNEXT_API_SECRET. Email alerts via RESEND_API_KEY, RESEND_FROM_EMAIL.
Last touched 2026-03-25 (server-side auth hardened)
Issues / next None. Next: mobile signature capture, document upload (proof of address, ID), annual W-4 refresh prompt.
PII storage: per-employee JSON at /data/onboarding/{employee_id}.json in the kimai container; directory chmod 750, owner www-data. Save endpoint uses merge logic — never overwrites.
05 ERPNext live
Backend of record — employees, salary structure, GL accounts, journal entries, leave ledger config.
URL erp.gadgetgeekspro.com
Code Compose at /Users/research/payroll-setup/; container payroll-setup-backend-1; bench at /home/frappe/frappe-bench/ inside.
Stack ERPNext + Frappe + MariaDB.
Vault keys ERPNEXT_URL, ERPNEXT_API_KEY, ERPNEXT_API_SECRET. Compose-only: DB_ROOT_PASSWORD, ADMIN_PASSWORD, TAXBANDITS_*.
Last touched 2026-04-23
Issues / next None. Next: evaluate move of ACH/tax filing to QuickBooks or Gusto (~$88/mo); keep this stack as employee-management layer.
Company Gadget geeks pro (abbr GGP). Salary Structures: Standard Hourly + Standard Salaried. GL accounts 2310/2320/2330/2340/2350/2360/2120/5120/5130. Leave: sick 1h per 30h worked (annual cap 24h), PTO 40h annual grant, both carry forward, 90-day waiting period; ledger at leave_ledger (append-only).
docker exec -w /home/frappe/frappe-bench payroll-setup-backend-1 \
bench --site erp.gadgetgeekspro.com execute <module.function>
Storefront & customer three systems
06 Refresh Theme live
Online Store 2.0 storefront for gadgetgeekspro.myshopify.com.
URL gadgetgeekspro.myshopify.com · admin
Code /Users/research/refresh-theme/
Stack Shopify Liquid (Dawn 15.2.0 fork). Theme ID 157805740283. Breakpoints 750/990 px.
Vault keys SHOPIFY_STORE, SHOPIFY_ACCESS_TOKEN (24h refresh), SHOPIFY_CLIENT_ID, SHOPIFY_CLIENT_SECRET. Plus DEVICEPLUG_STORE, DEVICEPLUG_ACCESS_TOKEN.
Last touched 2026-03-16
Issues / next None. Next: continue CWV polish (LCP <2.5 s, CLS <0.1, INP <200 ms, Lighthouse ≥90).
API 2026-01 GraphQL Admin only. Bulk ops via bulkOperationRunQuery for >250 records. Theme push discipline: theme dev MUST run, strip JSON comments after pull, full-theme push always.
07 Transactional Emails built · not deployed
Order confirmations, shipping, refunds, review requests via Shopify webhooks → Resend. Code complete, never deployed — verified 2026-04-25 (no process on port 4000, no launchd, no autostart). Render deploy chosen.
URL Not deployed. After Render: *.onrender.com. Shopify webhook URLs need updating once live.
Code /Users/research/gadget-geeks-emails/ — Procfile + nixpacks.toml staged.
Stack Express + React Email + Resend SDK. HMAC-SHA256 webhook sig verification present.
Vault keys RESEND_API_KEY, RESEND_DOMAIN, RESEND_FROM_EMAIL, RESEND_FROM_NAME, SHOPIFY_ACCESS_TOKEN, SHOPIFY_WEBHOOK_SECRET.
Last touched 2026-03-09 (1 commit total)
Pre-deploy gaps idempotency on Shopify retries · structured logging (Pino) · smoke tests · rate limit · doc LOGO_URL/STORE_URL defaults.
⚠ kimai container has resend-webhook.php + dwolla-webhook.php handlers (audit 2026-04-25). Investigate overlap before deploying the Express server — server-side may already handle some webhook flows.
08 The Hub (Financial OS) live
Financial dashboard — invoice OCR, payments, AR/AP, journal entries against ERPNext.
URL app.gadgetgeekspro.com · fallback the-hub-4og.pages.dev
Code /Users/research/ggp-hub/
Stack Next.js 16 + Tailwind + Framer Motion → Cloudflare Pages. Auth: passkeys (SimpleWebAuthn). Offline: service worker + IndexedDB queue.
Vault keys ANTHROPIC_API_KEY, ERPNEXT_*, CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_TUNNEL_API_TOKEN. CF Pages secrets: WEBAUTHN_RP_ID, WEBAUTHN_ORIGIN, NEXT_PUBLIC_APP_URL.
Last touched 2026-04-09 (Day 1 launch)
Issues / next Day-1 leftovers: enter opening balances with brother; register passkey on his iPhone; Add to Home Screen.
cd /Users/research/ggp-hub
npx @cloudflare/next-on-pages
CLOUDFLARE_ACCOUNT_ID=99b9624f8d6c3f6410a36d19db9a39fd \
npx wrangler pages deploy .vercel/output/static \
--project-name the-hub --branch main --commit-dirty=true
Inventory one system
09 Inventory Intake (PWA) live
Shop-floor IMEI scanning, auto-detect device specs, create ERPNext Item Variant + Serial No + Stock Entry.
URL intake.gadgetgeekspro.com
Code Frontend /Users/research/ggp-inventory/frontend/src/; backend /Users/research/ggp-inventory/ggp-intake-app/server/server.py (~1900 lines, deployed to /root/ggp-intake-app/server/).
Stack Vite + React + TypeScript (Quagga2 barcode) + FastAPI + ERPNext + unlock4less + 248K-entry TAC database.
Vault keys Server /root/ggp-intake-app/server/.env: ERP_URL, ERP_TOKEN; u4l creds (username Tradeingadgets, key) live only on the server. u4l account email accounts@gadgetgeekspro.com. Top-level vault has ERPNEXT_* for cross-system use.
Last touched 2026-04-23 (auto-print labels after submit, grade+tester on label)
Issues / next TS build errors in lots system — ship via npx vite build, fix types as tech debt. Color auto-fill flake on re-tested IMEIs (DHRU 24-48h cache).
u4l health: /api/health returns unlock4less: ok | ip_blocked | auth_failed | down. Per-path egress IPs at /api/u4l/whoami. If ip_blocked, refresh the IPv6 whitelist at unlock4less.com → Profile → API Access.
phone → intake.gadgetgeekspro.com
→ nginx (payroll-setup-proxy-1) on 94.130.58.243
→ FastAPI (server-ggp-intake-api-1) :8080
→ ERPNext (erp.gadgetgeekspro.com)
→ unlock4less (direct from server via IPv6 2a01:4f8:1c19:4c00::1)
Marketing one system · listed but pending Will's confirmation
11 Marketing Org live per memory
Repo of 26+ AI agents on GitHub Actions for content / social / research. Listed as an active workstream in _projects/ggp/context.md; Will did not recognize the name in chat — confirm familiarity before relying on it.
URL github.com/mindfulcrumb/gadgetgeeks-marketing-org
Code Local clone /Users/research/gadgetgeeks-marketing-org/
Stack GitHub Actions + Claude API; cron schedules 2h/3h/6h.
Vault keys ANTHROPIC_API_KEY, OPENROUTER_API_KEY, OPENAI_API_KEY, plus per-platform social tokens stored as GitHub Actions secrets.
Last touched 2026-03-19 (last commit)
Issues / next Run gh run list -R mindfulcrumb/gadgetgeeks-marketing-org to confirm active runs; promote to LIVE once Will confirms ownership.
Vendor & dormant two entries · not part of daily ops
10 Hi-Tek Nova testPod vendor
Phone diagnostics, grading, ADISA-certified data erasure. Vendor SaaS — not built by Will.
URL cloud.hiteknova.com
Code N/A (third-party)
Stack Hi-Tek Nova cloud testPod — ~50–200 devices/day, 45 simultaneous tests, <3 min cycle.
Vault keys None in ~/.claude/.env. Login lives in Hi-Tek's portal — keep in 1Password.
Last touched 2026-04-21 (decision: stay on Hi-Tek, request on-prem/factory edition + custom dashboard wrapper)
Issues / next Awaiting on-prem quote and REST/webhook API spec from Hi-Tek sales.
12 u4l Proxy retired
Cloudflare Worker that proxied unlock4less DHRU calls because Hetzner IPv4 was blocked. Replaced.
URL Former — u4l.gadgetgeekspro.com
Code /Users/research/u4l-proxy/ + local Mac proxy /Users/research/u4l-local-proxy.py + tunnel config ~/.cloudflared/u4l-config.yml
Stack Cloudflare Worker + Wrangler.
Vault keys None — retired.
Last touched ~2026-04 (replaced)
Issues / next Hetzner now calls unlock4less directly via IPv6 (2a01:4f8:1c19:4c00::1 whitelisted). Local Mac files can be archived.
Hetzner host map
Host 94.130.58.243 · IPv6 2a01:4f8:1c19:4c00::1 · SSH ssh -i ~/.ssh/erp-deploy root@94.130.58.243
Container Role Notes
payroll-setup-proxy-1Nginx — terminates :80/:443, routes by Host: Only public ingress
payroll-setup-frontend-1ERPNext frontend (nginx) Serves static, proxies to backend
payroll-setup-backend-1ERPNext + Frappe (bench) API at erp.gadgetgeekspro.com
payroll-setup-queue-short-1Frappe RQ worker (short) Email sends, light async
payroll-setup-queue-long-1Frappe RQ worker (long) Reports, bulk ops
payroll-setup-scheduler-1Frappe scheduler Cron-like ERPNext jobs
payroll-setup-websocket-1Frappe websocket Realtime UI updates
payroll-setup-redis-cache-1Redis (cache) App cache
payroll-setup-redis-queue-1Redis (queue) RQ job queue
payroll-setup-db-1MariaDB 10.11 ERPNext + Kimai DBs
payroll-setup-kimai-1Kimai 2 (apache) + clock/onboard PHP APIs Hosts time.*, container OS in CEST — see TZ note
payroll-setup-n8n-1n8n automation Hosts auto.gadgetgeekspro.com
server-ggp-intake-api-1FastAPI intake :8080 Reads ERPNext + unlock4less
ggp-cloudflaredCloudflare tunnel client Investigate purpose — likely legacy u4l
TZ: payroll-setup-kimai-1 container OS is CEST. Kimai PHP, ERPNext containers, MariaDB, host are UTC. Mismatch only matters if anything reads container date instead of PHP. Set TZ=America/Phoenix on the kimai container to align with the user-facing timezone.
Host file layout
/root/clock-app/index.htmlClock app frontend
/root/clock-app/admin.htmlPayroll Admin frontend
/root/onboard-app/index.htmlOnboarding frontend
/root/ggp-intake-app/Intake PWA static + server
/root/payroll-scripts/Tax reminder cron, NACHA helpers
/data/onboarding/*.jsonPer-employee PII (chmod 750)
/data/company_info.jsonCompany bank info + EIN
/data/admin_password.hashAdmin bcrypt hash
/data/admin_sessions.jsonActive admin sessions
/data/tax_liability_*.jsonPer-period tax liability snapshots
/opt/kimai/public/*.phpAll Kimai-container PHP APIs
Cloudflare DNS
Account Will@mindfulcrumb.com (99b9624f8d6c3f6410a36d19db9a39fd) · Zone gadgetgeekspro.com (521107c5ff9225d0f4b03df30818ee00) · Pages project the-hub → the-hub-4og.pages.dev
Subdomain Type Target Proxied
app.gadgetgeekspro.comCNAME the-hub-4og.pages.devyes
clock.gadgetgeekspro.comA 94.130.58.243yes
time.gadgetgeekspro.comA 94.130.58.243yes
onboard.gadgetgeekspro.comA 94.130.58.243yes
erp.gadgetgeekspro.comA 94.130.58.243yes
intake.gadgetgeekspro.comA 94.130.58.243yes
auto.gadgetgeekspro.comA 94.130.58.243 (n8n)yes
u4l.gadgetgeekspro.com— retired —
hub.gadgetgeekspro.comMX route{1,2,3}.mx.cloudflare.net (future email)—
Vault index tap to expand · key names only, never values
Shopify Theme + Emails + Inventory
SHOPIFY_STORE · SHOPIFY_ACCESS_TOKEN · SHOPIFY_CLIENT_ID · SHOPIFY_CLIENT_SECRET · DEVICEPLUG_STORE · DEVICEPLUG_ACCESS_TOKEN
Webhook only: SHOPIFY_WEBHOOK_SECRET in /Users/research/gadget-geeks-emails/.env
Retrieve: grep '^SHOPIFY_' ~/.claude/.env
ERPNext Hub + Payroll + Onboarding + Inventory + ERP itself
ERPNEXT_URL · ERPNEXT_API_KEY · ERPNEXT_API_SECRET
Compose-only (/Users/research/payroll-setup/.env): SITE_NAME · DB_ROOT_PASSWORD · ADMIN_PASSWORD
Intake server-only (/root/ggp-intake-app/server/.env): ERP_URL · ERP_TOKEN
Retrieve: grep '^ERPNEXT_' ~/.claude/.env
Kimai / Payroll compose-only
In /Users/research/payroll-setup/.env: KIMAI_DB_PASSWORD · KIMAI_ADMIN_EMAIL · KIMAI_ADMIN_PASSWORD
Tax filing Payroll Admin · TaxBandits
In /Users/research/payroll-setup/.env: TAXBANDITS_CLIENT_ID · TAXBANDITS_CLIENT_SECRET · TAXBANDITS_USER_TOKEN
Cloudflare Hub deploy + DNS + Tunnels
CLOUDFLARE_ACCOUNT_ID · CLOUDFLARE_ZONE_ID · CLOUDFLARE_TUNNEL_API_TOKEN
Wrangler OAuth: ~/.wrangler/config/default.toml
Retrieve: grep '^CLOUDFLARE_' ~/.claude/.env
Resend Emails + Onboarding alerts
RESEND_API_KEY · RESEND_DOMAIN · RESEND_FROM_EMAIL · RESEND_FROM_NAME
Retrieve: grep '^RESEND_' ~/.claude/.env
AI providers Hub OCR + Marketing Org
ANTHROPIC_API_KEY · OPENROUTER_API_KEY · OPENAI_API_KEY · GOOGLE_AI_API_KEY · FAL_KEY · ELEVENLABS_API_KEY
Marketing Org / agents
TWITTER_CONSUMER_KEY · TWITTER_CONSUMER_SECRET · TWITTER_BEARER_TOKEN · TWITTER_ACCESS_TOKEN · TWITTER_ACCESS_TOKEN_SECRET · TELEGRAM_BOT_TOKEN · TELEGRAM_LUMINARY_BOT_TOKEN · FIRECRAWL_API_KEY · MODAL_TOKEN_ID · MODAL_TOKEN_SECRET · WANDB_API_KEY · TINKER_API_KEY
Adjacent projects not GGP, kept in same vault
D'Lux Space: DLUX_SPACE_* Lotshare: GITHUB_TOKEN_LOTSHARE · VERCEL_TOKEN_LOTSHARE · SUPABASE_TOKEN_LOTSHARE · CLAUDE_CODE_OAUTH_TOKEN_LOTSHARE · DATABASE_URL_LOTSHARE
Cross-system data flows
A. Time → Pay → ACH out
Employee phone
→ clock.gadgetgeekspro.com (Clock App)
→ kimai PHP APIs → MySQL kimai2_timesheet
→ time.gadgetgeekspro.com (Kimai admin)
→ admin.html (Payroll Admin) reads pay-period
→ clock-generate-nacha.php → NACHA file
→ bank ACH (manual today)
→ ERPNext salary structure + journal entry
→ The Hub displays + reconciles
B. Sale → Invoice → Reconcile
Shopify (gadgetgeekspro.myshopify.com) order
→ webhook → ERPNext sales order + item
→ Hub displays order + payment status
→ Hub OCR (Claude) extracts invoice → ERPNext journal entry
→ Hub closes loop with payment settlement
C. Phone in → Inventory → Storefront
Shop floor IMEI scan
→ intake.gadgetgeekspro.com (PWA)
→ FastAPI :8080 → TAC lookup + unlock4less enrichment
→ ERPNext Item Variant + Serial No + Stock Entry
→ (future) sync → Shopify catalog
Daily operations playbook
1. Run a payroll for the current pay period
Open clock.gadgetgeekspro.com/admin.html .
Verify Live Status, then Pay Period Summary — confirm hours per employee (use hours_override when owner-confirmed differs from raw clock).
Review Payroll Readiness Checklist — every employee green (W-4, A-4, direct deposit, address).
Click Generate Payroll → downloads NACHA + CSV + payment sheet.
Upload NACHA at the bank portal; mark deposit dates in /data/tax_liability_<period>.json.
2. Add a new employee
Create the user in ERPNext (employee record + salary structure).
Send onboarding URL: https://onboard.gadgetgeekspro.com?token=<kimai_token>.
Confirm green on the Payroll Admin "Onboarding" panel.
3. Fix a stuck clock-in
ssh -i ~/.ssh/erp-deploy root@94.130.58.243
docker exec -it kimai bash
mysql -u root -p"$KIMAI_DB_PASSWORD" kimai → UPDATE kimai2_timesheet SET end = ... WHERE id = ...;
4. Deploy intake frontend
cd /Users/research/ggp-inventory/frontend && rm -rf dist && npx vite build
ssh -i ~/.ssh/erp-deploy root@94.130.58.243 "rm -rf /root/ggp-intake-app/assets/*"
scp -i ~/.ssh/erp-deploy dist/index.html root@94.130.58.243:/root/ggp-intake-app/index.html
scp -i ~/.ssh/erp-deploy dist/assets/* root@94.130.58.243:/root/ggp-intake-app/assets/
curl -s -o /dev/null -w "%{http_code}\n" https://intake.gadgetgeekspro.com
5. Deploy intake backend
scp -i ~/.ssh/erp-deploy /Users/research/ggp-inventory/ggp-intake-app/server/server.py \
root@94.130.58.243:/root/ggp-intake-app/server/server.py
ssh -i ~/.ssh/erp-deploy root@94.130.58.243 \
"cd /root/ggp-intake-app/server && docker compose down && \
docker compose build --quiet && docker compose up -d"
curl -s https://intake.gadgetgeekspro.com/api/health
6. Rotate the Shopify access token (24h cycle)
Refresh via flow in ~/.claude/CLAUDE.md knowledge router (shopify-token-flow.md).
Update ~/.claude/.env (SHOPIFY_ACCESS_TOKEN=...).
Update ~/.claude/mcp.json if Shopify MCP is configured there.
Restart any webhook listeners that read the env (Transactional Emails server :4000).
7. Restart a Hetzner container
ssh -i ~/.ssh/erp-deploy root@94.130.58.243
docker ps -a
docker restart kimai
docker logs --tail 100 -f kimai
8. Check ERPNext logs
docker exec -it payroll-setup-backend-1 \
tail -f /home/frappe/frappe-bench/sites/erp.gadgetgeekspro.com/logs/web.log
9. Push refresh-theme to Shopify
Ensure shopify theme dev is running; visually verify at 1280 px AND 375 px.
After any shopify theme pull, strip /* */ blocks from JSON template files.
Push the FULL theme: shopify theme push --live=false --theme <id> (never --only).
10. Send a test transactional email
cd /Users/research/gadget-geeks-emails
node -e "require('./send.js').sendTest('order_confirmation', 'will@example.com')"
Adjust to whatever entrypoint the repo exposes — check package.json scripts.
Open issues & next up
Immediate · this week
Fix _global/identity.md — currently lists owner as "Tony"; it is Will .
Hub Day-1 leftovers — opening balances with brother; passkey on his iPhone; Add to Home Screen.
Hi-Tek Nova on-prem quote — push for price + REST/webhook spec at ~5,000 devices/month.
Confirm Marketing Org — Will to verify the GitHub Actions repo is owned and active, or tell me to delete the entry.
2–4 weeks
Inventory TS debt — fix lots-system type mismatches so npm run build works again.
Pay-stub PDF emailer — generate per-employee PDFs at end of pay period and email via Resend.
Archive cleanup — review ADP-Payroll-Data/, payroll-backups/, ggp-data-export/, ggp-intake-app-upgrade/, payroll-system-docs/; delete or move to cold storage.
1–3 months
QuickBooks/Gusto migration for ACH + tax filing. Keep this stack as the employee-management layer.
Phone Refurb on-prem move + dashboard wrapper — only after Hi-Tek quote arrives.
Inventory ↔ Shopify real-time sync.
MFA on admin dashboards (Payroll Admin + Inventory).
Source of truth: ~/GGP.md · UI: ~/ggp-ledger/index.html · Vault: ~/.claude/.env
Updating: when you build a new system, add a card to the right group using the same eight-field shape, add a row to the status board, and bump the timestamp at the top.
Vault rule: keys here are pointers only. Values stay in the env file.