Commit Graph

20 Commits

Author SHA1 Message Date
mariosemes
b243e06175 Fix SSE streaming by hijacking Fastify response
Fastify was buffering the SSE response, causing store progress
to appear stuck. Using reply.hijack() hands off the raw response
so events flush immediately to the client.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:22:45 +01:00
mariosemes
37425812e0 Add real-time per-store search progress via SSE streaming
Backend: new /api/search/stream SSE endpoint that emits events
as each store completes: start (store list), store_complete
(results + duration), store_error, and done (final meta).

Frontend: results page now shows live progress per store with
spinning indicators while searching, checkmarks when done, and
X marks on errors. Each store chip shows product count and
response time. Results stream into the table as stores complete
instead of waiting for all stores to finish.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:15:50 +01:00
mariosemes
fe56c3b17e Lazy-load puppeteer to fix tsx watch hanging on startup
Puppeteer import at top level was blocking tsx watch mode,
preventing the server from starting. Now imported dynamically
only when a JS-rendered store is actually scraped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:08:09 +01:00
mariosemes
42f2cab158 Add Links.hr store config (cheerio, no JS rendering needed)
Croatian electronics retailer, 24 products per page.
Uses .card.mobile-card containers with h3 for names,
.product-price for prices, a.card-link for links.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:56:36 +01:00
mariosemes
0693b66b3c Make filter input larger and more prominent
Bigger padding, larger icon, rounded-lg, ring on focus,
text-sm instead of text-xs. Matches the search bar feel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:53:10 +01:00
mariosemes
acda8d5270 Replace search bar with title and New Search button on results page
Header now shows "Search results for: <keyword>" with meta stats,
and a "New Search" button that navigates back to the homepage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:52:22 +01:00
mariosemes
ac05e83bdd Move store chips to own row below filter input
Filter bar now has two rows: text filter + count on top,
store toggle chips on the bottom. Chips wrap on narrow screens.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:50:54 +01:00
mariosemes
4fb0d65710 Replace store dropdown with checkbox toggle chips
Each store appears as a clickable chip with a checkmark. Click to
exclude a store from results (greys out with strikethrough). Click
again to re-include. Multiple stores can be toggled independently.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:49:55 +01:00
mariosemes
a8d4a9ce3a Always show store filter dropdown on results table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:47:43 +01:00
mariosemes
68b3f9ecbc Make search and filter inputs full width within container
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:46:07 +01:00
mariosemes
23d46384d7 Cap results page width at 1400px for readability on wide screens
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:44:36 +01:00
mariosemes
9bdd5c4910 Replace results cards with sortable, filterable table
- Compact table view with thumbnail, product name, price, store, link
- Click column headers to sort (toggles asc/desc)
- Filter bar to search within results by product name
- Store dropdown filter when multiple stores present
- Sticky header, hover-reveal "Open" link, sort direction arrows
- Shows "X of Y shown" count when filtering

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:43:32 +01:00
mariosemes
c24b06215b Fix loading state stuck when API calls fail on startup
Add try/catch to all onMount API calls so the UI recovers
gracefully when the server isn't ready yet instead of hanging
on the loading skeleton forever.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:41:17 +01:00
mariosemes
6e740d3db4 Fix CSS @import order — must precede @tailwind directives
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:37:20 +01:00
mariosemes
130ab30fcc Add Puppeteer browser scraping and HG Spot store config
- Add browser-scraper.ts using Puppeteer for JS-heavy stores
- Add render_js flag to store model, migration, YAML sync, and UI
- Scraper engine auto-selects cheerio vs Puppeteer based on flag
- Store forms include JS rendering toggle in Advanced section
- Create first store config: HG Spot (Croatian electronics retailer)
- Update Dockerfile with Chromium for production Puppeteer support

Tested: HG Spot returns 15 products per page with correct names,
prices (EUR), links, and images using headless browser rendering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:36:20 +01:00
mariosemes
97fb8d9663 Make sidebar collapsible with hamburger toggle
Sidebar is now hidden by default, opened via a small hamburger
button in the top-left corner. Clicking a nav link or the overlay
closes it. Keeps focus on the search bar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:18:23 +01:00
mariosemes
98e326266f Restyle entire frontend with Linear-inspired dark design
- Dark-first design with #0a0a0b backgrounds and subtle borders
- Purple/violet accent colors for primary actions
- Inter font with custom design tokens
- Sidebar navigation replacing top nav bar
- Compact, information-dense tables and cards
- Consistent component classes (btn-primary, input-field, card, label)
- Custom scrollbar and selection styling

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:14:14 +01:00
mariosemes
26467a6368 Add YAML-based store configs with bidirectional sync
Stores can now be defined as YAML files in the stores/ directory.
On startup, YAML files are synced into the database. Changes made
via the admin UI are written back to YAML files automatically.

- Add store-sync service (load from files, export to files, write-back)
- Add /api/stores/sync and /api/stores/export endpoints
- Add Sync/Export buttons to admin UI
- Mount stores/ volume in Docker
- Include example store config template

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 21:06:29 +01:00
mariosemes
8ce5ba62dc Add README with project overview and quick start guide
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:57:24 +01:00
mariosemes
e0f67d0835 Initial commit: Price Hunter — self-hosted price comparison engine
Complete application scaffolding with:
- Backend: Node.js + Fastify + sql.js (SQLite)
- Frontend: SvelteKit + Tailwind CSS
- Scraper engine with parallel fan-out, rate limiting, cheerio-based parsing
- Store management with CSS selector config and per-store test pages
- Docker setup for single-command deployment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 20:54:52 +01:00