- Simple preferences page with engine selection
- Light/dark theme toggle with localStorage persistence
- Clean form layout without complex JS dependencies
- Add dark theme CSS variables
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wikipedia returns HTML entities like <span> which were being
double-escaped by Go templates. Now using html.UnescapeString and
template.HTML to render properly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace React SPA with simple Go templates using search-zen-50
visual style. No JavaScript required - pure HTML/CSS with clean
teal accent color scheme, monospace logo, and minimal design.
- Simplified base.html without HTMX or autocomplete JS
- Clean homepage with centered search box
- Results page with sticky header and category tabs
- Simplified CSS matching search-zen-50 aesthetics
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add internal/spa package for embedding React build
- Wire SPA handler in main.go for non-API routes
- Add gitignore entry for internal/spa/dist
- Add implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace template-based handlers (h.Index, h.Preferences) with the new spa
handler. API routes (healthz, search, autocompleter, opensearch.xml) are
registered first as exact matches, followed by the SPA catchall handler
for all other routes. Remove unused views and io/fs imports.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Creates internal/spa package that:
- Embeds React build output from cmd/kafka/dist/
- Provides HTTP handler for static file serving
- Falls back to index.html for SPA client-side routing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reverted CSS to the known-working state at 4b0cde9, then re-applied
only the image grid styles. The duplicate .results-layout block is
intentional — it was present in the working version too.
The old 3-column layout block (referencing .left-sidebar/.right-sidebar
classes that don't exist in the HTML) was overriding the correct layout
defined earlier. Removed the stale duplicate.
Three new image search engines:
- bing_images: Bing Images via RSS endpoint
- ddg_images: DuckDuckGo Images via VQD API
- qwant_images: Qwant Images via v3 search API
Frontend:
- Image grid layout with responsive columns
- image_item template with thumbnail, title, and source metadata
- Hover animations and lazy loading
- Grid activates automatically when category=images
Backend:
- category=images routes to image engines via planner
- Image engines registered in factory and engine allowlist
- extractImgSrc helper for parsing thumbnail URLs from HTML
- IsImageSearch flag on PageData for template layout switching
- results-layout: 3-column grid (1fr | min(768px,100%) | 300px) max-width 1400px, centered
- Widen center results column to 768px max
- Right column (formerly sidebar): sticky, contains knowledge panel + related searches
- Knowledge panel: Wikipedia/infobox summary with optional thumbnail
- Related searches: clickable links to refine the query
- Empty left buffer creates balanced whitespace on large screens
- Responsive: 2-col at 1000px, 1-col at 700px
New brave.go: scrapes https://search.brave.com directly.
Extracts title, URL, snippet, and favicon from Brave's HTML.
No API key required.
Rename existing BraveAPIEngine (was BraveEngine) to avoid collision
with the new scraper. API engine stays as 'braveapi', scraper as 'brave'.
The correct vendorHash for current go.mod is:
sha256-8wlKD+33s97oorCJTfHKAgE2Xp1HKXV+bSr6z29KrKM=
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The go.mod was updated with new replace directive for golang.org/x/net.
Need to recompute vendorHash.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Go's regexp package doesn't support Perl lookahead (?=...). Removing
the unnecessary lookahead since each MjjYud div is self-contained.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap sidebar time/type filters in a form with HTMX attributes so
filter changes trigger partial page updates instead of full reload.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add tmplPreferences variable to views.go var block
- Initialize tmplPreferences in init() function
- Add RenderPreferences function to views.go
- Fix step numbering for Task 4
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wikipedia language subdomain was derived from user input without
validation, allowing attackers to redirect requests via malicious
language values like "evil.com.attacker.com". Added a whitelist of
valid Wikipedia language codes to prevent this.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move template registration from Phase 2 to Phase 4 (was causing build failure)
- Add filter params (activeCategory, activeTime, activeType) to FromResponse
- Add DisabledCategories to PageData for backend-unsupported categories
- Add disabled class to sidebar for future categories
- Clarify POST handler is a no-op for localStorage-only preferences
- Note CSS must be tested manually in browser
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Clarify localStorage-only preferences (no server persistence)
- Expand category tiles including future ones (weather, sports, crypto)
- Define filter UI options with query params (time range, result type)
- Add mobile breakpoints and collapse behavior
- Reduce quick popover to theme + engines only
- Rename Preferences Sidebar to Preferences Nav
- Add results count format specification
- Add sticky positioning CSS for left sidebar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Brave API only supports offset values 0-9. When pageno > 1 with
resultsPerPage=20, offset exceeded this limit causing 422 errors.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The nix store may have stale vendor directories with incorrect
permissions. Force chmod before removing to ensure clean build.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>