all repos — weimar @ cd624b1b90061a10147950a7633dd7579c78a61d

Unnamed repository; edit this file 'description' to name the repository.

cd624b1b
feat: full-screen drag-and-drop upload zone

Document-level drag events trigger a full-screen overlay with dark
backdrop and dashed red border, accepting the file on drop
anywhere on the page. File can still be selected via button click.

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-v4-flash
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 21:14:24 +0200
afea02cb
fix: graceful SIGINT shutdown and SIGHUP config reload

SIGINT now exits cleanly with code 0 instead of propagating
http.ErrServerClosed as a fatal error. SIGHUP re-reads the config file
and atomically swaps the config pointer β€” settings like site_title,
favicon_path, behind_proxy, and require_auth_for_browse take effect
immediately without restarting. Config is stored as *config.Config
throughout so handlers and middleware read the live value at request time.

Co-authored-by: Crush
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 20:10:38 +0200
b26a020c
feat: configurable site title, favicon, and nav logo

Add site_title, favicon_path, and logo_path config options. Default favicon
is an embedded SVG with a red lowercase "w" on black. Custom favicons can
be SVG, PNG, JPG, or ICO β€” the /favicon handler serves them with the
correct Content-Type detected from the file extension. The /logo handler
serves a nav logo; when set, the layout shows an <img> instead of the text
site title. The GET /api/config endpoint exposes these URLs to the frontend.
Includes example config at configs/example.toml.

Co-authored-by: Crush
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 20:05:05 +0200
a213da87
fix: security hardening β€” bcrypt cost, secure cookies, security headers, avatar auth

Bump bcrypt cost from 10 to 12 for adequate brute-force resistance in 2026.
Add behind_proxy config option that enables Secure flag on session cookies
for deployments behind a TLS-terminating reverse proxy (Caddy, nginx).
Add X-Content-Type-Options, X-Frame-Options, and Referrer-Policy security
headers to every response. Fix avatar endpoint auth mismatch β€” avatars are
now served publicly since their URLs are exposed in gallery listings anyway.

Co-authored-by: Crush
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 19:56:35 +0200
87601e8f
feat: public browsing, shareable image URLs, and tag editing

Public browsing is the new default β€” unauthenticated users can browse the
gallery, view images, and download originals. Lock it down by setting
`auth.require_auth_for_browse = true` in weimar.toml.

Each image now gets a shareable URL when opened in the overlay viewer:
`/browse?image=<id>`. Navigate to it directly and the viewer opens
automatically (or redirects to the detail page if the image is on a
different page).

Image owners can now edit tags from the overlay viewer or the detail page.
A text field with autocomplete and ADD/REMOVE buttons appears below the
tag display on your own uploads.

Backend: new public/optional auth middleware, AddImageTags/RemoveImageTags
queries, is_owner field on image detail, require_auth_for_browse config
option. Frontend: viewer tag editing, shareable URL via pushState, image
detail page uses is_owner from backend instead of separate getMe() call.

Co-authored-by: Crush
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 19:42:40 +0200
cf03eeda
fix: reduce avatar processing to 128px, double viewer avatar to 80px

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 18:25:32 +0200
c9643af6
feat: default avatar SVG, nav bar avatar, fix settings preview

- Avatar.svelte component: shows uploaded image or red SVG fallback
  with first letter of username
- Nav bar shows avatar (28px) in top-right corner next to LOGOUT,
  links to /settings
- Layout now fetches GET /api/users/me instead of pinging images
  endpoint for auth state
- Settings page loads current avatar on mount via getMe()
- ImageViewer uses Avatar component for uploader display
- Cleaned up unused CSS classes

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 16:53:37 +0200
8d72190a
feat: add user avatars and settings page

Backend:
- Migration v7: avatar_path TEXT column on users table
- POST /api/users/me/avatar β€” upload avatar (resized to 256px, JPEG)
- GET /api/users/{id}/avatar β€” serve avatar image
- avatar_url included in both list and detail image responses

Frontend:
- New /settings page with avatar upload (file picker, preview, save)
- SETTINGS link in nav bar (visible when logged in)
- Uploader avatar shown in browse card overlay, ImageViewer info bar,
  and image detail page

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 16:41:12 +0200
74fc3e1e
feat: show uploader username and database ID on media

- Added UploaderUsername field to Image model, populated from users
  table in both list and detail API responses
- Shows uploader username in browse card overlay, ImageViewer info
  bar, and image detail page
- Shows database ID (#id) alongside metadata in all three locations
  for admin CLI convenience

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 16:31:26 +0200
da5efcda
fix: restore full-width grid by fixing :global target after layout refactor

The layout changed from `<main>` to `<div class="main">`, breaking
the browse page's `:global(main)` override. Updated to `:global(.main)`.

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 16:19:04 +0200
a8921d22
feat: bold Swiss/constructivist design overhaul

Typography:
- Inter for body text, Oswald for headings (bold condensed)
- ALL CAPS labels, large type hierarchy, tight letter-spacing

Colors:
- Black (#1a1a1a) background on UI elements, white text
- Red (#c62828) accent for hover states, underlines, CTA buttons
- Light gray (#f5f5f5) page background for contrast

Layout:
- Black nav bar with red bottom border, red hover states
- Red accent underline blocks (3px x 3rem) on page headings
- No border-radius anywhere β€” sharp rectangular constructivist forms
- Full-width 6-column gallery grid with 2px gaps

All pages redesigned: home, browse, upload, login, image detail,
and image viewer overlay.

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 16:14:34 +0200
3ab9da92
feat: make tags clickable with usage counts, larger and more prominent

- Tags in ImageViewer and detail page are now clickable pill buttons
- Clicking a tag navigates to /browse?tag=<tagname>
  with the filter auto-applied on mount
- Browse page reads ?tag= URL param on initial load
- Tags display usage count badge (sorted most→least frequent)
- Larger pill sizing with hover effects in both viewer and detail page
- New GetImageTagsWithCounts DB function joins tags+image_tags
  for usage counts returned in GET /api/images/{id} as tags_detail

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 16:02:30 +0200
a338ad58
feat: make browse grid 6 columns and full-width

- Grid layout set to repeat(6, 1fr) with responsive breakpoints for smaller screens
- Removed layout max-width constraint on browse page via :global(main) override
- Header and pagination get their own padding within the full-width layout
- Increased per page to 60 for better coverage at 6 columns

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 15:50:15 +0200
4725091c
feat: redesign browse grid with Chevereto-style card layout and hover overlay

- Compact grid with 2px gaps and dark image backgrounds (aspect-ratio 16:10)
- Image fills card via object-fit: cover with subtle scale-on-hover
- Gradient overlay on hover shows filename, dimensions, and truncated tags
- Removed rounded corners and info text below cards for cleaner look

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 15:44:59 +0200
4240c5c9
feat: add image overlay viewer with keyboard navigation and idle UI fade

Replaces full-page navigation with a Chevereto-inspired lightbox overlay
when clicking thumbnails in the browse grid. Supports prev/next via
buttons and arrow keys, close via Esc/click-outside, auto-hiding controls
after 3s of inactivity, and a bottom info bar with metadata and download.

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 15:34:07 +0200
5db53247
fix: preserve all tags on upload and return empty array on no match

Tags beyond the first were silently dropped because `r.FormValue("tags")`
returns only the first value when the frontend sends each tag as a
separate FormData field. Changed to `r.Form["tags"]`.

Nil slices in API responses (`var images []Image`) marshalled to JSON
`null`, causing a TypeError in the Svelte template (`null.length`),
making "Loading..." persist forever. Initialized all API-facing slices
with `make()` so they marshal as `[]`.

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 15:16:05 +0200
77821058
feat: implement core backend API and SvelteKit SPA

Full MVP implementation of the weimar media repository:
- CLI commands for user CRUD, image deletion, password reset
- HTTP API with auth (cookie sessions), upload, browse, download,
  thumbnail serving, and tag autocomplete
- SQLite-backed storage with migrations
- Hash-partitioned disk storage with EXIF stripping and thumbnails
- SvelteKit SPA with login, upload, browse grid, and image detail pages
- Makefile build flow: SvelteKit build -> Go embed -> single binary
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 14:03:41 +0200
28e89651
feat: initial project scaffolding

Single-binary media repository for home servers β€” Go backend with
embedded SvelteKit SPA.

- Cobra CLI with viper config (TOML, env vars WEIMAR_*, flags)
- Commands: serve, users, image, version
- HTTP server with Go 1.22+ ServeMux, API route stubs, SPA fallback
- SvelteKit frontend with adapter-static (SPA mode, 5 routes)
- Build pipeline: Makefile, GoReleaser, UPX compression
- ldflags-based version and build date injection

πŸ’˜ Generated with Crush

Assisted-by: Crush:deepseek-reasoner
Maxwell Jensen maxwelljensen@posteo.net
Wed, 13 May 2026 11:05:44 +0200