v1.33.2May 17, 2026Latest
Edit-form influencers, 'Use current location' on new dreams, Trending patterns shortcut, signed-in CTA
featureuxsubmit
- 📋 Editing an existing dream now exposes the same six 'Dream Influencers' fields the submit form has — location, time of day, food/drink, substances, stress level, sleep quality. The panel lazy-loads existing values when you open the edit form and auto-expands when there's already data; empties on save clear the row. No more losing influencer context just because you went back to fix a typo
- 📍 'Use current location' button on the New Dream form's Location field. Tap it, approve the browser permission, and we reverse-geocode your coordinates via Nominatim into a clean 'City, State' (US) or 'City, Country' label and drop it into the field. Handles permission-denied / position-unavailable / timeout with inline messages. Auto-expands the influencers panel so you can see what got filled in
- 🔁 New /api/geocode/reverse endpoint (auth-gated, 30/hr/user rate limit) wraps Nominatim's reverse lookup and returns the short label. Same User-Agent + 1-req/s discipline as the existing forward geocoder
- 📈 Trending page now surfaces 'Your personal dream patterns & trends' at the top — same card design as the profile shortcut, gated on signed-in users so signed-out visitors don't see a dead link to /patterns
- 🚪 Dream detail page CTA flips for signed-in viewers: instead of 'Join DreamKeg →' (a pitch aimed at signed-out OG-card visitors), authenticated users now see 'Continue to Feed →' linking back to /feed
v1.33.1May 17, 2026
Remove GitHub sign-in
auth
- 🧹 Dropped the 'Continue with GitHub' option from /login. Facebook + Discord now cover the social-graph audiences we care about; GitHub is a leftover from the early Supabase scaffolding and not a natural fit for a dream-journal audience
- 📜 Privacy Policy and /data-deletion updated to drop GitHub from the enumerated sign-in providers
v1.33.0May 17, 2026
Sign in with Facebook + Discord
authfeature
- 🔐 Added Facebook and Discord as OAuth sign-in / sign-up providers on /login alongside the existing Google and GitHub buttons. Both routed through Supabase Auth — same /auth/callback exchange flow, same welcome-flag detection, same invite-token forwarding
- 📜 Privacy Policy updated to enumerate exactly what we receive from each provider (FB: public_profile + email only; Discord: identify + email only — no friends, no posts, no messages, no servers). Required for FB app review
- 🗑️ New /data-deletion page with explicit instructions for requesting account deletion, including FB- and Discord-specific callouts. Linked from the landing-page footer and added to the sitemap — satisfies Facebook's User Data Deletion URL requirement
- ✅ Domain verification meta tag for Facebook Business Manager wired into the SSR head via Next's metadata API (must be static, not JS-injected, or FB's scraper misses it)
v1.32.2May 17, 2026
Cleanup: mobile menu scroll, comments on dream page, globe dots reliability
mobileuxfeature
- 📱 Mobile drawer menu now scrolls inside itself. On shorter phones the nav was previously cut off at the bottom — How It Works / Sign Out were unreachable. Added overflow-y + touch scrolling to the sidebar container
- 💬 Dream detail pages now render the full comments thread (avatar, name, timestamp, body) under the dream. Previously the page only showed a 💬 count and notification clicks landed users on a dead-end with no way to see what the comment actually was
- 🔔 Comment notifications now pass ?focus=comments to the dream page, which auto-scrolls the new comments section into view on landing. The 💬 stats badge is also a jump anchor
- 🌍 Globe dots that started on the far hemisphere were being created as empty SVG groups — the inner circle/label elements were never appended, so rotating those dots into view did nothing. World's Trending appeared empty on first load (default rotation faces central Asia, American dots were hidden) and Dream Locations dropped dots in regions that weren't front-facing initially. Every dot now gets its geometry appended unconditionally; only the wrapper's display is toggled by rotation
v1.32.1May 17, 2026
Sidebar icons — full brand color
designsidebar
- 🎨 The 12 sidebar nav icons now carry their own signature color from the cosmic palette instead of all reading violet. Dream Feed = violet, New Dream = cyan moon + amber spark, Notifications = amber, Profile = rose, Explore Globe = sky cyan, Trending = orange, Import = teal, Definitions = violet, Settings = cool gray, How It Works = cyan, Sign Out = red. The sidebar reads as a constellation of jewels rather than a column of monochrome glyphs
- ✨ Dream Matches specifically: each of the 5 stars in the constellation gets a different palette hue (violet / rose / cyan / orange / green) — multi-colored on purpose, since the icon represents many kindred dreamers connecting
- 🪨 Geometry is unchanged — same Duotone silhouettes shipped in 1.32.0. Active vs inactive state still comes from the button background + border, not the icon color, so brand color stays consistent whether or not the page is selected
v1.32.0May 17, 2026
Sidebar icons — custom cosmic SVG set
designsidebar
- 🌙 The 12 sidebar nav icons are now custom-drawn SVGs in a unified duotone style (filled silhouette at 30% + crisp 1.8 stroke at 100%), replacing the previous mix of unicode glyphs and emoji that rendered inconsistently across platforms. All inherit currentColor so the violet active / muted inactive states come through cleanly
- ☁️ Dream Feed = single cloud silhouette. New Dream = crescent moon with one sparkle. My Profile reuses the Dream Feed cloud as the head shape (sitting over a torso curve) so Feed + Profile share the same visual language
- ✨ Dream Matches = a constellation of 5 connected star nodes — the previous Venn-circle icon was too sedate for what's a flagship feature. The new one reads as 'kindred dreamers, plural' and feels distinctly cosmic
- 📈 Trending = a chunky upward arrow. Settings, Notifications, Explore Globe, Definitions, Import, How It Works, Sign Out all redesigned to match the duotone language at 20px (previous set was 18px and felt thin against the cosmic backdrop)
- 🔍 Dev preview gallery at /icon-preview (404s in production) lets future iterations compare design directions side-by-side with a live sidebar mockup. Used to triage 5 candidates for Dream Matches before locking in the constellation
v1.31.2May 17, 2026
Trending Dreams sidebar — click to open in a modal
feedtrendingux
- 🪟 Clicking a card in the /feed sidebar's Trending Dreams widget now pops the full dream up in a center-screen modal — no more hunting for it in the feed list. Backdrop click or Escape closes
- 🧩 The modal renders the same DreamCard the feed uses, always expanded, with vote / follow / comment / report controls fully wired. Owners get edit + delete inside the modal too, and a successful delete dismisses it automatically
- 📜 Background scrolling locks while the modal is open so the page underneath doesn't drift. Clicking a username inside the modal closes it and navigates to that profile
v1.31.1May 17, 2026
Feed sidebar trending: theme emojis on tags, banner art on dreams
feedtrendingdesign
- ✨ The /feed sidebar's 'Trending Tags' pills now lead with the same emoji icon used on the /trending page Trending Dream Themes list (🥂 socializing, 👨👩👧 family, ✈️ travel, 🤝 friendship, 💼 work, 🚶 walking, 🎮 gaming, 🎉 party, etc.) — a lot more life in the widget than bare hashtags
- 🖼️ The /feed sidebar's 'Trending Dreams' cards now show a small dream banner / AI video poster behind the title + author line, with a dark scrim for readability. Falls back to the cosmic gradient palette when a dream has no media — same approach we use on /trending Top Dreams, just sized down for the sidebar
- 🔧 Extracted the theme→emoji map to module scope (THEME_EMOJI / themeEmoji helper) so the feed sidebar and /trending page draw from the same source of truth. Added ~25 entries for common social/lifestyle/travel themes that were falling through to the ✦ fallback
- ✦ Rendered-AI-video dreams in the sidebar get a tiny ✦ pill in the corner so they're recognisable at a glance
v1.31.0May 16, 2026
Real-data trending sidebar + banner art on /trending Top Dreams
feedtrendingdata
- 🪄 The Dream Feed sidebar's three trending widgets — Trending Accounts, Trending Tags, Trending Dreams — are now backed by real data. No more Shaquille O'Neal / Billie Eilish / 'Flying Over Tokyo' placeholders
- ⭐ Trending Accounts pulls live from /api/trending/users?kind=top_dreamers — clicks navigate to the dreamer's profile and the Follow / Following button is wired to the same follow API the rest of the app uses
- 📈 Trending Tags is computed in-browser from the public feed across themes / emotions / activities, top 8 by occurrence. Counts shorten cleanly (1.2k → 12k) and the widget hides itself entirely when there isn't enough data yet
- 🔥 Trending Dreams shows the top 4 dreams from the visible feed sorted by likes (recency breaks ties). Clicking expands the dream in the main feed
- 🖼️ /trending Top Dreams cards now use each dream's rendered AI video poster or banner image as the hero background, with a top-to-bottom dark scrim so the title / username / heart count stay readable. Falls back to the original cosmic gradient when no media exists. Rendered-video dreams get a small ✦ RENDERED pill in the top-right
- 🧹 Removed the TRENDING_ACCTS / TRENDING_TAGS / TRENDING_FEED_DREAMS demo constants from DreamKegApp.tsx — they were a launch-readiness liability sitting in production
v1.30.0May 16, 2026
🎉 Pattern overlay LIVE for all visitors
designlaunch
- 🚀 After 26 iterations, the dream-card pattern overlay graduates from `?patterns=1` opt-in to default-on for every visitor. Each dream gets one of 5 designer-drawn vector tiles (Switzerland flowing waves / Belgium damask / France diagonal hatching / Korea organic textures / South Africa chevron), picked deterministically from its UUID hash so the assignment is stable forever
- ✨ Rendering: V B 200×200 single-motif vector SVGs, stretched edge-to-edge across each card via CSS mask-image at 6% opacity. Crisp lines at any size, resizes cleanly when 'read full dream' expands the card, works the same on desktop and mobile. Total wire cost ~108 KB combined (browser caches all 5 after first load)
- 🎨 Tinted per-dream from the cosmic palette (violet/cyan/rose/amber/green) so the texture harmonises with each card's glow halo rather than fighting it
- 🚪 Opt-out for debugging: `?patterns=0` in URL or `dk_patterns=0` in localStorage. Default is ON
v1.29.26-experimentalMay 16, 2026
Pattern overlay: opacity 7% → 6%
designexperimental
- 🪶 Dropped pattern overlay opacity one more notch, 7% → 6%. Reads as a barely-there texture now
v1.29.25-experimentalMay 16, 2026
Pattern overlay: opacity 8% → 7%
designexperimental
- 🪶 Lowered pattern overlay opacity from 8% to 7%. The V B vector tiles read crisply at 8% but were just slightly busier than they needed to be — 7% keeps the design legible while leaving more breathing room for banner art and dream text
v1.29.24-experimentalMay 16, 2026
Pattern overlay: all 5 V B vector tiles live (Switzerland, Belgium, France, Korea, South Africa)
designexperimental
- 🎉 The Switzerland V B vector tile felt right on every screen size, so we extended the same treatment to the other 4 countries. All 5 are now pulled from designer V B (commit 6593c46) — single 200×200 motif tiles, vector-crisp at any size
- 🌍 Live rotation now includes: Switzerland (flowing waves), Belgium (ornate damask), France (diagonal hatching), Korea (organic painterly textures), South Africa (chevron / zigzag). Each dream gets one deterministically picked from its id hash, so the assignment is stable across navigations
- 📦 Tile sizes gzipped: switzerland 17 KB, belgium 25 KB, france 21 KB, korea 18 KB, southafrica 27 KB. All under 30 KB on the wire each
- 🛠 DreamCloud's inner pattern layer now uses `${pattern}-tile.svg` so any of the 5 names work. preserveAspectRatio=none + width/height=100% on each SVG root + mask-size: 100% 100% stretches the 200×200 viewBox to fill the entire card. Cache-buster ?v=10
- 🔎 The /css-patterns preview page now shows all 5 V B tiles under a green 'LIVE' header so you can see what's actually deployed
v1.29.23-experimentalMay 16, 2026
Pattern overlay: vector V B Switzerland tile — crisp lines
designexperimental
- 🔍 v1.29.22's PNG tile looked low quality on desktop because we were upscaling a 200×200 bitmap ~6.5× to fill wider cards. Every line went visibly fuzzy
- 💎 Pulled the designer's Version B Switzerland tile from git history (commit 6593c46) — V B was specifically designed as a 200×200 single tile (one complete wave motif per file). 46 KB raw / 17 KB gzipped, 209 paths. Vector means infinitely crisp lines no matter how much we stretch it across the card
- 📐 DreamCloud now uses switzerland-tile.svg via mask-size: 100% 100% (added preserveAspectRatio=none + width/height=100% so the stretch actually takes effect). The 200×200 viewBox stretches across the entire card width and height, exactly one motif per card
- 💰 Trade-off: +8 KB on the wire vs the rasterized PNG, but lines stay sharp at any zoom level. Cache-buster ?v=9
v1.29.22-experimentalMay 16, 2026
Pattern overlay: ONE motif, full card width (Switzerland tile)
designexperimental
- 🎯 Back to basics: ONE pattern graphic filling the entire card. Cropped a single 200×200 wave cell out of the Switzerland artwork (the original PNG was a 2×6 grid which is why cards kept showing two patterns side-by-side) and saved as switzerland-tile.png at 8.7 KB
- 📐 Inner pattern layer in DreamCloud now uses `mask-size: 100% 100%` to stretch this one tile edge-to-edge across the entire card width and height — no duplication, no vertical overflow, no tiling. The wave motif distorts slightly to match the card aspect ratio, but that's the trade-off for 'one pattern fills the whole card'
- 🇨🇭 DREAM_PATTERN_ROTATION locked to ['switzerland'] only. Live site at ?patterns=1 now shows a single Switzerland wave motif per card. Cache-buster ?v=8
- 📦 File size summary: 8.7 KB for the live tile, vs 812 KB for the original SVG (~93× smaller). The motif was already in the rasterized 46 KB switzerland.png — just extracted the top-left cell
v1.29.21-experimentalMay 12, 2026
Pattern overlay: EXACT designer art via rasterized PNG-8 masks
designexperimental
- 💡 Realisation: 'recreate exactly in CSS' isn't possible with hand-drawn artwork — the Switzerland SVG has 4080 paths, France has 984. No combination of CSS gradients can replicate that. But you can rasterize the SVG to a small PNG-8 with palette compression and use it as a CSS mask-image — pixel-faithful, ~20× smaller
- 🛠 New build script scripts/rasterize-patterns.js uses sharp to render all 5 designer SVGs to 400px-wide PNG-8 with 8-colour palette. Results: switzerland 812 KB → 46 KB (5.6%), france 825 KB → 35 KB (4.3%), belgium 187 KB → 47 KB, korea 650 KB → 5 KB, southafrica 315 KB → 35 KB
- ✨ Added #16 (Switzerland exact) and #17 (France exact) to /css-patterns. Now visible as the EXACT designer artwork — Switzerland's flowing hand-drawn waves and France's diagonal hatching — at a fraction of the byte cost. CSS still handles tint (via backgroundColor + mask-image), opacity, and stretch
- 📌 New 'EXACT designer art' jump pill at top of /css-patterns lands you on #16–17 immediately so you can compare against the geometric (#1–10) and organic (#11–15) attempts
v1.29.20-experimentalMay 7, 2026
Pattern overlay: 5 organic / random CSS candidates (#11–15)
designexperimental
- 🎨 Added 5 new CSS pattern candidates to /css-patterns that lean hard into asymmetry and hand-drawn shape language — the first 10 read as too uniform / wallpaper-y. These try to recreate the 'excitement & randomness' that the designer's Switzerland SVG had, but in <1 KB of inline SVG each
- ✏️ #11 Ink scatter (25 dots, varied sizes, irregular positions). #12 Organic blobs (10 elongated ovals at random angles). #13 Flowing brushstrokes (6 curved horizontal strokes). #14 Sketchbook mark-making (mix of dots, slashes, tiny curves — busiest). #15 Crystalline shards (12 irregular polygon outlines, stained-glass)
- 🔗 Added a 'Jump to organic candidates' shortcut at the top of /css-patterns so they're easy to find below the original 10 geometric ones
v1.29.19-experimentalMay 7, 2026
Pattern overlay: 10 CSS-only candidates at /css-patterns
designexperimental
- 🧪 Pivoting from designer SVGs to pure-CSS patterns. The artwork SVGs (150–670 KB each) look beautiful up close but at 8% opacity over busy cards they read as undifferentiated noise — paying a lot of bytes for texture that geometric CSS does as well or better
- 🎨 New preview page at /css-patterns shows 10 candidates side-by-side on real DreamCloud-shaped cards over the cosmic background: dots-tight, dots-loose, diagonal pinstripes, vertical pinstripes, crosshatch, concentric ripples, topographic waves, hex mesh, plus sparkles, diamond lattice
- ⚙️ Live opacity slider (4–25%) and tint picker (violet/cyan/rose/amber/green) so you can dial in each pattern at the right intensity and colour. All patterns are tint-aware via a build(tint) function and stay deterministic per dream
- 📦 New module at src/lib/cssPatterns.ts. Each pattern is 1–6 lines of CSS. Most use pure gradients (zero bytes); 3 use sub-500-byte inline SVG data URIs for shapes CSS gradients can't easily express (topo waves, hex mesh, plus sparkles)
v1.29.18-experimentalMay 7, 2026
Pattern overlay: try France with single-panel natural aspect
designexperimental
- 🇫🇷 Swapped Switzerland → France in the rotation. France's pattern is more symmetrical so the centre-axis seams may be less visible without needing the 2×2 mirror-tile trick (which made the previous iteration read as 'pretty good but too kaleidoscope-y')
- 📐 Reverted DreamCloud to the v1.29.16 single-panel natural-aspect approach: `mask-size: 100% auto` + `mask-position: top center`. The SVG fills card width with its natural 1:3 portrait ratio; vertical overflow is clipped by the outer wrapper
- 🛠 Restored france.svg root to its natural V C form (removed the width/height/preserveAspectRatio additions from v1.29.15). Cache-buster bumped to ?v=7
- 💭 Open question for next iteration: if neither artwork-based approach lands, we have a much cheaper option — generate a simple pattern with CSS-only tricks (repeating linear/conic gradients, inline SVG `<pattern>`, or a small data-URI tile). Zero asset cost, full control over scale and density
v1.29.17-experimentalMay 7, 2026
Pattern overlay: 2×2 mirror-tiled quadrants hide the centre-axis seams
designexperimental
- 🔁 v1.29.16 filled the width correctly but read as 4 visible blocks with seams along the card's centre axes — the artwork doesn't tile naturally. Fix: render the same Switzerland mask 4 times in a 2×2 grid and mirror-flip alternating cells (TR horizontal, BL vertical, BR both). The classic seamless-tiling trick — each cell's centre-axis edge is the mirror image of the adjacent cell's edge, so they always meet pixel-for-pixel regardless of what the artwork does at the SVG boundary
- 🛠 Re-added preserveAspectRatio='none' + width/height=100% to switzerland.svg so each quadrant's `mask-size: 100% 100%` actually stretches the SVG (without those attributes the browser preserves the viewBox's 1:3 ratio when the SVG is loaded as an external CSS mask). Cache-buster bumped to ?v=6
v1.29.16-experimentalMay 7, 2026
Pattern overlay: one pattern, natural aspect — Switzerland V C only
designexperimental
- 🎯 Simplified to one-pattern-only mode (Switzerland V C) to dial in a single design before re-introducing the other four countries. Easier to iterate when there's just one knob to turn
- 📐 Strategy change: fill card width 100%, let the SVG keep its natural 1:3 portrait aspect ratio (no more `mask-size: 100% 100%` distortion attempts). On a wide feed card the SVG extends below the visible area and is clipped by the outer wrapper's overflow:hidden; on an expanded 'read full dream' card more of the pattern shows. Because V C is uniformly distributed across its canvas, any vertical slice the user sees looks consistent
- 🧹 Restored switzerland.svg root to its original V C form (removed the width=100% height=100% preserveAspectRatio=none additions from v1.29.14–15 — they were the wrong fix for the wrong assumption). Bumped cache-buster to ?v=5
v1.29.15-experimentalMay 7, 2026
Pattern overlay: width=100% height=100% on root SVG — actually fills now
designexperimental
- 🐛 v1.29.14 wasn't enough: `preserveAspectRatio='none'` on the SVG root is ignored when the file is loaded as an external CSS `mask-image`. Browsers compute the SVG's intrinsic aspect ratio from the viewBox (1:3 portrait here) before mask-size kicks in, so the pattern still rendered as a centered ~133px-wide strip on wide cards
- ✅ Patched all 5 V C SVGs to additionally set `width='100%' height='100%'` on the root <svg> tag. That removes the intrinsic aspect ratio so `mask-size: 100% 100%` truly stretches the artwork edge-to-edge
- 🧹 Added a `?v=4` cache-buster to the mask URL so any stale copies cached at Vercel/CDN/browser layers get re-fetched on the next visit
v1.29.14-experimentalMay 7, 2026
Pattern overlay: preserveAspectRatio=none on V C — finally fills the card
designexperimental
- 🔑 Found the actual root cause of the 'thin strip in the middle' problem: it was never the artwork distribution. The V C SVGs have viewBox 400×1200 (1:3 portrait). Without `preserveAspectRatio='none'` on the root <svg> tag, the browser preserves that aspect ratio when rendering as a CSS mask — fitting to height and centering with empty space on the sides — even though we asked for `mask-size: 100% 100%`
- ✅ Post-processed all 5 V C files to add `preserveAspectRatio='none'`. Pattern now actually stretches to fill the entire card on every viewport. Combined with V C's uniform paint distribution, this gives the full-card wallpaper texture we've been chasing across 13+ iterations
v1.29.13-experimentalMay 7, 2026
Pattern overlay: Version C — uniform paint distribution
designexperimental
- 🎨 Designer shipped Version C of all 5 patterns (Switzerland, France, Belgium, Korea, South Africa) with the artwork redistributed uniformly across the entire 400×1200 canvas — no more clustering in jersey-specific bands. Distribution analysis confirms: Korea and South Africa within 1% spread top-to-bottom, others within 5–9%. Single-panel stretch should now fill the entire card with consistent texture, fixing the 'thin strip in the middle' problem
- 📦 V C files are 10–14× larger in path data than V A (Switzerland V C is 831KB vs V A's 59KB) — much more pattern detail per pattern, but still trivial download size
v1.29.12-experimentalMay 6, 2026
Pattern overlay: revert above-content (z-index 1) — awaiting V C
designexperimental
- ↩️ Reverted z-index 3 → 1 so pattern renders behind banner and dream text again. Above-content rendering tinted the banner art too much. Holding here while the designer prepares Version C: square tiles with the artwork redistributed to fill the canvas uniformly (current V B has art clustered in jersey-design bands, leaving empty zones when stretched as a single panel)
v1.29.11-experimentalMay 6, 2026
Pattern overlay: render above content for full-card coverage
designexperimental
- 🔼 Bumped pattern layer z-index from 1 → 3 so it renders ABOVE the banner image, dream text, and action bar instead of behind them. Pattern was already stretched to fill the full card, but the banner image (top ~40%) was hiding it. Now reads as a translucent surface texture across the entire card. Trade-off: pattern very faintly tints the banner image and dream text
v1.29.10-experimentalMay 6, 2026
Pattern overlay: V B single-panel stretch, 8% opacity
designexperimental
- 🔍 Diagnosed why the V A stretch only showed a thin pattern band on desktop: V A SVGs are laid out like soccer jerseys with art concentrated in specific vertical bands and empty space elsewhere (Switzerland V A has 73% of art in the bottom third). When stretched, only the dense band paints and the empty zones leave the card plain
- 🔁 Switched to V B SVGs (200×200 seamless tile crops) as the single-panel source. Square aspect means the stretch to landscape desktop cards is much less extreme, and V B paint distribution is mostly uniform (Southafrica V B is fully uniform; Switzerland V B has the most asymmetry but still way less than V A)
- 🌫 Bumped opacity 6% → 8% per request
v1.29.9-experimentalMay 6, 2026
Pattern overlay: back to single-panel stretch (V A SVGs, 6%)
designexperimental
- 🖼 Switched back to Version A SVGs (400×1200 portrait crops) stretched edge-to-edge with `mask-size: 100% 100%` + `no-repeat`. No tile boundaries means no seams. Pattern geometry warps to card aspect ratio, but at 6% opacity it reads as a faint texture so the distortion is acceptable
- 🧹 Removed the dual-mask seam-bridge from the previous attempt — not needed when there's only one panel
v1.29.8-experimentalMay 6, 2026
Pattern overlay: dual-mask offset bridges tile seams, opacity 6%
designexperimental
- 🩹 Layered a second copy of the pattern mask offset by half a tile (200px, 200px). Where the first layer's tile edges had an empty hairline strip (the SVG path data doesn't reach the viewBox edges), the second layer's tile centers cover those strips. CSS unions the two masks (`mask-composite: add`) and the seams disappear
- 🌫 Dropped opacity 8% → 6% per request
v1.29.7-experimentalMay 6, 2026
Pattern overlay: revert to Version B tiles, opacity 8%
designexperimental
- ↩️ Reverted from the single-panel stretch (V A SVGs) back to the seamless 400px tiles (V B SVGs, `mask-repeat: round`). Tiny hairline gaps were preferred over the cross-device geometry distortion the stretch caused
- 🌫 Dropped opacity 10% → 8% so the pattern reads as a faint background texture rather than a foreground element
v1.29.5-experimentalMay 6, 2026
Pattern overlay: close hairline tile seams
designexperimental
- 🪡 Switched mask-repeat from `repeat` to `round`. The browser now snaps tile size so a whole number fits edge-to-edge, eliminating the 1px sub-pixel hairline gaps that appeared between adjacent tiles when 400px didn't divide cleanly into the card width
v1.29.4-experimentalMay 6, 2026
Pattern overlay: 2× tile size for legibility
designexperimental
- 🔍 Doubled the tile size from 200px → 400px. The line work in Switzerland and Korea was reading as fine noise at 200px; at 400px each pattern's character is visible. Density drops from ~4×2 tiles per desktop card to ~2×1, which feels more intentional
v1.29.3-experimentalMay 6, 2026
Pattern overlay V2: seamless 200×200 tiles, identical fit on every device
designexperimental
- 🧩 Designer re-exported all 5 patterns (Switzerland, France, Belgium, Korea, South Africa) as seamless 200×200 square tiles instead of the original portrait jersey canvases. Files are 25–50% smaller across the board
- 🪄 Replaced the rotation + 480% zoom + inset:-50% workaround with a clean three-line `mask-repeat: repeat` at a fixed 200px tile size. Pattern density is now identical on phone, tablet, desktop, and any card aspect ratio — no more mobile-vs-desktop fork
- 🧹 Dropped ~30 lines of CSS hacks and explanatory comments from <DreamCloud>
v1.29.2-experimentalMay 3, 2026
Pattern overlay desktop fit + 10% opacity
designexperimental
- 🖥 Bumped pattern-layer inset from -30% to -50% so the rotated layer overhangs the wrapper enough to cover wide desktop cards (1.7:1 aspect). Mobile worked at -30% by luck — mobile cards are roughly square, desktop cards needed more headroom
- 🌫 Dropped opacity from 15% → 10% so it no longer fights with body text
v1.29.1-experimentalMay 3, 2026
Pattern overlay polish: full-card fit, 5 patterns, 15% opacity
designexperimental
- 🌍 Added South Africa (5th pattern) and replaced all 5 SVGs with the designer's uniform black-100% exports. Pattern rotation now: Switzerland (violet) / France (cyan) / Belgium (rose) / Korea (amber) / South Africa (green)
- ↔️ Rotated patterns -90° and stretched mask-size to 100%×100% so the line work runs horizontally across the full card width and fills top-to-bottom, instead of appearing as a thin vertical column from the original portrait jersey canvas
- 🌫 Dropped opacity to 15% (down from 18%) — visible-but-subtle texture across the whole card
v1.29.0-experimentalMay 3, 2026
Decorative line-pattern overlay for dream cards (dev flag)
designexperimental
- 🎨 Added an opt-in decorative line-pattern overlay layer to <DreamCloud>. Each card gets one of 4 country-themed line patterns (Switzerland, France, Belgium, Korea) picked deterministically from hash(dream.id), so a single dream's pattern stays stable across navigations but a feed of cards looks varied
- 🔌 Behind a dev flag for now — append ?patterns=1 to any feed URL or set localStorage 'dk_patterns'='1'. Doesn't ship to anyone who doesn't opt in
- 🖌 Patterns render via CSS mask-image (alpha-only) so the source colour in each SVG file is irrelevant — we tint per-pattern at the layer level (violet/cyan/rose/amber). When the designer ships uniform black-100% versions of the remaining files, no code change is needed
- 🐛 Fixed two subtle bugs found while wiring this up: pattern wrapper had zIndex 1.5 (invalid CSS, fell back to auto, hid the layer behind content) and the prior Belgium SVG had opacity:0.05 baked in (would've made it nearly invisible as a mask). Z-index now 1; Belgium replaced with the new black-100% export
v1.28.3May 3, 2026
Person-tag popup correctly reflects follow state
feedfollows
- 🐛 Tapping a linked @-mention (e.g. @James → James Carson) now correctly shows 'Following' when you already follow that user. Before, the popup always showed 'Follow' if the linked user happened to not author any of the dreams currently loaded in the feed — `userFollows` was only seeded from feed authors. Now we probe `/api/follows` for the linked user on demand and merge the result in
v1.28.2May 3, 2026
Linked people popup + profile aggregation fixes
taggingfeedprofile
- 👤 Profile 'People In Your Dreams' rows now aggregate generic words (mom, dad, sister, etc.) into the linked person they belong to, when the user has a definition tying them together. So '@Laurie Carson — mom' now shows up as 'Laurie Carson / mom / mother' with the dreams from all three tags counted toward the same row
- 🐛 /api/definitions/lookup no longer crashes when legacy data has case-pair duplicates (e.g. both 'Dad' and 'dad' rows). It now returns the row with linked_user_id when present, falling back to any match. This was the root cause of the '@dad — Not linked to a DreamKeg user yet' popup that some users saw even though their dad → Bill Carson definition existed
- 🧹 Cleaned up 13 legacy case-pair duplicate definitions on joewcarson's account (Dad/dad, James/james, John/john, Jul/jul, Farrell/farrell, Leface/leface, Trigo/trigo, Ginger/ginger, Demarco/demarco/DeMarco, McNamee's/Mcnamee's, Tay/tay, Justin/justin). Kept the linked row in each group; deleted the no-link duplicates
v1.28.1May 3, 2026
Linked people-tags now render as @-mentions
taggingfeed
- ✨ When a dream's author has defined a generic people tag (e.g. `dad`, `mom`, `sister`) and linked it to a real DreamKeg user account, the inline render now treats it as a clickable @-mention instead of a plain coloured placeholder. So `dad → Bill Carson` shows up in dream text as @-rainbow, and tapping it opens Bill's link card
- 🛠 Dreams API (`GET /api/dreams`, `/api/dreams/search`, `/api/dreams/featured`) now attaches a per-author `linkedPeople` array — just the lowercase tag words that map to a real account. No PII / no `meaning` is exposed across users; this is the minimum needed for the highlighter to know which generic words to elevate
v1.28.0May 3, 2026
Feed UX cleanup: search popup, smarter notifications, inline-tag fixes
uxfeedtagging
- 🔍 Search bar collapsed into a single icon button in the Dream Feed header. Clicking it opens a glass-modal popup with the existing input + filter UI; the bulky persistent search row is gone. Active-search state is indicated by a result-count badge on the icon
- 🔔 Notifications widget on /feed now only renders when there is at least one UNREAD notification (read-only feeds no longer pin a stale 'joined DreamKeg!' panel to every visit). Added a ✕ button so the user can dismiss the panel for the session
- ✨ Inline tag highlighter now expands multi-word people tags to also match their first-name surface form. Fixes the long-standing bug where a user with `definitions` like `Seth → Seth Francus` saw `Seth Francus` stored as the tag, but only `Seth` in their dream text — so the inline @-mention failed to render. Same fix covers `Julia / Julia Carson` and any other first-name → full-name definition pair
- 🛡 Highlighter now ALSO suppresses the @-rainbow treatment whenever a 'people' tag's surface form appears in a non-person category (places/objects/etc) on the same dream. Locations like `@Northport` no longer get rendered as if they were a person — they fall back to the places palette
- 🤖 Tagger prompt updated: an `@` prefix in the dream text is no longer treated as evidence that a noun is a person. Users colloquially write `@Northport` to mean 'at Northport' (a place), and the tagger now classifies based on what the noun actually is
- 🧹 Cleaned up one historical mis-tag in the database — bare `Northport` was tagged as both `people` and `places` on one dream; the duplicate `people` row was deleted
v1.27.0May 2, 2026
Meta Pixel + ad-formats export script (pre-launch ads infra)
marketingtooling
- 📊 Meta Pixel base code installed in layout.tsx, gated behind NEXT_PUBLIC_META_PIXEL_ID so dev / preview builds don't ship a stub. PageView fires automatically on every route change. <noscript> img fallback included for users with JS disabled
- 🎯 New trackPixel() helper in src/lib/meta-pixel.ts — type-safe wrapper around fbq('track') so any client component can fire conversion events without touching window.fbq directly
- 🆕 New <MetaPixelEvents> client component mounted in layout.tsx — watches the URL on first mount for ?welcome=1 and fires Meta's standard CompleteRegistration event exactly once per fresh signup, then strips the flag so refreshes don't double-count
- 🔁 auth/callback route now detects fresh signups by checking whether the user's profile.created_at is < 60 seconds old, and appends ?welcome=1 to the redirect when true. Combined with <MetaPixelEvents> this gives Meta Ads accurate signup attribution without needing the Conversions API yet
- 🎬 New scripts/export-ad-formats.sh — batch-exports every dream video to four Meta-ad sizes (1080×1920 vertical + 1080×1080 square, each in blurred-pillarbox + center-crop variants) using ffmpeg with libx264 / crf 20 / faststart. Skips outputs that already exist so it's safe to re-run after adding new dreams
v1.26.0May 2, 2026
Security hardening — title caps, profile sanitisation, edit rate limits
security
- 🛡 Dream titles now capped at 200 characters and run through sanitizeShortText (strips HTML + control chars) on both POST and PATCH /api/dreams. Closes a paste-bomb / XSS-defence-in-depth gap
- 🛡 Influencer fields (location / time-of-day / food-drink / substances / sleep-quality) sanitised + capped at 200 chars on dream submit
- 🛡 Profile name + bio + location are now HTML-stripped and control-char-stripped on PATCH /api/profile (was previously trim-only). Bio uses a multi-line variant that preserves paragraph breaks; name/location use the single-line variant
- 🛡 Rate limit added to PATCH /api/dreams (30/hour per user) — closes the AI re-tag abuse vector that could have been used to spike Sonnet costs by spamming edits
- 🛡 Rate limit added to PATCH /api/profile (30/hour per user)
- Pre-existing protections confirmed in place across every dream-input endpoint: 10,000-char body cap, sanitizeDreamText (HTML + control + whitespace), Claude-Haiku content moderation (rejects spam / hate / non-dream content), and per-user rate limits on POST /api/dreams (20/hr), comments (30/hr), import (5/hr), reports (10/hr), votes (120/hr)
v1.25.0May 2, 2026
Programmatic SEO — 2,300+ dream-symbol pages + long-form journal guide
seofeaturebranding
- 📖 New long-form pillar page at /how-to-keep-a-dream-journal — ~1,500 words covering why dream journals work, how to start one, what to write down, how to remember more dreams, finding patterns over time, and common mistakes. Article + BreadcrumbList JSON-LD, 6-question on-page FAQ, internal links back to feed and signup. Targets the high-intent 'how to keep a dream journal' query family
- 🔮 New programmatic route /dream-symbol/[tag] — every tag in the dream-tag database with at least 3 public dreams gets its own evergreen page. Each shows 6 real dream excerpts, related tags that co-occur, category breakdown, and a CTA to log your own dream. Article + BreadcrumbList schema per page. 2,317 such pages live as of launch (water, flying, falling, school, family, death, etc.) — each targets a unique long-tail query like 'dreams about [tag]'
- 🗺 Sitemap.xml now includes the journal guide + every dream-symbol page above the 3-public-dream threshold + every public dream + the static routes. Total ~3,300 URLs ready for Google to crawl
- 🔁 Tags-per-public-dream aggregation in sitemap.ts now paginates through dream_tags 1,000 rows at a time and joins client-side against the public-dreams set. Previous IN-filter approach blew past PostgREST's URL-length cap and silently returned zero rows
v1.24.0May 2, 2026
SEO markup pass — landing page targets dream-journal search queries
seobranding
- 🔍 Landing page meta title now: 'DreamKeg — Free Dream Journal & AI Dream Tracker'. Description and keywords expanded to target the high-intent dream-journalling search space (dream journal, dream logging, dream tracker, write down my dreams, track my dreams, free dream journal, AI dream journal, dream patterns, recurring dreams, lucid dreaming)
- 🤖 Schema.org graph expanded from {WebSite, Organization} → {WebSite, Organization, SoftwareApplication, FAQPage}. SoftwareApplication tells Google this is a free LifestyleApplication / Dream Journal — unlocks the 'App' rich-result treatment. FAQPage covers six common dream-journalling questions and gives us a chance at featured snippets
- ❓ On-page FAQ section added below the feature grid that mirrors the FAQPage JSON-LD verbatim (Google rewards FAQs whose markup matches the rendered content). Six questions: what is a dream journal, how do I write down my dreams, why should I track my dreams, is DreamKeg free, are my dreams private, can DreamKeg interpret my dreams
- 📝 Hero copy sharpened — H2 is now 'The free dream journal that tracks your dreams' and the subhead leads with 'Write down your dreams, and AI auto-tags every person, place, emotion, and symbol' so crawlers see the function in plain language above the fold
- 🔗 Keyword-rich internal-link block added to the landing footer — 'Public dream feed', 'Online dream journal', 'Track your dreams', 'AI dream tagging', 'Lucid dreaming community' all link to /feed
- 📑 Title template added to layout.tsx so per-page titles format as '%s | DreamKeg'
v1.23.0May 2, 2026
Pre-launch polish: generic people tags, OG sharing, dream-detail cosmic, friendlier empty state
polishbrandingseo
- 👥 Generic / non-specific people tags (everyone, hippies, some of us, kids, coach, goalie, mom, dad, etc) no longer render with an @ prefix or a click handler — they're still tagged as 'people' for analytics, but they can never link to a real account so they now appear as plain coloured tags instead. Full list lives at module scope as GENERIC_PEOPLE_TAGS so it's easy to extend as we observe real user data
- 📸 Dream-detail page OG image priority now: video poster → AI banner → site default. Previously only used the AI banner, so video-rendered dreams were sharing the static fallback. URLs are now absolute (with explicit https://dreamkeg.com prefix) so they survive every social-platform cache and CDN intermediary
- 🌌 Dream-detail page background made transparent so the global cosmic background shows through. Removed the page's local 15-particle .star-particle field that was redundant with the cosmic starfield — same fix that we already applied to the feed in 1.22.5
- ♡ Friendlier 'Following' empty state — copy now reads 'Your following feed is quiet — you haven't followed anyone yet, browse public dreams and tap a dreamer's avatar to follow,' with a 'Browse all dreams →' button that switches the tab back to All Dreams
v1.22.5May 2, 2026
Cosmic background now visible on mobile (and behind every page)
fixmobilebranding
- 🌌 The global <CosmicBackground/> with its starfield + nebula drift + shooting stars was being completely covered by the DreamKegApp's outer wrapper, which had its own opaque dark gradient. The wrapper's background is now transparent so the cosmic atmosphere shows through behind every page — most noticeably on mobile, where the dark gradient was hiding everything
v1.22.4May 2, 2026
Tighter bottom-left corner so upvote arrow doesn't clip
polish
- 🌥 Bottom-left corner of every Drift sub-path tightened — the curve now hugs the corner to (x=4, y=580) before going up the left edge, instead of dipping inward toward (x=6, y=580) earlier in the path. Result: the upvote arrow at the bottom-left of each card sits safely inside the silhouette
v1.22.3May 2, 2026
Drift silhouettes pulled back to almost-rectangles
polish
- 🌥 All 5 drift sub-paths redesigned with under 1.5% inset on any side. Cards now read as gently-wavy rectangles rather than visible cloud blobs — keeps a hand-drawn personality without ever clipping body text or action buttons. Variants still differ subtly (canonical / right-leaning / left-leaning / high-crowned / low-bellied) so a feed scroll feels hand-shaped, not stamped
v1.22.2May 2, 2026
Drift silhouettes resized to fit content end-to-end
polish
- 🌥 All 5 drift sub-paths redesigned to be near-full-bleed (use 99% of the viewBox) with subtle wave character only. Previous version's wave dips were eating into body text and pushing action buttons outside the silhouette. Now: text never clips, action buttons stay inside the cloud, and the hand-shaped drift personality is preserved through gentle top/bottom edges and slight asymmetric biases (canonical / right-leaning / left-leaning / high-crowned / low-bellied)
v1.22.1May 2, 2026
Cloud silhouette now masks banner; legacy sparkle field removed
polishperf
- 🌥 Banner images and videos at the top of dream cards now clip to the same cloud silhouette as the surrounding glass shell — no more rectangular banner peeking out above the cloud's top wave. Achieved by applying the SVG path-mask to <DreamCloud>'s content layer (previously only the shell + drop-shadow were masked)
- 🧹 Removed the legacy 30-particle .sp sparkle field that was rendering inside DreamKegApp on every page. It was redundant with the global <CosmicBackground/> introduced in 1.22.0, and was the source of a stale Math.random()-driven hydration warning in the React console
v1.22.0May 2, 2026
Cosmic atmosphere + cloud-shaped dream cards
brandingfeaturepolish
- ✨ <CosmicBackground/> mounted globally in layout.tsx — every page now sits over a slow-drifting violet/cyan/rose nebula, a 110-pinprick starfield with async twinkle, and a rare shooting-star streak (every 40–50 seconds, cyan→violet trail). All CSS-only, animated via composited keyframes. Respects prefers-reduced-motion. Star positions cached at module scope so they stay put across navigation and React Strict Mode double-mounts
- ☁ <DreamCloud/> wraps every dream card in a soft asymmetric blob silhouette instead of a hard rectangle. Variant 'drift' chosen — long horizontal cloud shape with gentle wave on top/bottom and tapered ends, like a dream pulled by slow wind. 5 sub-paths in the family rotate deterministically by hash of dream.id, so the same dream always shows the same shape but a feed-scroll feels hand-shaped rather than identical
- Each card also gets a coloured glow halo behind the silhouette (violet / cyan / rose / amber / mixed) rotating independently of the shape — solves the brand tension between 'intimate authentic dreams' and 'AI cinematic visuals' by making each card feel like it's emitting a quiet light onto the cosmic backdrop
- Dark glass surface, backdrop-filter blur, and faint procedural noise grain (4% opacity) preserved inside the cloud silhouette — same readability as before, new chrome around it
- Preview routes for the design exploration: /cloud-shapes (5 silhouette variants with glow picker), /drift-variants (5-card feed-style preview with different sub-paths and glows). Parchment-direction work parked dev-only at /parchment-test and /parchment-textures (404 in production) — kept on disk as reference
v1.21.2April 26, 2026
Dream→video rotation pool doubled — 5 → 10 dreams
contentai
- 🎬 5 more dreams added to the rotation pool, picked for maximum visual variety so the daily-rotating sidebar widget never feels repetitive: Wine Brunch Hawk Fishing Terror (aerial predator over lake dock), Pulp Fiction Chase Through Zoo Power Plant (canoes + crocs in abandoned industrial river), Homecoming Apocalyptic Ghost Transformation (football field burning, body fading), Ring of Animals (eagles + lions + cobras in mythic stone archway ring), Yakuza Den Escape (tatami + paper lanterns + tattooed figures fleeing to moonlit garden)
- Total rendered dreams now 10. Sidebar widget rotates daily by deterministic UTC-date hash, so visitors see a different dream each day without confusion from per-visit shuffling — gives roughly 10 days of variety before any repeat
- Total cinematic content cost to date across all 10 dreams: $15 in Wan 2.7 t2v calls. Average payload ~14 MB per video, all served from /public/dream-videos/
- Showcase page (/dream-videos-showcase) now lists all 10 with download links for each mp4 + poster — ready to grab for paid social ads (FB / IG / TikTok) when traffic launch is greenlit
v1.21.1April 26, 2026
Banner storage: 3.9 GB → 220 MB (PNG → WebP)
toolingai
- 🗜 All 2,340 existing AI dream banners re-encoded from PNG to WebP @ quality 82 — bucket dropped from 3.9 GB to 220 MB (94% smaller, ~85 KB avg vs 1.7 MB), back well under the Supabase 1 GB free tier with ~800 MB headroom
- 🛠 Banner generation pipeline (api/dreams/banner + scripts/backfill-banners) now pipes the model output through sharp().webp({quality: 82}) before upload — every new dream submission going forward writes WebP, not PNG. Buys roughly 10× more banners per GB of storage
- 📜 New scripts/convert-banners-to-webp.ts is a resumable, bounded-concurrency migrator: lists bucket → downloads PNG → re-encodes → uploads .webp sibling → updates dreams.banner_image_url → deletes original PNG. Skips files where a .webp sibling already exists, so re-runs are safe. Supports --dry-run and --limit=N for staged rollouts
- Side benefits: smaller egress (faster page loads, lower bandwidth bills), and far more headroom before the next storage upgrade is needed regardless of the upcoming AI dream→video pivot
v1.21.0April 26, 2026
Dream videos go live across the app
featurebrandingdata
- 🎬 Dream → video is now a first-class concept everywhere a dream appears. New <DreamMedia> component unifies the priority chain (animated dream video > AI banner image > gradient fallback) and powers three placements with one source of truth
- 📺 Placement A — Dream card banner: any dream with a rendered video now shows the looping video as its banner in the feed instead of the static AI image, with a '✦ RENDERED' badge in the corner. The card grows slightly taller (220px vs 180px) when video is present so the motion has room to breathe
- 📺 Placement B — Sidebar 'Dream in Motion' widget: new compact 250×156 video tile in the right-hand /feed sidebar between Trending Tags and Trending Dreams. Picks one rendered dream per calendar day (deterministic, same for everyone), giving repeat visitors a reason to come back daily — and seeding aspiration for the future paid 'render my dream' feature
- 📺 Placement C — Dream detail hero: the banner at the top of every /dream/[id] page is now a full-width 320px-tall cinematic video when one exists, with the rainbow title overlaid
- 🛡 Performance discipline baked in: each video uses preload='none' until IntersectionObserver decides the card is at least 35% in viewport (5% for the hero), then swaps to preload='auto' and starts playing. Pauses + resets when scrolled out of view. Pauses on document.hidden (Page Visibility API). Skips autoplay entirely on prefers-reduced-motion or saveData/2g/3g. Means a feed of 100 video-rendered dreams streams at most ~1-2 videos at a time as the user scrolls
- 🗄 Schema migration (add_dream_video_columns): dreams table now has video_url, video_poster_url, and video_status ('none' | 'queued' | 'rendering' | 'rendered' | 'failed') with a partial index on rendered status for cheap feed/sidebar queries
- 🔌 New endpoint /api/dreams/featured-video returns the daily-rotating sidebar pick (revalidate every 1h at the edge — daily rotation only changes once per 24h)
- 5 dreams pre-rendered and backfilled into the new columns: alien storm hurricane, Utah underwater portal, hockey shark transition, mountain bears at Christmas, floating sand vanishing
v1.20.0April 26, 2026
Landing page reborn — real dreams, rendered with AI
featurelandingbranding
- 🎬 The unauthenticated landing page now opens with a full-bleed cinematic AI video — a real public dream rendered into 15 seconds of moving imagery via Wan 2.7 t2v. The first video is 'Alien Abduction During Hurricane Storm' (joewcarson, Jan 2019): a swirling purple/blue hurricane with a glowing cyan eye, the moment before the alien beams down
- Tagline added: 'Real dream data, rendered with AI' — frames the video as authenticity to dream-logic (AI video's surreal physics IS dream physics) and primes users for the future paid 'turn your dream into a video' feature
- Video uses HTML5 autoplay/muted/loop/playsInline (works on every modern browser including iOS Safari), preload='metadata' so first paint isn't blocked, poster image renders instantly under the video tag, vignette scrim keeps the rainbow DreamKeg headline + CTAs crisp over moving footage
- Source dream attribution at bottom of hero links to the actual dream entry — 'Real dream data' isn't a tagline, it's clickable proof
- Added a 4th feature card 'Dreams → Video' to the existing AI Tagging / Globe / Matching grid, teasing the next major feature
- Footer + JSON-LD schema preserved exactly so SEO rankings carry over
v1.19.1April 25, 2026
Mascots come alive — full character animation
featurebrandingpolish
- 🎬 All 6 mascots now have real character animation, not just static drift — the Pandaren stumble-walks while banging his drum, the eastern dragon undulates serpentine through the air, the clockwork owl flaps its brass wings, the bronze golem clunks along, the sky whale floats with its little cloud companions, and the two-headed eagle slowly beats its wings
- Pipeline: Wan 2.7 image-to-video (3sec loops, first/last frame matched for seamless looping) → ffmpeg frame extraction → custom flood-fill alpha extraction (handles Wan's varying warm-tan studio backgrounds per video by auto-sampling corner pixels) → animated WebP encoding with full transparency
- Animated WebPs are 730KB–1.4MB each, ~5.9MB total for all 6 — small enough that they preload alongside the page; browser auto-loops them natively (no JS, no GIF artifacts)
- Static PNG fallback (256px) accompanies each WebP so older browsers (or any that fail to load the WebP) still see the mascot — degraded to no animation but full presence
- Build pipeline (scripts/animate-mascot.mjs) is now a one-command per mascot: drop a Wan-generated mp4 in scripts/anim-test/<name>.mp4, run `node scripts/animate-mascot.mjs <name>`, get an animated WebP at public/mascots/<name>.webp. Per-video bg color auto-detection means future mascot regenerations 'just work'
v1.19.0April 25, 2026
Mascots take flight
featurebranding
- 🐼 Six hand-painted mascots — Pandaren brewmaster, Sisu/Shenron-style eastern dragon, brass clockwork owl (Jhoira's-Familiar inspired), bronze runic golem (Metalworker MTG inspired), Studio-Ghibli sky whale, and a heraldic two-headed bald eagle — now drift across the site as branding easter eggs. Each was generated as a hand-painted MTG-card-style illustration via Grok Imagine Pro, then background-removed and exported as transparent PNGs in /public/mascots/
- Mascots have two modes: ambient (rare drift across any page, ~1 spawn every 1.5 minutes) and editor (dense + contextual, mounted only on the dream composer when text exists, fires every 4s with up to 3 mascots on screen at once)
- Editor mode picks mascots by keyword affinity to whatever you're typing — write about water/swimming and the whale shows up, write about fear/fight and the dragon, late-night session and the owl drifts in. 15-25 trigger keywords per mascot
- Time-of-day biases: owl gets a +2 weight boost between 10pm and 5am, eagle gets +1.5 between 5am and 9am
- All 6 mascot illustrations were AI-generated this session. Source assets live in /public/mascots-v2-raw/ (pre-bg-removal) and the live transparent set in /public/mascots/. Internal /mascot-bakeoff route shows the platform comparison and the chosen direction for future iteration
v1.18.2April 23, 2026
SEO: unblock /feed, block auth-gated shells
seodata
- robots.txt: removed /feed from the disallow list — it's a publicly browseable page linked from the landing ('Or browse the dream feed →'), so Googlebot should be crawling it. This was triggering Search Console 'blocked by robots.txt' notices because the landing page advertised /feed as crawlable while robots.txt slammed the door
- robots.txt: added /globe and /patterns to the disallow list — both are auth-gated app shells with no indexable content for anonymous crawlers, so sending Googlebot there was pure crawl-budget loss
- sitemap.xml: added /feed at priority 0.9 (one notch below the homepage) with a daily change-frequency since new public dreams post continuously
v1.18.1April 22, 2026
Fix Dream Globe deep-link 404
fixglobe
- Clicking '← Dream Globe' from a dream detail page (after drilling in from a globe dot) was 404-ing — the back link pointed to /globe but no such app-router page existed (the globe lived only inside DreamKegApp's internal 'explore' page state). Added a dedicated /globe route that mounts DreamKegApp with the explore page pre-selected, so the back link now lands users directly on the globe
- DreamKegApp now accepts an optional initialPage prop so future app-router pages can mount it with a specific internal page already open — same pattern if we ever deep-link /matches or /trending directly
v1.18.0April 20, 2026
Globe Dot Inspector + Deeper Zoom
featureglobedata
- 🔍 Click any dot on your Dream Locations globe to open a new Dot Inspector — shows every dream that contributed to that dot with a direct link into each one (routes with ?from=globe so '← Dream Globe' takes you straight back), plus the list of source tags that rolled up into that location
- 🛠 Per-tag 'Fix this tag' controls inside the Inspector — two options per tag: 'Not a place' (permanently hides it from your globe) or 'Move…' (opens a live Nominatim search box so you can pick the correct city). Your corrections are saved per-user, so one person's 'Austin is my friend's name, not the city' never rewrites anyone else's globe
- New tag_geocode_overrides table stores each user's exclude/remap decisions; the /api/globe/dream-locations endpoint now applies them before hitting the geocoder so corrected tags plot at the right spot (or don't plot at all) on the next fetch
- Zoom range on the globe expanded 3× — the max-zoom is now 12× initial scale instead of 4×, so you can actually zoom in on a specific metro area and see individual dots separately. Dot sizes compress past 3× zoom (sqrt curve) so they stay clickable without swallowing the map at tight zoom
- Globe header hint text updated in dream mode to mention dot clicks — desktop reads 'Click a dot to view dreams or fix a tag', mobile reads 'Tap a dot to view dreams or fix a tag'
- New supporting endpoints: /api/globe/dreams-at-place (dreams matching a set of place tags), /api/globe/override (POST exclude/remap, DELETE clear), /api/globe/tag-search (auth-gated Nominatim proxy for the Move… picker)
v1.17.2April 20, 2026
Globe Proper-Nouns Only + Mobile Pinch Zoom
fixglobemobile
- Dream Globe now only plots proper-noun place tags — added a capitalization gate that rejects tags like 'sunroof', 'power plant', 'radio section', 'parking lot' before they're ever sent to the geocoder. Common-noun compounds were sneaking past the blocklist and resolving to random obscure villages. A tag is accepted only if it contains at least one uppercase letter OR is a known alias ('nyc', 'la', 'atx')
- Mobile pinch-to-zoom on the globe is now actually functional — before, d3.drag was intercepting two-finger gestures as single-finger rotation (so pinching just spun the globe). Added a multi-touch filter to d3.drag that skips out when 2+ fingers are down, and moved the pinch handler to run in the capture phase so it beats d3 to the touch events
- Pinch handler also now initializes cleanly on touchstart (not just touchmove) so the first pinch frame no longer 'snaps' to a new scale when the second finger first lands
- Dream-locations API response now includes a filteredNonPropers counter so the UI can eventually surface 'N junk tags rejected' stats
v1.17.1April 20, 2026
On This Day default + Dream Detail polish
uxpatternsfix
- 📅 On This Day is now the default /patterns tab (and the first module in the tab grid) — it's the most time-sensitive module (a fresh time-capsule snapshot every single day) so it gets the default slot
- Dream detail page now shows the AI-generated banner image when one exists — previously only the gradient fallback was rendering, even for dreams that had banner_image_url set. Banners also got a subtle dark scrim at the bottom so the title stays legible over any image, and the banner itself is now a bit taller (120px → 180px) so the imagery has room to breathe
- Dream detail '← DreamKeg' back link is now context-aware — when you open a dream from /patterns (e.g. an On This Day card), the back link reads '← Dream Patterns' and takes you back to /patterns instead of dumping you on the feed. Same ?from= mechanism also supports profile, globe, and changelog referrers for future deep-links
- Fixed a latent metadata bug: og:image/twitter:card preview URLs were reading dream.banner_url (never existed) instead of dream.banner_image_url — social previews for dreams with AI banners are now wired up correctly
v1.17.0April 20, 2026
All 8 Dream Patterns Modules Live
featureanalyticspatterns
- 🎭 Recurring Cast — top 15 specific people tagged across the most dreams, with first/last-seen dates and a per-person appearance bar. Filters out generic tags (guy, kid, friend) so only real names surface
- 👻 Forgotten Faces — people you used to dream about 3+ times who haven't appeared in the last 6 months of your journal. Anchored to your most recent dated dream, not wall-clock 'now', so taking a journaling break doesn't falsely mark everyone as forgotten
- 💜 Emotion Timeline — your top 6 emotions stacked across the last 12 months. Each bar is a month, each colored segment is an emotion's share of that month's emotional texture
- 🧬 Dream DNA — your category fingerprint (People vs Places vs Emotions vs Actions vs Themes vs Objects vs Animals vs Activities) as a horizontal bar chart, plus a human-readable 'signature' phrase like 'Theme-rich · People-light · Animal-forward'
- 📅 On This Day — every dream you've ever had on today's exact calendar day across all years. Click any card to jump to the full dream. Falls back to a friendly empty state on days you haven't journaled yet
- 🌀 Weekday Vibes — a 7-card grid (Mon → Sun) showing dream count, top 5 tags, and dominant emotion for each weekday. Weekend cards get a distinct purple accent so Saturday-Sunday dreaming patterns jump out visually
- ✨ New vs Familiar — per-month stacked bars of 'tags you've never dreamed of before' vs 'tags returning from earlier dreams'. Gives an overall 0-100 novelty score with a flavor caption ('deeply repetitive' / 'balanced' / 'new territory') so you can see whether your dream vocabulary is expanding or settling
- 🍂 Seasonal Pulse — 4 themed cards (spring/summer/fall/winter) with top tags, dream count, and dominant emotion per season. Each season's card is tinted with a seasonal accent color
- All 8 modules share a single /api/profile/patterns fetch via an in-memory bundle cache — clicking between tabs doesn't re-scan, and the scan cost is only paid when the first of the 8 tabs is opened (the 3 original tabs still fetch their own focused endpoints, so pure Dream Patterns / YoY / Trends users never trigger the big fetch)
v1.16.3April 20, 2026
Mobile Polish + Globe Admin-Trivia Filter
fixmobileglobedata
- Sidebar 'DreamKeg' wordmark was clipped under the mobile top bar — the sidebar now starts at 48px on mobile so the logo sits cleanly below the header instead of hiding behind it
- Mobile top-bar page title now uses the same Bungee rainbow styling as the sidebar wordmark — matches the brand feel instead of the plain white it was before
- Dream Globe place filter tightened: removed borough/district/county/quarter/locality/suburb/neighbourhood from the allowed place types, raised the minimum importance threshold from 0.3 to 0.45, and added an admin-level <=6 gate on boundary hits. Borough-level mis-tags like 'Aleutians East Borough' and 'Kenai Peninsula Borough', plus random Indian tehsils, no longer plot
- Added a retroactive display-name filter so existing cached geocodes that match admin-trivia words (borough, tehsil, taluk, parish, subdistrict, township) are silently dropped from the globe without waiting for re-queries
- Blocklisted observed mis-matches from user globe screenshots: 'aswan high', 'east volcano', 'tehsil', 'hof hasharon', 'medical city', 'beach area', 'volcano'
v1.16.2April 20, 2026
Profile Streamlined
uxprofile
- Removed the Dream Patterns per-category section from the profile — it now lives exclusively on /patterns (where it opens by default), so the profile stays focused on header → streaks → deeper analytics link → people → timeline → starred → your dreams
- The Dream Patterns & Trends link card now sits directly under Dream Streaks, right where the removed section used to start, so the flow from 'how often am I dreaming' to 'deeper analysis' is a single scroll away
- The 'Tags' stat in the profile header now routes to /patterns instead of scrolling to a section that no longer exists
- Removed the dead aiInsight computation from the profile (moved to /patterns alongside the Dream Patterns breakdown)
v1.16.1April 20, 2026
Dream Patterns Polish
uxprofileanalytics
- Dream Patterns is now a first-class tab on /patterns (in addition to its profile placement) — opens by default and shows your top 8 tags in every category plus the AI Insight summary
- Profile reorder: the Dream Patterns section now sits directly under Dream Streaks so the reading flow goes 'how often am I dreaming → what am I dreaming about → who's in them → timeline → deeper modules'
- /patterns tab navigation is now a fitted 2-column (mobile) / 5-column (desktop) grid instead of a horizontal-scrolling strip — every module is reachable at a glance, no sideways scrolling
v1.16.0April 20, 2026
Dream Patterns Page + A Year Ago Tonight
featureprofileanalytics
- New /patterns page — a dedicated home for deeper dream analytics, accessible from a new 'Dream Patterns & Trends →' card on your profile. The heavy monthly-tag-trends chart no longer renders inline on the profile, so profile first-paint is noticeably faster for users with thousands of tags
- Launched the first new trend module: 🕰️ A Year Ago Tonight — a grid of the last 12 months showing the top people, places, and themes in your dreams for the same month one year prior. Months before your earliest dated dream are omitted; months with zero dreams show a placeholder card so the timeline stays honest. Only participating dreams are ones with a real dream_date (backdated or posted-on-day) so the comparison reflects when you actually dreamed, not when you posted
- /patterns ships with tab stubs for 7 additional upcoming modules — Recurring Cast, Forgotten Faces, Emotion Timeline, Dream DNA, On This Day, Weekday Vibes, New vs Familiar, Seasonal Pulse — each marked 'coming soon' so you can see what's on the roadmap. Each future module will fetch its own data only when opened, so unused trends cost nothing
- Existing Tag Trends chart moved into /patterns unchanged — same selector pills, same stacked bars, same trend arrows in the legend
v1.15.0April 20, 2026
Mobile Header, XP Backfill & Profile Polish
fixmobilexpprofile
- New thin mobile top bar — hamburger menu tucked into a 48px header with the current page title centered, so the menu button no longer overlaps page titles on narrow screens
- Fixed a long-standing XP gap: imported dreams were silently skipping every content XP grant. Bulk imports now award the same dream_post / long-dream / rich-tagging / epic-tagging / backdated / milestone bonuses that normal submissions get. Streaks are intentionally not retro-granted (historical imports aren't 'daily' events)
- New self-service backfill endpoint — heavy importers whose lifetime XP was stuck on a fraction of their dream count can retroactively grant themselves the XP their historical library deserves. Idempotent, safe to re-run
- Profile people-tag counts no longer double-count aliased tags — when a single dream tags both 'sister' and 'Jackie' (both pointing to the same canonical person via definitions), it now counts as one appearance instead of two. Existing counts automatically re-derive on next load; no migration needed
- Dream banner images now load on other users' profile pages — the API was dropping the banner_image_url column when shaping dreams for public profiles, so cards that should show the AI-generated art were falling back to the gradient
- Dream Globe: the 'Beyond Earth' cosmic-places panel no longer covers the globe on mobile — it now renders below the globe instead of as an absolute overlay
- Tuned 'Added a definition' XP from 15 to 10 so it sits in line with similar profile actions
v1.14.2April 19, 2026
Globe Accuracy Pass
fixglobedata
- Dream Locations globe was plotting tons of false-positive places — 'gate' → Ghat Libya, 'couch' → Couch WV, 'flat ground' → a random address, '99999' → Matruh Egypt, 'costco' → a specific Wichita store. Added a two-stage filter: a structural-word pre-filter that rejects phrases like 'flat ground', 'back yard', 'big building', '3 story building' before they ever hit the geocoder, and a Nominatim post-filter that only accepts real administrative places (cities, towns, villages, countries) with a minimum importance score — buildings, shops, amenities, and natural features are now dropped
- Massively expanded the generic-phrase blocklist with abstract concepts users commonly tag (party, wedding, work, vacation, class, upstairs, hotel room, high school, tennis court, gas station, etc.) — these no longer match random foreign villages
- Swept ~430 bad cached geocodes out of the DB so existing users see an immediately cleaner globe without waiting for re-queries
v1.14.1April 19, 2026
Globe Fixes + Beyond Earth
fixglobedatafeature
- Dream Locations globe was silently empty for anyone with 1,000+ dreams — PostgREST default row cap was truncating both the dreams query and the dream_tags query, and the geocode cache lookup URL was blowing past PostgREST's URL limit. All three paths now paginate properly and chunk their `in.()` filters. Heavy users should now see thousands of city dots instead of zero
- New 🌠 Beyond Earth panel in the corner of your Dream Locations globe — cosmic and afterlife places from your dreams (outer space, Mars, the moon, heaven, hell, dreamland, the void, etc.) render as floating gradient chips with per-place dream counts. 19 curated off-Earth destinations with conservative keyword matching so 'skyline', 'event space', and 'marsh' stay on Earth where they belong
- Sleep Locations globe had the same row-cap bug and also now paginates correctly
v1.14.0April 17, 2026
XP, Levels & Streaks
featuregamificationxpprofile
- New XP system — earn experience for posting dreams, tagging richly, backdating older dreams, hitting dream-count milestones, and keeping a daily streak
- 100 levels with seven tiers: Dreamer → Lucid Dreamer → Dream Weaver → Dream Architect → Dream Sage → Dream Master → Dream Legend
- Social XP for follows, upvotes, and comments — both sides of the interaction earn, with anti-farming safeguards (each specific like/follow between two users only grants XP once)
- Daily streak tracking with a 1-day grace window — miss a day, keep your streak; miss two, reset. Streak milestone bonuses at 3, 7, 30, 100, and 365 days
- Level badge + streak flame pill on your profile, with a gradient progress bar showing XP into your next level — click it to open your XP timeline
- XP timeline modal with range filters (today / 7d / 30d / all-time) and a by-category breakdown
- Level-up celebration: when a dream submission pushes you across a level threshold, the celebration modal banners the new level with the tier gradient
- Public level chip + streak flame shows everywhere a dreamer appears: on every dream card in the feed, on comments, on the Trending Dreamers list, and on other users' profile pages
- New 🏆 Leaderboards on the Trending page with three tabs — All-Time XP, This Week (XP earned in the last 7 days), and Longest active Streaks. Top 3 get gold/silver/bronze medals, your own row is highlighted
- Historical backfill: your entire dream history (and all your past follows, upvotes, comments, definitions, profile fills, and badge unlocks) was scored retroactively — new accounts start at Level 1, but nothing you've already done is wasted
- Floating +XP toasts pop up when you upvote, comment, or follow — a little gold pill flies up from the corner so you feel the reward (idempotent grants stay silent, so spamming the same action doesn't spam the toast)
- Avatar emoji picker now shows live progress toward each locked emoji — hover a grayed-out emoji to see a progress bar and 'X / Y' counter (e.g. '42 / 100' for 🏆 Dream Legend). New 'N / M unlocked' counter above the picker so you can see your avatar collection at a glance. Unlock celebrations now flag 'Now available as avatar' so you know the emoji's yours to wear
v1.13.0April 16, 2026
Real-Data Explore Globe & Trending
featureglobetrendingdata
- Explore Globe now renders real dreamers — no more seed data. 'World's Trending' dots are geocoded from public profiles' location fields, sized by how many dreamers are in each city
- 'Dream Locations' globe mode plots real places tagged inside your dreams (places category). Abstract places like 'the beach' or 'a hallway' are silently dropped
- 'Sleep Locations' globe mode plots where you physically were when each dream happened, sourced from per-dream location (falls back to profile location until you add dream-level sleep locations)
- Trending page: replaced the hardcoded celebrity list with three real rankings — Top Dreamers (most dreams), Rising (joined in last 30 days with 3+ dreams), Most Followed
- Trending cards are clickable (opens profile) and the Follow button is wired to real follow state
- Free OpenStreetMap (Nominatim) geocoding with a persistent DB cache — respects the service's 1 req/sec rate limit and backfills over successive visits
- Empty states everywhere so the globe and trending feel intentional while the platform is still young
v1.12.1April 16, 2026
Badges Stat + Full Badge Modal
profileuxbadges
- New '# Badges' stat in the profile header showing how many badges you've unlocked
- Click the Badges stat to open a full badge modal — browse every badge with description, unlock hint, and live progress bar
- Filter tabs: All / Unlocked / Locked so you can focus on what's next
v1.12.0April 16, 2026
Privacy Tightening & Profile Polish
privacyprofileux
- Private dreams are strictly author-only — no notifications are sent when someone is tagged in a private dream, and the dream is never visible to anyone but the author
- Public 'Someone dreamed about you!' notifications now link directly to the dream (tap the notification to view)
- Tagged people in private dreams are still aggregated into tag statistics, but their identity is never exposed to anyone else
- Profile: 'Your Dreams' list now paginates at 10 dreams per page (was 20)
- Profile: 'People In Your Dreams' list now paginates at 10 people per page (was 15)
- Profile: Badges section moved to the bottom of the profile so primary dream activity reads first
v1.11.0March 18, 2026
New Logo & Merge Tags
brandingfeatureprofile
- New DreamKeg dreamcatcher logo across the entire site — favicon, PWA icon, Open Graph, and app logo
- Merge people tags: combine duplicate people (e.g., 'James' + 'james' into 'James Carson') from your profile's People section
- Searchable merge modal with two-step flow: pick the primary person, then select tags to fold in
- Merge is reversible — delete the definition from the Definitions page to un-merge
v1.10.0March 16, 2026
AI-Generated Dream Banners
featureai
- AI-generated banner images for dream posts — powered by DALL-E 3 (1792x1024 wide format)
- Haiku-crafted image prompts from dream title + tags for vivid, surreal dream artwork
- Banner auto-generates on new dream submission (non-blocking, appears when ready)
- 'AI Banner' button on existing dreams to generate banners on demand
- Dream cards expand taller when displaying AI banners vs gradient backgrounds
- Images stored in Supabase Storage with public CDN access
- Stability AI SDXL support wired up as a cheaper alternative provider
v1.9.0March 12, 2026
Content Security & Moderation
securityai
- AI content moderation: dreams are screened for spam, hate speech, and non-dream content before tagging (powered by Claude Haiku)
- 10,000 character limit on dream posts — prevents spam walls while accommodating even the longest real dreams
- Input sanitization: HTML tags, scripts, and control characters are stripped from dream text
- Character counter on dream submit and edit forms showing live count against limit
- Moderation and sanitization applied to dream submit, edit, import, and pre-analysis endpoints
v1.8.1March 11, 2026
Appeared In Dreams Stat
featuresocialprofile
- New 'Appeared In' stat on your profile showing how many other users' dreams you're tagged in
v1.8.0March 11, 2026
Social, Search & Onboarding
featuresocialsearchuxonboarding
- Public user profiles: click any username/avatar to view their dreams, tag patterns, and stats
- New GET /api/users/[id] endpoint returning profile, public dreams, and tag stats
- Follow/unfollow directly from public profiles with real-time state updates
- Dream search with debounced text search across titles and dream bodies
- Filter dreams by tag name, tag category, and 'my dreams only' toggle
- Shareable dream links: each dream has a unique URL at /dream/[id] with OG meta tags
- Server-rendered dream pages for rich social media previews (Twitter, Facebook, etc.)
- Share button on dream cards copies link to clipboard with visual confirmation
- Following feed tab: toggle between 'All Dreams' and dreams from people you follow
- Dream streaks card on profile: current streak, longest streak, this month, avg/week
- Encouraging streak messages for active journalers
- Tag trends over time chart: visualize how dream themes change month by month
- Selectable tag pills to focus on individual tag trends with direction indicators
- Manual tag editing: add or remove tags after AI tagging on your own dreams
- New POST/DELETE /api/dreams/tags endpoints for granular tag management
- Real-time tag highlighting updates when tags are added or removed
- First-time user onboarding flow: set avatar, username, bio after signup
- Two-step onboarding with profile setup then CTA to submit first dream
v1.7.0March 10, 2026
Person Tag Popup — View, Follow & Invite
featuresocialux
- Clicking @person tags in dreams now opens an interactive popup modal instead of a brief toast
- Popup shows linked DreamKeg profile with avatar, name, bio, follower count, and Follow/Following button
- On your own dreams: Link unlinked person tags to DreamKeg users via search or invite via email
- On others' dreams: Shows profile if linked, or 'Not on DreamKeg yet' status
- Debounced user search (300ms) within the popup for quick linking
- Email invites sent directly from the popup with success/error states
- New GET /api/definitions/lookup endpoint for fetching definitions with linked profiles
- Click-outside-to-close and glass morphism styling matching the app design
- Fixed Resend email client lazy initialization to prevent build-time crashes
v1.6.0March 10, 2026
Smart Definition Prompts, Notifications & Invites
featuresocialemailnotifications
- Post-submission modal prompts users to define new people and places tags
- Per-tag definition inputs with category badges and context-aware prompts
- User search dropdown to link people tags to real DreamKeg accounts
- Email invite system via Resend for non-DreamKeg users ('Someone dreamed about you!')
- Notification system with bell icon, unread count badge, and 60-second polling
- Notification types: dream_link, invite_accepted, follow, comment, like
- Notifications page with glass cards, from-user avatars, and mark-all-as-read
- Invite acceptance flow: signup preserves invite param, auto-links definition, notifies inviter
- Deferred prompts with 7-day cooldown ('Ask Me Later' button)
- Batch definition save endpoint with notification creation for linked users
- Rate-limited invites (10 per user per 24 hours) with duplicate detection
- Branded dark purple HTML email template matching DreamKeg design
- Three new database tables: notifications, invites, deferred_prompts
v1.5.0March 9, 2026
Mobile Responsiveness
mobileresponsiveux
- Sidebar converts to slide-out hamburger menu on screens < 768px
- Dream Feed switches to single-column layout on mobile, trending sidebar hidden
- DreamCard responsive padding, banner height, and font sizes for small screens
- Submit page influencer fields stack vertically on mobile
- Profile page header stacks vertically, stats row wraps, avatar resizes
- Globe page reduced height (320px), touch pinch-zoom support, touch-action CSS for iOS
- Dream Matches side-by-side comparison stacks vertically on mobile
- All page titles, card padding, and spacing adapt to mobile viewport
- Definitions form stacks vertically, list items wrap on small screens
- Settings emoji grid and input fields resize for touch targets
- Landing page feature grid stacks to single column, CTA buttons stack on small screens
- Added viewport meta tag (device-width, initial-scale 1)
- Added overflow-x: hidden on mobile to prevent horizontal scroll
- Hamburger button with glass morphism style, animated sidebar backdrop overlay
v1.4.0March 9, 2026
Context Document & Project Organization
docstooling
- Created CLAUDE_CODE_CONTEXT.md with full project documentation
- Documented complete tech stack, repo structure, database schema, and design system
- Cataloged all existing features and prioritized next features roadmap
- Added TypeScript build rules and key patterns reference
v1.3.0March 8, 2026
Import Tool & Profile Stats Engine
featureimportapi
- Built Import Dreams page with drag-and-drop file upload (JSON, CSV, TXT)
- Batch processing with progress bar and error tracking
- Pre-tagged data detection preserves existing tags on import
- Server-side profile stats computation via /api/profile/stats endpoint
- Full tag frequency analysis across all 2,241+ dreams efficiently
- Dream list pagination (20 dreams per page) with scroll-to-top
- People In Your Dreams pagination (15 per page)
v1.2.0March 7, 2026
Globe, Matches & Trending
featured3visualization
- Built Explore Globe with D3.js orthographic projection
- Three globe modes: World Trending, Dream Locations, Sleep Locations
- Drag-to-rotate and scroll-to-zoom with smooth transitions
- Interactive tooltips on data dots with city, theme, and count
- Dream Matches page with Jaccard similarity scoring
- Side-by-side dream comparison with shared tag pills
- Cross-user matching + self-pattern detection fallback
- Trending page with real theme data computed from feed dreams
- Celebrity demo accounts for aspirational content
- Top Dreams section sorted by engagement
v1.1.0March 5, 2026
Definitions, Settings & Voice Input
featurevoicecrud
- Definitions page with full CRUD operations via /api/definitions
- Category filtering (People, Places, Things) with stats bar
- Rainbow @People links in definitions with click-to-view
- Settings page with username, display name, bio, location editing
- Avatar emoji picker with 16 options and visual selection
- Voice-to-text dream input using Web Speech API
- Recording indicator with pulsing animation and append mode
- AI auto-title toggle on dream submission form
- Privacy toggle (public/private) with visual feedback
- Dream influencer fields (location, time, food, substances, stress, sleep quality)
v1.0.0March 4, 2026
Core Platform Launch
launchfeatureai
- DreamKegApp single-file architecture with client-side page routing
- Google OAuth authentication via Supabase Auth
- Auth middleware protecting all app routes with redirect to /login
- Dream submission with Claude AI exhaustive tagging (8 categories)
- Live dream feed from Supabase with real-time data
- DreamCard component with gradient banners, expandable text, tag legend
- Inline color-coded tag highlighting in dream text
- Profile page with avatar, stats (dreams, tags, followers, following)
- Dream Patterns by category with tag frequency pills
- AI Insight dynamically computed from tag statistics
- Dream edit and delete functionality on profile page
- Landing page with star particle animation and CTA buttons
- Glass morphism design system with rainbow animated text
- 8 gradient presets for dream card banners
- 8 tag category colors (people, places, emotions, actions, themes, objects, animals, activities)
v0.1.0February 25, 2026
Initial Commit
setup
- Next.js 14 App Router project scaffold
- Supabase client and server configuration
- Tailwind CSS setup with custom theme
- Database schema: profiles, dreams, dream_tags, definitions, follows, likes, comments
- Row Level Security (RLS) enabled on all tables
- Counter triggers for dream_count, like_count, follower_count, following_count
- PostgreSQL enum for tag categories
dreamkeg.com · Built by Joe Carson