7.0 KiB
7.0 KiB
Ghost Node — Session Memory
What belongs here: Current architecture state, key gotchas, reusable patterns, dev paths. What does NOT belong here: Session history (→ PROGRESS.md or ARCHIVE.md).
⚠️ MD Update Rule — DYNAMIC, NOT STATIC
Only update the MD file(s) whose content was actually touched this session. Do NOT update all files after every task. Each file gets only what is relevant to it.
- Update this file only when a new reusable gotcha, pattern, or architecture decision was made.
- Update PROGRESS.md whenever any code file was changed.
- Update CLAUDE.md only if API endpoints, DB schema, config keys, or architecture changed.
- Move old PROGRESS.md session entries to ARCHIVE.md when they're no longer active context.
Project Identity
- Ghost Node International Auction Sniper v2.7
- Owner: Abbas, Baghdad, Iraq
- Path:
C:\Users\Abbas\Documents\Downloads\ClaudeAuction2\ - Backend: Python FastAPI (worker.py, 5000+ lines), port 8000
- NOT a git repository
Frontend Stack (Current — Session 16, fully migrated)
- Location:
frontend/directory - Next.js 16.1.6, React 19, TypeScript, Tailwind CSS v4 (NOT v3)
- Tailwind v4: CSS variables via
@theme {}inglobals.css— NOtailwind.config.ts - Session 27 redesign: CSS prefix changed from
ghost-*tog-*. Colors:--color-g-base(#050510),--color-g-green(#00e87b),--color-g-cyan(#06b6d4), etc. Classes:bg-g-base,text-g-green. Components:.g-card,.g-card-glow,.g-btn,.g-btn-primary,.g-badge,.g-table,.glass,.glass-strong,.gradient-text,.gradient-accent. Backward compat aliases (.card-panel,.btn-ghost,.btn-danger,.page-title,.page-subtitle) still work. output: 'export'in next.config.ts → static build atfrontend/out/- Node.js: default installer
C:\Program Files\nodejs\(on PATH). Alternative: portable atC:\Users\Abbas\AppData\Local\nodejs-portable\node-v22.14.0-win-x64\
Key Architecture Decisions
- SSE route disabled for static build (
app/api/stream/route.ts.disabled) - All API files use
http://localhost:8000as BASE (full URL, not relative) - FastAPI serves Next.js static build when
frontend/out/exists if _frontend_out.exists():guard is safe —dashboard.htmlstill works without out/ dir- SPA routing:
app.mount("/_next", ...)for assets only +@app.get("/{full_path:path}")catch-all for SPA routing. Never useapp.mount("/", StaticFiles(html=True))— it shadows all explicit routes
File Structure
frontend/
├── app/
│ ├── ai-log/page.tsx
│ ├── dashboard/page.tsx
│ ├── keywords/page.tsx
│ ├── listings/page.tsx
│ ├── settings/page.tsx
│ ├── sites/page.tsx
│ ├── globals.css (Tailwind v4 @theme, cyberpunk palette, btn-ghost, btn-danger)
│ ├── layout.tsx
│ ├── page.tsx (redirects to /dashboard)
│ └── providers.tsx ('use client' QueryClientProvider)
├── components/
│ ├── ai-log/ (AILogCard, AILogFeed)
│ ├── dashboard/ (StatsGrid, ActivityLog)
│ ├── keywords/ (KeywordRow, KeywordsTable — dnd-kit, ScoringRulesPanel)
│ ├── layout/ (Header, Nav, StatusBar)
│ ├── listings/ (ListingRow, ListingsTable, ListingDetailPanel, ImageGallery)
│ └── sites/ (SiteRow, SitesTable — dnd-kit)
├── hooks/ (useSSE, useListings, useCountdown, useKeywords, useSites)
├── lib/
│ ├── api/ (listings, keywords, sites, config, engine, system, ai, scoring-rules)
│ ├── types.ts
│ └── utils.ts (cn, formatUptime)
├── store/ (engineStore, settingsStore)
├── out/ (static build — served by FastAPI)
└── vitest.config.ts (has @/ alias resolution)
Tests (21 passing)
- theme.test.ts (2), types.test.ts (4), engineStore.test.ts (3)
- listings-api.test.ts (3), useCountdown.test.ts (2)
- StatsGrid.test.tsx (1), StatusBar.test.tsx (3), ListingRow.test.tsx (3)
Dev Paths & Commands
Node.js
- Default installer (
C:\Program Files\nodejs\): usually on system PATH — open new terminal and runnode --version; no manual PATH needed. - Portable (if used): set PATH in each shell before
npx/npm:- PowerShell:
$env:PATH = "C:\Users\Abbas\AppData\Local\nodejs-portable\node-v22.14.0-win-x64;$env:PATH" - Bash:
export PATH="/c/Users/Abbas/AppData/Local/nodejs-portable/node-v22.14.0-win-x64:$PATH"
- PowerShell:
Common Commands
# Start backend
python worker.py # port 8000
# Frontend build (from project root)
export PATH="..." && npm run build --prefix frontend
# Run tests (from project root)
export PATH="..." && cd frontend && npx vitest run
# Combined build + test
export PATH="..." && cd frontend && npx vitest run && npm run build
Key Gotchas (Never Forget These)
Python / Backend
threading.Eventnotasyncio.Eventfor cross-thread signalling — asyncio.Event is not thread-safe- SQLite
enabledfield: Store asint(1/0), neverbool—filter(enabled==1)breaks on PythonTrue - JS in f-strings: Use backtick template literals, never apostrophes — breaks Python f-string parsing
db.flush()beforedb.commit(): SQLite WAL locking requires thiscalculate_attribute_score()opens own DB session — don't call inside an already-open session loopclosing_alerts_sent: JSON list — alwaysjson.loads+ append, never overwrite
FastAPI Routing
- NEVER
app.mount("/", StaticFiles(html=True))with explicit routes you want to preserve — the root mount captures ALL paths. SPA fallback returns 200+index.html for unknown paths, shadowing@app.get("/legacy")etc. - Fix:
app.mount("/_next", ...)for assets +@app.get("/{full_path:path}")explicit catch-all
API Format
/api/configGET returns flat{key: value}dict, NOTConfig[]array/api/configPOST expects flat dict — not[{key, value}]array- Frontend
fetchConfig()must call.then(data => setConfig(data))directly — no.map()
Frontend
- SSE disabled in static export —
EventSource('/api/stream')always 404s. Use HTTP polling instead createPortalneeds SSR guard —document.bodyunavailable during Next.js SSR. UseuseEffect(() => setMounted(true), [])before rendering portal
HiBid
- Apollo cache: Search results pages have 0 Lot entries — images only from detail pages
- Image dedup: Use full URL including query string (HiBid CDN uses same path
img.axdfor all images, differentiated only by query params)
Pending Work (Priority Order)
- Redis Cache Layer — replace in-memory Python dicts; survives restarts; pub/sub for live dashboard
- Docker Compose — one-command startup with PostgreSQL + Redis
- Lot Description Extraction — AI only sees title; detail page descriptions → better AI-first accuracy. Needs
JS_DETAIL_TEXT+descriptioncolumn on Listing + pass to_ai_analyze()