Commit Graph

43 Commits

Author SHA1 Message Date
denshooter 31dff10636 Use heic-convert for HEIC-to-JPEG conversion
Sharp's prebuilt libvips lacks HEIF codec support. Replace with
heic-convert (pure JS decoder) for reliable HEIC conversion on all
platforms. Existing HEIC files on disk will be converted on-the-fly
when served via /api/files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-22 02:01:04 +01:00
denshooter 6f826c66ea Fix HEIC photos not displaying on non-Apple devices
- Add HEIC-to-JPEG conversion in family-upload route (was missing, unlike admin upload)
- Add error logging for HEIC conversion failures in file serving route

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-22 01:56:37 +01:00
denshooter aa23fb12a5 Refactor Dockerfile: Remove custom libvips build and update stages for Next.js app
Add .dockerignore: Exclude node_modules, .next, .git, markdown files, and docker-compose.yml
2026-02-22 01:50:50 +01:00
denshooter 5061b9c287 Fix Docker build: Use git archive --remote for libvips source
- Replaced curl download with git archive --remote to fetch libvips source, bypassing previous download issues.
- Adjusted tar extraction and directory navigation to correctly handle the output of git archive.
2026-02-22 01:45:47 +01:00
denshooter a6b211a749 Fix Docker build: Download libvips tarball to temporary file first
- Modified the Dockerfile to download the libvips tarball to a temporary file (vips.tar.gz) using curl -o, then extract from that file.
- Added 'set -eux' to the RUN command for better debugging output.
- This addresses the 'gzip: stdin: not in gzip format' error by ensuring a complete download before extraction.
2026-02-22 01:45:16 +01:00
denshooter 48411e432a Fix Docker build: Download libvips tarball directly instead of git clone
- Replaced 'git clone' with 'curl' to download and extract the libvips source tarball. This avoids persistent 'Remote branch not found' errors when cloning specific tags in the Docker environment.
2026-02-22 01:43:51 +01:00
denshooter 6148e5e9ac Fix Docker build: Specify libvips tag explicitly for git clone
- Changed git clone --branch to git clone --branch refs/tags/ to correctly fetch the libvips version by tag, resolving the 'Remote branch not found' error.
2026-02-22 01:27:30 +01:00
denshooter 82c7b5bcc7 Fix Docker build: Add ca-certificates and refine environment variables
- Added ca-certificates to libvips-builder stage to fix SSL verification during git clone
- Refined ENV declarations to avoid build warnings
- Switched back to entrypoint.sh with gosu for better volume permission handling
2026-02-22 01:25:41 +01:00
denshooter 0facc29a97 Fix HEIC/HEIF image loading in Docker and improve Timeline layout
- Rewrote Dockerfile to compile libvips with HEIF support from source
- Set sharp failOn: 'none' to handle minor image metadata warnings
- Improved timeline thumbnails: increased max-h, added object-[center_15%] to prevent cutting off heads, and added subtle hover effects
- Reverted horizontal timeline spacing to restore the original gap
- Polished timeline card padding and font sizes for a more premium look
2026-02-22 01:22:34 +01:00
denshooter 49d8798e11 Update Dockerfile to add HEIF support dependencies and adjust TimelineSection styles for better layout and image handling 2026-02-22 00:27:12 +01:00
denshooter eb28501b2e Add HEIC to JPEG conversion and image resizing support; update dependencies and Dockerfile 2026-02-22 00:17:08 +01:00
denshooter bf070ec47f Fix UI issues, add tests, and patch missing auth on API routes
- Rewrote CandleSection with properly aligned animated flames (fix
  Framer Motion transform-overwrite bug by using left:0 / pixel offsets
  instead of translateX(-50%)); added size prop for inline flames
- Fixed Timeline: CSS dots/line replacing broken SVG estimates, mobile
  padding (pl-10), larger dots, cards grow with content
- Fixed MusicPlayer: actual play/pause (not mute), visibilitychange +
  pagehide handlers so music stops on iOS lock screen / app switch
- Fixed nav: horizontal scroll on mobile (overflow-x-auto whitespace-nowrap)
- Fixed footer: Impressum centered, admin link moved to absolute/hidden
- Removed meine-oma link from TributeSection (page still accessible)
- Added admin auth (isAdmin cookie check) to /api/upload POST,
  /api/contributions/[id] PUT/DELETE, and /api/candles/[id] PUT/DELETE
- Extracted sp(), relativeTime(), formatDate() to src/lib/utils.ts
- Added Vitest with 15 unit tests for utility functions (npm test)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 23:20:48 +01:00
denshooter 6e2ef55cee Fix candle layout, relax AI moderation, fix ReadableStream error
- Candles: clean grid layout with consistent sizing, no overlapping
- AI moderation: much more lenient prompt - short descriptions,
  dates, locations are all valid memorial content
- Fix ReadableStream error by clearing abort timeout after response

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-21 20:37:14 +01:00
denshooter c184f5c679 Make candles bigger and fix inconsistent text sizing
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 21:49:24 +01:00
denshooter 984a616dd1 Fix hero image not showing when cached (check img.complete)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 21:43:41 +01:00
denshooter 5fce4cd1c6 Add fade-in effect to hero image on load
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-19 21:39:29 +01:00
denshooter b14166d826 fix: update funeral date from February 20 to February 19, 2026 2026-02-18 17:10:05 +01:00
denshooter 3c5a92955d fix: correct birth year from 1944 to 1945
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 17:06:01 +01:00
denshooter d5fc2e7ab8 fix: deduplicate photos in gallery by filename, remove duplicate setState
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 16:57:42 +01:00
denshooter ab7e540e25 fix: use persistent data path /opt/oma-memorial/data
Workspace dir gets recreated each build, losing all data.
Using fixed host path ensures DB and uploads persist across deploys.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 16:48:47 +01:00
denshooter bc081c777b fix: allow Next.js RSC/Server Action requests through proxy
Simplified API route matching and added RSC/next-action header passthrough
to prevent 'Failed to find Server Action' errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 16:39:03 +01:00
denshooter ebdac49f91 fix: use proxy network gateway IP for Ollama host mapping
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 13:38:29 +01:00
denshooter c242976b41 fix: configurable OLLAMA_URL for Docker container
Ollama runs on host, container needs host.docker.internal mapping.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 13:38:12 +01:00
denshooter 70ac6c132f fix: entrypoint script fixes data dir permissions at runtime
Container starts as root, creates data dirs, chowns to nextjs,
then drops to nextjs user via su-exec.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 13:26:27 +01:00
denshooter f13b1ba878 fix: data directory permissions for nextjs user (UID 1001)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 13:23:48 +01:00
denshooter b1d52633a6 fix: health check uses node fetch instead of wget
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 13:18:46 +01:00
denshooter 034ba854b5 feat: admin categorized display, improved CI/CD pipeline
- Admin: User timeline contributions shown in Timeline section
- Admin: User memory contributions shown in Erinnerungen section
- Admin: User photo uploads shown in Familien-Uploads section
- All contributions still appear in unified Beiträge section
- Dockerfile: fix data dir path (/data -> /app/data)
- CI/CD: use checkout@v4, retry health check, auto-create proxy network
- CI/CD: support SITE_PASSWORD/ADMIN_PASSWORD secrets
- CI/CD: use wget instead of curl (alpine compat)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 13:04:20 +01:00
denshooter 9223a2bfbb fix: photo display, duplicate detection, memory photos
- Remove duplicate FamilyUploadSection from public page
- Remove 'Von Anonym' caption from user-uploaded gallery photos
- Add SHA-256 duplicate detection in upload route (same file → same path)
- Fix timeline photos: use object-contain instead of object-cover (no clipping)
- Fix timeline modal photos: remove fixed h-48 height
- Add photo display support to MemorySection component
- Include media_filenames in memory contribution queries
- Add media_filenames to Memory type

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 12:53:25 +01:00
denshooter 40ace3522c fix: uploads and contributions display
- Remove duplicate FamilyUploadSection (PhotoUploadSection already handles this)
- Fix contributions POST: don't require content for timeline/media types
- Save all fields (year, month, day, location, media_filenames) in contributions INSERT
- Add user-uploaded photos from contributions to public photo gallery
- Fix PhotoUploadSection to include title in submission

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 12:43:13 +01:00
denshooter 2fb6dd7279 fix: auto-approve clean content, fix AI moderation, show all contributions
- Auto-approve: clean submissions now default to 'approved' (not 'pending')
- Switch AI model from qwen3:4b to llama3.2 (qwen3 writes to thinking field, response always empty)
- AI now correctly flags spam, nonsense, and irrelevant content
- Admin: show all contribution types including timeline (was filtering them out)
- Add FamilyUploadSection to public page (was imported but never rendered)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 12:32:22 +01:00
denshooter a34d406375 feat: complete memorial website features
- Add user contribution system (memories, timeline entries)
- Add AI content moderation with Ollama (bad word detection + qwen3:4b)
- Add family photo/video upload with admin approval
- Add candle lighting feature
- Add timeline and recipe sections
- Add QR code page and OG image
- Add site authentication (password-protected access)
- Add proxy middleware for auth routing
- Add admin dashboard for content management
- Remove email fields, make name optional (default: Anonym)
- Add CI/CD pipeline for Gitea Actions
- Add Docker deployment configuration
- Optimize Ollama RAM usage (42GB → 2.9GB)
- Fix API routes accessibility through proxy middleware

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-02-18 12:20:33 +01:00
denshooter 43e9d49620 fix: simplify music autoplay for Mac desktop compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 04:15:30 +01:00
denshooter 41604e8314 fix: Music autoplay auf Desktop – saubere fadeIn/startPlayback Logik
Refs statt State für started/audible Tracking, fadeIn als eigene
stabile Callback-Funktion, kein verschachteltes Promise-Handling mehr.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 04:02:03 +01:00
denshooter 6363d1327b feat: Musik global, Dennis-Teil auf eigene Seite, Mobile-Autoplay
- MusicPlayer ins Layout verschoben (läuft auf allen Seiten)
- Mobile-Autoplay: Desktop startet stumm + fade-in bei Scroll,
  Mobile wartet auf ersten Touch und startet dann mit Fade-In
- Dennis-Perspektive auf eigene Seite /meine-oma ausgelagert,
  dezenter Link "Von Dennis" am Ende der Tribute-Sektion
- "Berge von Essen" entfernt
- "Jacky und Niklas" → "ihre Enkelin" / "Meine Schwester"

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 03:57:48 +01:00
denshooter 4d56d4904a feat: persönliche Gedenkseite – Tribute, Autoplay-Musik, Next.js 16 Fixes
- TributeSection: zwei Perspektiven (Familie + Dennis), emotional und persönlich
- MusicPlayer: Autoplay mit stummem Start + Fade-In bei Interaktion, nahtloser
  Crossfade-Loop (überspringt stille letzten 10s), kompakter Mute-Button
- Alle API-Routes: export const runtime = 'nodejs' für node:sqlite in Next.js 16
- Admin: defensive res.ok Checks vor .json() Parsing
- DB: mkdirSync erst zur Laufzeit, path.resolve für DATA_DIR
- page.tsx: plain() Helper für null-prototype SQLite-Rows
- erinnerungen.md: alle Familieninfos und Erinnerungen dokumentiert
- Nav: Musik-Tab entfernt, "Über Oma" hinzugefügt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 03:48:46 +01:00
denshooter 313b5ff7fd fix: singing bowls ambient + Next.js 16 async params/cookies
Ambient:
- Replace oscillator drone/melody with singing bowl synthesis
- Each bowl: instant attack + exponential decay (7–12s) = real physical sound
- Two detuned copies per strike for natural shimmer beat
- A-minor pentatonic (A3 C4 D4 E4 G4 A4 C5 E5), weighted toward warm lows
- 30% chance of soft harmonic fifth companion tone per strike
- Random gaps 3–8s between strikes so it breathes naturally
- Two long hall reverb tails (2.4s / 4.8s) for warmth and space
- Graceful 2.5s fade-out on stop

Next.js 16 compatibility (breaking changes from v14→v16):
- Dynamic route params now Promise<{...}> → await params in all handlers
- cookies() now returns Promise → isAdmin() made async, await cookies()
- Files: [...path], memories/[id], media/[id], auth, upload all updated

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 02:44:45 +01:00
denshooter 00abbfda51 feat: emotional ambient – melody + dynamic arc + vibrato
Three layers:
1. PAD: Am9 breathing pad (unchanged structure, more varied mid-valley shape)
2. MELODY: slow A-minor cello phrase (A4→Ab4→G4→F4→E4→D4→C4→D4→E4→G4→A4)
   - ~45s per cycle, soft attack/release per note
   - Vibrato LFO (4.5 Hz, ±4 Hz) for natural voice quality
   - Scheduled via AudioContext timing for sample-accurate handoffs
3. DYNAMIC ARC: 60s master gain cycle (0.12 → 0.26 → 0.12) for emotional peaks
   - Builds over 18s, peaks at 30s, exhales to 60s
   - Repeats → each minute has a distinct emotional shape

Result: sounds like a distant cello line over a soft choir pad, with
emotional crescendos every minute. Not just breathing – actual movement.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 02:37:09 +01:00
denshooter 74b253095e fix: ambient pad – emotional choir swell, no bass buzz
Replace static LFO drone with proper breathing envelope pad:
- Remove low bass (55/110 Hz) that caused "surren" (buzzing)
- Am9 chord in mid range: A3·C4·E4·G4·B4 (220–494 Hz)
- 10 voices total (2 detuned copies per note) → natural chorus shimmer
- Each note breathes independently: 10–18s swell cycle, staggered offsets
- Envelope: gradual rise (45% of cycle) + smooth fade → sounds like choir
- Two long hall-reverb delay lines (2.6s / 3.9s, no feedback) for depth
- Clean fade-out on stop

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 02:33:08 +01:00
denshooter 1ab5809a82 fix: remove candles, deduplicate dates, add ambient music fallback
- Remove CandleSection from page; dates now appear only in hero
- Footer stripped to just quote + impressum/admin links (no name/dates)
- Musik nav link always visible
- MusicPlayer: Web Audio API ambient mode when no tracks uploaded
  - A-minor pad (55/110/130/164/220 Hz sine oscillators)
  - Feedback delay for spaciousness, per-note LFO swells, 6s fade-in
  - "Stille Begleitung" UI with waveform bars
  - When tracks are uploaded: full track list + cycle mode as before
  - Floating mini-player works for both modes

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 02:19:28 +01:00
denshooter 4aeb08cb57 feat: music player redesign, candle section, impressum
MusicPlayer:
- Beautiful inline section with numbered track list + click-to-play
- Animated waveform bars on playing track
- Time display (elapsed / duration) on progress bar
- Floating mini-player with track name + time, shows after first play
- Play/pause in mini-player, close button

CandleSection:
- 7 hand-coded CSS/Framer Motion candle flames with organic flicker
- Layered flame (outer glow + main + inner core) + wax drip highlight
- "Ruhe in Frieden" text with subtle glow

Impressum:
- New /impressum page with TMG §5 structure (placeholder address)
- Privacy notice (no cookies/tracking, voluntary memory data)
- Copyright, liability disclaimer
- Consistent cream design with Cormorant/Lora typography

page.tsx:
- CandleSection added between VideoGallery and MusicPlayer
- Musik nav link (conditional on tracks)
- Footer Impressum link
- MemorySection wrapped in id="erinnerungen" section for nav anchor

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 02:08:28 +01:00
denshooter 279a07e4eb feat: dark cinematic hero + public memory write section
- HeroSection: animated warmgold/burgundy/indigo orbs on #060304 bg, film grain CSS overlay, larger glowing typography
- WriteSection: new public component – collapsible form (name optional, title, textarea) posts to /api/memories without auth, shows success state and refreshes page
- API: remove isAdmin() guard from POST /api/memories, accept author field
- DB: migration adds author TEXT column to memories (try/catch for existing DBs)
- Types: add author: string | null to Memory type
- MemorySection: display "— [Name]" beneath date when author is set
- globals.css: grain keyframe animation for film-texture overlay

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-16 01:45:57 +01:00
denshooter 8b4dc2e7e6 Fix crash when no music uploaded (null guard for track) 2026-02-16 01:37:02 +01:00
denshooter bdcfa8f3c5 Initial commit: Maria Malejka memorial website
Next.js 14 + node:sqlite memorial site with:
- Hero section, photo slideshow & gallery
- Memory/thoughts editor (admin)
- Music player with upload
- Video gallery
- Docker Compose deployment
- Responsive warm earth tone design
2026-02-16 01:26:37 +01:00