Todos los cambios notables de Spectral se documentan aquí. Este proyecto sigue Semantic Versioning.
1.0.38 —
Added
Automated code quality checks — ESLint configuration expanded from 8 to 35 active rules, catching import ordering issues, type safety problems, and architectural violations before they reach production
CSS design token enforcement — new Stylelint integration ensures all colors, fonts, spacing, and other visual properties use design tokens, keeping the interface consistent and themeable
Type-aware linting — enabled TypeScript type-checked linting that catches floating promises, misused async patterns, and unnecessary type assertions
Changed
Stricter import hygiene — imports are now automatically sorted alphabetically and grouped by origin, with type-only imports enforced via `import type`
Cleaner codebase — removed 87 unnecessary type assertions and fixed 600+ import ordering issues across the entire codebase
1.0.37 —
Fixed
Slider tooltips on touch devices — hint icons on sliders and hue range sliders now display proper tooltips instead of relying on `title` attributes, which are invisible in PWA and touch environments
1.0.36 —
Added
Defringe tool — a new tool under the Detail section that lets you desaturate green and purple/magenta chromatic aberration fringes at contrast edges. It features interactive Hue Range sliders to precisely target the affected colors.
Changed
Smart grade matching — the auto-grade matching algorithm now uses detailed histogram percentiles and cumulative distribution analysis to produce a more precise and natural match. It now generates automatic tone curves to emulate faded film shadows, highlight roll-offs, and custom color casts.
Dependency upgrades — upgraded core libraries including Astro, React, Vitest, and Playwright to their latest versions for performance and security improvements.
Fixed
Section toggle accuracy in tests — fixed an issue in the integration tests where preset buttons with "Color" in their name (e.g. True Color) were clicked instead of the Color section header.
1.0.35 —
Changed
Improved session security — authentication credentials are now cleared automatically when the browser tab is closed, reducing the risk of stale sessions on shared devices
Import safety guard — imported project files are now validated for size integrity before extraction, preventing corrupt or oversized archives from affecting the app
1.0.34 —
Fixed
Linear gradient rotation — the gradient effect now matches the angle of the on-screen guide lines on non-square images; previously the gradient appeared rotated compared to the handles
Gradient mask accuracy — the SVG mask overlay for both linear and radial gradients now reproduces the exact smoothstep curve used by the rendering engine, showing a precise preview of feathering and falloff
Radial gradient mask — the radial mask overlay now shows a realistic feather-to-edge fade instead of a flat solid fill, matching the actual shader result
Slider values reset on move — adjusting feather or opacity and then moving or rotating the gradient no longer resets those values to their defaults
1.0.33 —
Added
Gradient opacity control — a new Amount slider in the right panel lets you control how strongly each gradient mask affects the image, from subtle (0%) to full strength (100%)
Changed
Crop overlay improvements — more responsive crop handles and a refined crop interaction model
Gradient toolbar simplified — mask colour dots now appear inline next to the toggle; the toolbar is cleaner and less cluttered
Feather and Opacity sliders moved to right panel — gradient-specific controls now live alongside the adjustment sliders for a more Lightroom-like workflow
Fixed
Radial gradient geometry — the SVG mask overlay now perfectly matches the WebGL shader result for both circles and ellipses at any rotation angle
Gradient handles no longer jump — switching between circle and ellipse no longer causes the handles to snap to unexpected positions
Rotation no longer changes gradient size — rotating a gradient on a non-square canvas previously caused the gradient to shrink or grow; size is now preserved during rotation
Watermark ignored when disabled — disabling the watermark in the export menu was not respected during export; the toggle now takes effect immediately
1.0.32 —
Changed
Clone tool grain adjustment — the clone and heal brushes now support configurable film grain parameters, producing more realistic texture blending with the surrounding area
Typography refresh — switched to Overused Grotesk and Manrope typefaces for a more refined, modern look across the entire interface
Modals streamlined — all modal dialogs now use a unified accessible base, improving focus management, keyboard navigation, and screen reader support
1.0.31 —
Added
Spot healing tool — click any dust spot, blemish, or sensor mark and Spectral fills it seamlessly using the surrounding pixels; works on skies, walls, and any uniform surface
Clone and heal brushes — two additional brush modes for targeted retouching: Clone stamps an exact copy from a chosen source, Heal blends the source texture to match the destination's colour and lighting
Brush size slider — adjust the spot, heal, or clone brush radius with a dedicated size control in the retouching panel
Interactive spot overlay — placed spots appear as numbered circles on the canvas with source-to-destination guides; click any spot to re-select it, press × or Backspace to delete
Watermark on export — add a custom text watermark to exported photos with controls for position, opacity, and size
Changed
Onboarding tour updated — the guided tour now includes a step for the new retouching tools
Splash screen polish — CSS-driven animations for a snappier startup impression
Dialog and dropdown transitions — improved interruptibility transitions and reduced-motion accessibility
Fixed
Undo removes the full brush action — pressing undo after placing a spot now correctly removes both the spot and its source in one step
Language consistency — fixed a language display bug that caused inconsistent translations in certain viewer components
1.0.30 —
Added
Custom metadata injection — embed copyright, creator name, and software info directly into exported JPEGs as EXIF and IPTC data; configure once in Settings or the export menu and it applies to all future exports
Metadata in export menu — the export dropdown now includes an inline metadata section with toggle, copyright, and creator fields, so you can manage metadata right where you export
Settings hint clarified — metadata settings now clearly indicate they are saved globally and apply to all projects and exports
Roadmap updated — the metadata injection feature is now marked as shipped on the landing page roadmap
1.0.29 —
Added
Batch file renaming — compose filename templates from tokens like original name, date, time, project name, and sequence number; see a live preview of the resolved output before exporting
Changed
Export menu redesigned for batch mode — the batch export button now opens a unified panel with quality selection and file naming controls, instead of using a split button
Checkbox hover state — selected photo checkboxes now show a subtle hover highlight for better interactivity feedback
Roadmap updated — the batch rename feature is now marked as shipped on the landing page roadmap
Fixed
"Clear all photos" was deleting photos across all projects — the clear action now correctly limits deletion to the current project only, preventing accidental data loss in other projects
1.0.28 —
Added
Reference photo in onboarding tour — the guided tour now highlights the Reference Photo panel with a dedicated step, so first-time users discover colour palette extraction and grade matching right away
Changed
Onboarding tour order — tour steps now follow the visual top-to-bottom layout of the interface for a more natural flow (Navigator → Reference Photo → Cookbook → Filmstrip → Settings)
Splash screen animation — the startup logo reveal uses lighter, CSS-driven keyframe animations instead of the previous scripted approach, resulting in a snappier first impression
Landing page streamlined — removed redundant inline script blocks from both the English and localized landing pages for a cleaner page load
1.0.27 —
Added
Reference image panel — drop or upload a reference photo to extract its colour palette; Spectral analyses the tonal distribution and displays a swatch strip alongside the reference thumbnail in the left panel
Grade matching — a one-click "Match this look" button analyses the tonal relationship between your reference and current photo and applies a suggested starting-point grade (exposure, contrast, temperature, tint, HSL) that approximates the reference look
Changed
Dependencies updated — upgraded React 19.2.6, Astro 6.3.3, Lucide React 1.16.0, ExifReader 4.39.0, Playwright 1.60.0, Vitest 4.1.6, and several other dev dependencies to their latest versions
1.0.26 —
Changed
Contact email updated — all contact references across the site now point to spectral@platvlak.com instead of the previous personal email address
Pro recovery emails — Magic Link recovery emails now arrive in the correct language matching your interface language, instead of always defaulting to English
Site-wide configuration — contact details, social links, and author references are now managed from a single central config for easier future updates
Fixed
Pro recovery email delivery — improved error logging in the Pro API so email delivery failures are properly reported instead of silently swallowed
1.0.25 —
Fixed
Language switching in the editor — switching languages while in the editor or library no longer produces broken URLs (e.g. `/deitor/`) and 404 errors; the language preference now updates in-place without navigation
1.0.24 —
Added
TIFF file import — Spectral can now open TIFF files (.tif / .tiff) via drag-and-drop or the file picker; files are automatically decoded and converted for editing
Dedicated loading overlay — a redesigned loading screen with a centred spinner, status message, and cycling tips gives better feedback while RAW files are being decoded
Changed
Sharpening quality upgraded — sharpening now uses a high-quality two-pass Gaussian blur pipeline (17×17 effective samples) instead of the previous single-pass radial approach, producing cleaner edge enhancement with fewer artefacts
Editor architecture streamlined — tool state (crop, gradient, compare slider, HSL target, white balance picker) is now provided through a unified context, reducing prop complexity and improving performance when switching between tools
Lazy-loaded translations — locale dictionaries are now loaded on-demand instead of bundled upfront, reducing the initial download size for every supported language
1.0.23 —
Added
Reset confirmations — added safety confirmation dialogs for all destructive reset actions (reset all, reset section, reset local adjustments) to prevent accidental loss of editing progress
File handler integration — Spectral can now be set as the default application to open supported image formats directly from your operating system's file explorer when installed as a PWA
Before / After showcase — added an interactive split-view showcase to the landing page to demonstrate grading capabilities
Founder story — added a new section on the landing page explaining the motivation behind building Spectral
Changed
Landing page design — polished the landing page with a refined, high-fidelity editorial aesthetic and improved mobile layouts
SEO & Localization — expanded search engine optimization with fully localized meta descriptions and page headings across all supported languages
UI color consistency — migrated remaining hardcoded colors to the central design system tokens for perfect dark mode consistency
1.0.22 —
Changed
DropdownPanel unification — all dropdown and menu components (PopoverMenu, ExportMenu, LUT export, Filmstrip filters, zoom menu) now use a single `DropdownPanel` compound component for consistent styling, entry animations, and checkbox indicators
Crop toolbar redesigned — the floating crop overlay has been replaced with a persistent, bottom-aligned toolbar inspired by Lightroom, improving discoverability and reducing accidental interactions
Straighten axis snapping — the straightening tool now snaps to the nearest 90° axis (horizontal or vertical), producing accurate corrections regardless of reference line orientation
Before/After slider accuracy — the split comparison now uses screen-space coordinates, keeping the divider perfectly aligned during canvas rotations and transformations
Feedback button repositioned — moved to a less intrusive location to prevent overlap with the editor workspace
Open source licenses updated — added missing attributions for clsx, canvas-confetti, jose, and other runtime dependencies on the licenses page
Sound effects lightweight — replaced the howler.js dependency with native `Audio` instances for overlapping playback, reducing bundle size
Loupe thumbnail refresh — edited photos now display their latest graded version in the Loupe view and project grid immediately after returning from the editor
1.0.21 —
Added
Loading tips — curated photography advice, feature discovery hints, and workflow shortcuts cycle with a fade animation while images and RAW files are loading
Onboarding tour expanded — new guided steps for the Filmstrip and Settings panels so first-time users discover photo navigation and preference controls
Tip test coverage — dedicated unit tests for the tip pool and the `useTip` cycling hook
Changed
Smoother library ↔ editor transitions — navigation between the library and editor is now instant without visual glitches; view transitions are reserved for photo grid reorder animations only
Filmstrip navigation refined — the filmstrip component uses a unified track and arrow layout across all views for consistent scrolling behaviour
Editor loading layout — the spinner, status label, and tip are grouped in a centred column that stays stable regardless of tip text length
Fixed
View transition flicker — eliminated the brief see-through flash that could appear when switching between the library and editor on fast machines
1.0.20 —
Changed
Dark theme consistency — enforced dark colour scheme at the browser level so form controls, dropdowns, and native elements always render with dark backgrounds and light text, matching the rest of the UI
Temperature slider gradient — the local adjustment temperature slider now displays a blue-to-warm gradient track, matching the colour section's temperature control for a more intuitive editing experience
Design token migration — converted remaining hardcoded spacing and layout values across multiple components to centralised design tokens for better visual consistency
Select dropdown styling — native `
Fixed
Production console cleanup — removed verbose logging from the database, export, and editor modules that previously cluttered the browser console in production; diagnostic output is now limited to development builds only
1.0.19 —
Added
Before / After Slider — drag an interactive split divider over the canvas to compare your graded image against the original in real time; accessible via the toolbar's new Compare button
Clipping previews — hold a modifier key while dragging Exposure, Highlights, Shadows, Whites, or Blacks sliders to see a live clipping mask overlay, making it easy to spot blown-out or crushed areas
Cookbook notification badge — a small counter on the Cookbook panel lets you know when new community recipes have been shared since your last visit
"Continuously Refined" messaging — a new card on the landing page explains that every tool in Spectral improves with each release
Roadmap "Live" badges — shipped features on the roadmap (Before / After Slider, Batch Grading) now display a checkmark badge so you can see what's already available
Changed
Noise reduction upgraded — replaced the basic bilateral filter with an à-trous wavelet algorithm that preserves fine detail while still removing luminance and chroma noise
Contrast slider refined — the S-curve math has been reworked to prevent solarization and colour clipping at extreme settings; adjustments now feel smooth across the full range
Language switching in the editor — changing language no longer reloads the page; all UI text updates in-place so your editing session stays intact
Halation rendering improved — multi-pass bloom and halation now use a dedicated texture pipeline, preventing visual glitches when combining multiple glow effects
RAW base profiles expanded — manufacturer-specific tone mappings updated for more natural out-of-camera starting points on Canon, Nikon, Sony, Fujifilm, and Olympus files
Fixed
Contrast solarization — fixed a shader bug where pushing contrast to extreme values produced colour inversions and harsh clipping instead of a gentle S-curve roll-off
Removed
Fujifilm recipe import — the automated camera recipe parser has been removed; all RAW files now start from neutral manufacturer base profiles for consistent, predictable results
1.0.18 —
Fixed
Pro license persistence — Pro status now reliably persists across page reloads and app updates; previously, Pro could deactivate after a refresh
Removed
Fujifilm recipe import — removed the manual recipe input feature; Spectral now focuses exclusively on its native recipe system
1.0.17 —
Added
PWA Pro License Sync — Pro license activations now synchronize in real-time between browser tabs and the installed PWA using BroadcastChannel, with a visibilitychange fallback for when the app is backgrounded
PWA-specific guidance in the Pro Recovery modal: when running as an installed app, the success screen now shows clear instructions on how to complete activation (switch back to app, close/reopen on iOS)
New `pro-recovery-pwa-hint` i18n key added to all 6 locales (EN, NL, DE, FR, ES, IT)
`ProRecoveryModal` now detects standalone mode and conditionally renders PWA instructions in the success state
1.0.16 —
Changed
Refactored `Filmstrip` to use a new reusable `FilmstripTrack` component for consistent track behavior across the app
Added scroll arrow navigation to the `Loupe` photo viewer's filmstrip for consistent behavior between the editor and project pages
1.0.15 —
Added
Cryptographic Access Control — Rolled out a new security backend using cryptographically signed JSON Web Tokens (ECDSA-P256) for verifying Spectral Pro licenses over the network
Secure Token Utilities — Implemented frontend and backend worker logic to rigorously verify active license signatures
Changed
Refactored `useProStatus` to correctly support asynchronous external validation on app boot
Security enhancement: Hardened development and staging environments to prevent unauthorized bypassing of license checks
1.0.14 —
Changed
Domain migration — all references updated from `spectral.platvlak.nl` to `spectral.platvlak.com` (CNAME, Astro config, CORS origins, workers, robots.txt, OG images)
OG images regenerated with correct Spectral logo matching `favicon.svg` — now produces all 6 locale variants in a single script run
Cloudflare Web Analytics token updated for new `.com` domain
Mollie coffee payment link updated to new payment URL
`generate-og.mjs` rewritten to match favicon exactly: diamond with spectral gradient edges, inner gem with gradient stroke, locale-aware taglines
DEPLOY.md DNS instructions updated for `platvlak.com` domain
i18n completeness test expanded from NL-only to all 5 locales (168 tests, 1556 total)
Changelog preview titles migrated from hardcoded English to i18n translation keys (`titleKey`)
Release workflow updated with `titleKey` documentation for changelog preview
Removed
`canvas` devDependency — only needed locally for OG image generation, not for CI builds
1.0.13 —
Added
Full platform localization — all 6 locales (EN, NL, DE, FR, ES, IT) now have complete translations with 1173 keys each
New translation dictionaries: `de.ts`, `fr.ts`, `es.ts`, `it.ts` — 4 new locale files with full coverage
Localized blog content — 10 articles translated into DE, FR, ES, IT, and NL (50 new blog posts total)
Localized changelog page (`[lang]/changelog.astro`) — serves `/nl/changelog/`, `/de/changelog/`, etc.
Localized blog overview page (`[lang]/blog/index.astro`) with translated titles, categories, and reading time
Localized OG images for NL, DE, FR, ES, IT with translated taglines
`RoadmapPreview` component on the landing page for upcoming Pro features
`Select` UI component for dropdown form fields
E2E routing spec for locale switching and 404 handling
Changed
Locale routing expanded — all content pages (`about`, `community`, `gallery`, `licenses`, `maker`, `privacy`, `terms`, `changelog`, `blog`) now generate routes for all 5 non-EN locales via `[lang]` dynamic segments
Locale default changed from `'nl'` to `'en'` across all page files — English is the universal fallback
SiteNav `localizeHref` now supports all 6 locales (was NL-only)
Landing page components (`HeroCtas`, `FlowSteps`, `ProBanner`, `ChangelogPreview`) now use locale-aware `href` links via `getCurrentLanguage()`
404 page detects all 6 locales from URL path and localizes editor link
ContentLayout CSS `hyphens` property now language-agnostic (was NL/EN only)
Layout JSON-LD `featureList` now uses dynamic translation keys instead of hardcoded English
LicensesContent section headings (`Core Framework`, `UI & Icons`, etc.) now use i18n keys
Blog layout refactored with translated `readingTime` and `backLabel`
SiteNav hardcoded `aria-label="Change Language"` replaced with dynamic i18n key
E2E tests switched from Dutch (`nl-NL`) to English (`en-US`) locale with English text matchers
Release workflow updated with step 6b for syncing `[lang]/changelog.astro`
Changelog preview titles migrated from hardcoded English to i18n translation keys
Domain migration — all references updated from `spectral.platvlak.nl` to `spectral.platvlak.com` (CNAME, Astro config, CORS origins, OG images, workers, robots.txt)
i18n completeness test expanded from NL-only to all 5 locales (84 new tests, total now 1556)
Fixed
French translation build error — fixed double-escaped apostrophe in `fr.ts` (`jsonld-feature-3`) that caused esbuild parse failure
`BlogLayout.astro` edge case where `pubDate` was not a Date object — added `new Date()` wrapper
Removed
Unused Inter font — removed `@font-face`, ``, and `Inter-Variable-latin.woff2` (48KB saved)
Unused `donateUrl` variable from `AboutContent.astro`
Migrated inline SVGs to a centralized `Icon` component to improve accessibility (`aria-hidden`) and streamline markup
Normalized CSS fallbacks across UI components, removing hardcoded hex values in favor of strict CSS variables for better theming consistency
Fixed
Further refined Spectral Pro email templates with robust layout tables (`bgcolor`) ensuring perfect dark-theme contrast and compatibility across rigidly styled email clients (like Outlook) without relying on MJML
1.0.11 —
Added
Expectations Disclaimer — a transparent breakdown on the landing page to manage expectations around browser-based RAW processing and the "indie project" model
Pro Banner Recovery — integrated a direct "Restore purchase" link inside the Pro Banner for returning users who cleared their cache
Changed
Refined English and Dutch copy across the landing page for a more natural, authentic tone
Improved accessibility and focus styles across multiple UI components
1.0.10 —
Fixed
Updated Spectral Pro email templates with full HTML structure and explicit dark backgrounds to prevent readability issues in certain email clients
Fixed a syntax error in Dutch localization (`nl.ts`) regarding apostrophes in disclaimer text that caused the build to crash
1.0.9 —
Changed
Refined free and Pro messaging for Spectral — emphasizing affordability and clarifying Pro features as a one-time purchase
Updated liability and privacy statements (Terms of Service / Privacy Policy) to clarify Mollie payment processing and implement a liability cap
Removed
Removed outdated `data-store.json` to simplify project structure
1.0.8 —
Added
Spectral Pro — one-time purchase (€20) that unlocks Effects, Camera Calibration, and Local Adjustments via a gated paywall with upgrade modal, feature checklist, and Mollie checkout
Pro upgrade modal with email input, feature list, and one-click checkout flow to Mollie payment page
Pro recovery modal — restore a previously purchased license via Magic Link email (powered by Resend)
Pro badge on section headers (Effects, Calibration, Local Adjustments) indicating which sections require Pro
Golden "PRO" badge next to the SPECTRAL logo in both the Editor and Library top bars when Pro is active
`ProGate` component — locks Pro-only section content behind a sleek overlay with unlock call-to-action
`ProBadge` component — reusable pill badge for marking Pro features throughout the UI
`useProStatus` hook — manages Pro license lifecycle with localStorage persistence, URL activation (`?pro=1`), and payment status polling
Pro licensing utilities (`pro.ts`) with `isPro()`, `loadProStatus()`, `saveProStatus()`, and admin bypass via `?admin=1` URL parameter or `spectral-pro-admin` localStorage key
Pro API client (`pro-api.ts`) for checkout, status polling, and Magic Link recovery requests
Cloudflare Worker API (`workers/pro-api/`) — handles Mollie payment creation, webhook verification, KV license storage, and Resend Magic Link email delivery
Worker deployment documentation (`DEPLOY.md`) with KV setup, secrets management, and DNS configuration
Pro banner on English and Dutch landing pages linking to the editor upgrade flow
30+ new i18n keys for Pro UI strings in English and Dutch
11 new unit tests for Pro licensing utilities (`pro.test.ts`)
9 new E2E test cases for Pro gating, upgrade modal, admin bypass, and unlock verification (`editor-pro.spec.ts`)
`PUBLIC_PRO_API_URL` environment variable in GitHub Actions deploy workflow
Changed
Controls component updated to wrap Effects, Calibration, and Local Adjustments sections in `ProGate`
E2E test helpers updated with locale-independent selectors (EN/NL dual matching) and `RegExp` support in `openSection`
CSP headers updated to allow connections to the Pro Worker API
1.0.7 —
Added
Reconnect originals — restore photos from backup and re-link full-resolution files by selecting a folder with your originals; matched by filename with progress reporting and unmatched file warnings
Reconnect banner in `ProjectDetail` — automatically detects disconnected photos after backup restore and shows a prominent call-to-action to re-link originals
`getDisconnectedPhotoCount()` and `reconnectPhotos()` database utilities for tracking and resolving backup-restored photos missing their original files
`needsReconnect` field on `LibraryPhoto` records — set to `true` for backup-restored photos, cleared when originals are successfully reconnected
10 new i18n keys for reconnect flow (EN + NL) — banner, progress, toast, and tooltip strings
Import/export icon buttons in the Cookbook section header for quick access to recipe management
Changed
Cookbook UI modernized — replaced inline `+` save button with a full-width "Save Recipe" CTA at the bottom of the panel; recipe list is now the primary content above the save form
Section component refactored — header toggle zone separated from `headerExtra` content so that clicking action buttons (import, export) no longer accidentally collapses the section
Look Generator removed from Controls panel — `generateLook` and mood state extracted; `FiltersSection` simplified by removing look generator UI
Unused `RecipeInputModal.module.css` import removed from `Cookbook.tsx`
Backup export now skips the empty "Unsorted" default project to prevent clutter on restore
Backup restore deduplicates recipes and custom LUTs to prevent duplicates across repeated restores
Backup restore reuses the existing "Unsorted" project instead of creating a duplicate
Improved error handling in backup restore — descriptive messages for missing `DecompressionStream`, corrupted JSON, and malformed backup structures
Fixed
Section header actions (import/export buttons) no longer toggle the section's collapsed state — click events properly isolated via separated toggle zone
Recipe validation now handles edge cases with stricter sanitisation
`ShareRecipeModal` — two bare English strings ("Preview" label and `alt` text) wrapped with `__()` for proper i18n support
1.0.6 —
Added
Full backup & restore — export all projects, photos, recipes, custom LUTs, and settings as a single compressed file; restore from any backup to pick up where you left off
Backup status indicator in the Projects overview showing time since last backup and estimated file size
File System Access API integration — save backups directly to cloud-synced folders (iCloud Drive, Google Drive, Dropbox) on supported browsers; standard download fallback on others
Restore confirmation dialog with import summary (project/photo/recipe/LUT counts) before committing
Progress overlays for both backup and restore operations
18 new i18n keys for backup/restore UI (EN + NL)
19 new tests for full backup validation, `formatBytes`, and `previewFullBackup` — test suite now at 87 files, 1461 tests
Fixed
`CommunityRecipes` — resolved TypeScript error where `full.category` was accessed on `SharedRecipe` (migrated to `full.tags?.[0]`)
`CookbookAdmin` — resolved TypeScript error in tag rendering where a `category` fallback was used on a type that only has `tags`
TypeScript compilation now passes with zero errors
Changed
Blog article "Your Photos Deserve Privacy" updated — backup section rewritten to highlight the new one-click backup feature instead of presenting local-first storage as a trade-off
1.0.5 —
Added
Illustrative screenshots embedded in blog articles — tone curves, HSL panel, full editor view, LUT export dialog, gradient tool, and applied LUT examples
Image styling for markdown content images in `ContentLayout` — responsive sizing, rounded corners, and subtle shadow
Changed
Blog articles enriched with personal photography workflow details, gear preferences, and first-hand editing experiences for a more authentic voice
Editorial content column widened from 65ch to 75ch for improved readability on larger screens
Body copy typography updated to fluid sizing (`clamp(1.0625rem, 1rem + 0.25vw, 1.125rem)`) with relaxed 1.8 line height
About and Maker page copy refined with subtle emoji accents in both English and Dutch translations
1.0.4 —
Fixed
Crash when applying community recipes with missing nested state objects (curves, HSL, colorWheels, bwMixer, calibration) — corrupted data from incomplete recipe settings caused cascading TypeErrors across the WebGL renderer, histogram, and offscreen export pipeline
`migrateState()` now deep-merges all nested state objects instead of shallow-spreading, preventing `undefined` sub-fields from overwriting safe defaults when loading photos from IndexedDB
`sanitizeSettings()` handles `undefined` selectedFilter without crashing on `.startsWith()` call
`curvesAreIdentity()` and `buildCurveTexture()` no longer crash on undefined or partial curves objects
`buildHistogramRefreshKey()` guards against missing curves and HSL state
WebGL render loop guards `halationColor` and `bwTintColor` tuples with `DEFAULT_STATE` fallbacks
Offscreen render pipeline guards all nested state properties (colorWheels, HSL, bwMixer, calibration)
`applySectionMix()`, `isEdited()`, and `getSectionDirtyState()` handle corrupted or partial EditorState objects
CSS media query syntax error in `reset.css` — invalid `@media not (hover: hover) and (pointer: fine)` corrected
Changed
Recipe import (`applyRecipe`) now sanitizes all settings through `sanitizeSettings()` before applying, ensuring community recipes with missing fields get proper defaults
Astro configuration updated with blog content collection and sitemap integration
Expanded i18n translations for new pages, navigation items, and community features
Project documentation (AGENT.md) consolidated for efficient AI agent onboarding
Added
Community Cookbook gallery — browse, search, and import shared recipes from a public gallery powered by a Cloudflare Worker API
Recipe sharing modal — share your grading recipes to the community gallery with title, description, and tags
Cookbook admin panel (`/admin/cookbook/`) for moderating submitted recipes
Blog section with 10 SEO-optimized articles on color grading, LUTs, RAW editing, tone curves, and privacy
Blog layout with article listing page, individual article pages, and reading time estimates
Community page for discovering shared recipes and connecting with other photographers
Gallery page showcasing sample edits and use cases
Maker page with creator background and project story
Custom 404 error page with navigation back to the app
Dutch localized variants for all new content pages (about, community, gallery, maker, privacy, terms, licenses)
`llms.txt` machine-readable project summary for AI agent discoverability
Seed script for populating the cookbook API with sample recipes during development
Editorial and copywriting brand guidelines for consistent user-facing text
Cookbook API Cloudflare Worker with recipe CRUD, moderation, search, and CORS support
1.0.2 —
Added
Comprehensive E2E test suite — 8 new Playwright spec files covering editor load, tone controls, crop, filters, panels, shortcuts, undo/redo, export, and navigation
Reusable E2E helper module (`e2e/helpers/editor.ts`) with shared functions for seeding test data, navigating to the editor, dismissing tours, and interacting with sliders
Playwright configuration with `webServer` auto-start, `nl-NL` locale, and Chromium-only project
`BrowserGate` component — blocks rendering with a friendly message when WebGL 2 is unavailable instead of crashing
`histogram-core.ts` module — extracted `tallyPixels`, `computePixelStats`, and `smoothBins` from the Web Worker for shared use and easier testing
`canvasToBlob` and `blobToImage` exported from `export.ts` as shared utilities, eliminating duplicate implementations in `batch-export.ts` and `share.ts`
New tests for `crop.ts`, `project-export.ts`, `export.ts`, `hsl-target.ts`, `view-transitions.ts`, and `lut-export.ts`
Test fixture photo (`e2e/fixtures/test-photo.jpg`) generated via canvas for deterministic E2E seeding
Changed
Histogram Web Worker refactored to import pure functions from `histogram-core.ts` — reduced from ~120 lines to ~20 lines
Playwright `webServer` config — auto-starts the dev server when running `npm run test:e2e`
Vite error overlay auto-dismiss via `MutationObserver` in `addInitScript` — prevents pointer event blocking in dev
`openSection` helper now checks `aria-expanded` before clicking to prevent accidentally collapsing open sections
Changed
All E2E `waitForTimeout` calls replaced with proper Playwright waits (`waitFor`, `expect.poll`, `toBeVisible`) — suite runs in 2.4 min instead of 8 min
All silent `if (isVisible())` guards replaced with mandatory `expect().toBeVisible()` assertions — tests now fail on missing UI instead of silently passing
`expect(true).toBeTruthy()` soft-pass in export tests replaced with real UI assertions
Platform-aware keyboard shortcuts in undo/redo tests (`Meta` on Mac, `Control` on Linux/Windows)
Quality badge test uses DOM text (`High/Medium/Low`) instead of CSS-rendered uppercase
`getByText('BEWERKEN')` updated to match actual DOM casing (`Bewerken`)
`ERR_CONNECTION_REFUSED` when running E2E tests without a running dev server
Vite error overlay blocking all pointer events during test navigation
Duplicate comment in `editor.ts` helper
Incorrect dev server URL in README (`/spectral/` → `/`)
1.0.0 —
Added
Browser compatibility gate — shows a friendly message when WebGL 2 is unavailable instead of crashing
Comprehensive test suite hardening — 87 test files, 1442 tests, all passing
New test coverage for `hsl-target.ts` (rgbToHsl, channel weights), `view-transitions.ts`, `lut-export.ts` (identity image, .cube formatting), and extended tests for `crop.ts`, `project-export.ts`, `export.ts`
Exported `createIdentityImage` and `formatCubeFile` from `lut-export.ts` for testability
Changed
Feedback modal title updated from "Beta Feedback" to "Feedback"
README updated with browser compatibility table and stable release URLs
Beta badge and banner automatically hidden (version-based `IS_PRERELEASE` flag)
Fixed
All 9 TypeScript compiler errors resolved (test fixtures, type guards, mock types)
All 4 ESLint warnings resolved (unused imports, missing dependencies)
Vite chunk size warnings eliminated via `manualChunks` build configuration
0.2.0-beta.11 —
Added
Settings modal with tabbed interface for Performance, Editor, Export, and General preferences (RAW decode quality, auto-tone, slider hints, undo history limit, canvas background)
View Transition API integration for animated photo grid reordering during filter and sort changes
Crossfade photo transitions in the editor with reduced-motion support
Comprehensive test suite hardening — 10 new test files covering `useHslTarget`, `useWbPicker`, `useRecipePreview`, `useBatchExport`, `usePhotoContextMenu`, `useEditorSounds`, `SliderDragContext`, `useCanvasBounds`, `cx`, and `web-locks`
Global `localStorage` polyfill (`test-setup.ts`) for Node v25 compatibility in the test runner
Changed
Replaced hardcoded UI strings with internationalized labels across Controls, EditorTopBar, Filmstrip, Loupe, and export components
Added focus ring and touch device styles for improved keyboard and mobile accessibility
Optimized CSS with consistent component styling, spacing tokens, and responsive adjustments
Test suite expanded from 76 → 86 files and 1346 → 1412 tests with zero failures
Fixed
Module-level `localStorage` access in `i18n.ts` now safely guards against incomplete Storage implementations, resolving 14 failing test files
0.2.0-beta.10 —
Added
Numbered 3-step workflow section on the landing page (Import → Grade → Export) with animated step indicators
Changelog preview component on the landing page showing the latest release highlights
Contextual hint icons on editor sliders to aid user understanding of each control
Import result toast notifications — clear feedback after batch photo imports
Responsive design skill and guidelines for cross-device layout adaptation
Changed
Merged filter bar and selection bar in the library into a single streamlined toolbar, reducing visual clutter
Smoother opacity transitions across interactive UI elements for improved responsiveness
Enhanced press and hover interaction states with tactile feedback effects
Refined pseudo-element styling for better slider group visual separation
Improved visual consistency across subtle UI elements (borders, shadows, spacing)
0.2.0-beta.9 —
Added
Resizable editor panels — drag the edges of the left and right panels to adjust their width, persisted across sessions
`ResizeHandle` component with accessible `separator` role, pointer-capture drag, and col-resize cursor feedback
`SliderDragContext` for half-resolution proxy rendering while dragging sliders — reduces GPU workload during interaction
"As Shot" (neutral) white balance preset with Aperture icon as the default WB state
Icons for all white balance presets (Sun, Cloud, TreePine, Lightbulb, CircleDot, Zap)
Local adjustments now applied during HQ export — each enabled gradient is composited in a multi-pass WebGL pipeline
Export status overlay with smooth fade transition instead of conditional mount (prevents flicker)
Internationalized export status strings (RAW decoding, filter application) in English and Dutch
"No photos match filters" empty state message for the library
Export quality picker — choose between high, medium, and low quality when exporting photos
Compact export menu variant for the library selection banner with quality badge indicator
Changed
Landing page English content visible by default (no `display:none`) for improved SEO and First Contentful Paint
IndexedDB migration logic consolidated — fresh installs now create the full v6 schema in a single step instead of replaying six incremental migrations
`redo()` in edit history now synchronises `stateRef` before calling `setState`, fixing a stale-ref bug
Feedback modal heading uses an explicit `id` for `aria-labelledby` focus management
"Select All" and shift-click range selection now operate on the filtered photo list instead of all photos
Batch export accepts a quality parameter, defaulting to high quality
Fixed
Redo state sync — `stateRef.current` was not updated during redo, causing subsequent edits to reference stale state
Export overlay no longer flickers when toggling between status messages
Shift-click multi-select no longer selects photos hidden by the active filter
0.2.0-beta.7 —
Added
Web Share API integration — share photos via the native OS share sheet or copy to clipboard from the library
Batch sharing — select and share multiple photos at once from the project library
Custom SVG cursors for all editor tools — crosshair, eyedropper, grab/grabbing, rotate, resize handles, and a Lightroom-inspired target-adjust cursor for the HSL tool
Grabbing cursor state on slider thumb interaction for improved tactile feedback
Keyboard shortcut for sharing photos from the library
`LibraryTopBar` component — dedicated top bar for the library module with search and actions
Changed
Filmstrip filter bar redesigned with surface-level hierarchy instead of horizontal dividers
Keyboard shortcuts modal split into more granular categories (rating, labels) for better scannability
HSL Targeted Adjustment Tool automatically deactivates when switching to other tools or navigating between photos
Crop tool edge dragging improved — single-edge dragging now works reliably after initial adjustment
Context menu streamlined — color labels moved exclusively to right-click menu, rating options removed from context menu
Share functionality restricted to the library module — removed from the editor for a cleaner develop workflow
Fixed
Crop tool drag handles no longer collapse the crop rectangle due to incorrect clamping logic
Filmstrip no longer disappears when filtering on non-existent criteria
0.2.0-beta.6 —
Added
View Transitions API integration — smooth morphing animations between library grid and editor views
Compression Streams API for gzipped project exports — smaller, faster `.spectral` archive downloads
Web Locks API — prevents data corruption when multiple tabs access the IndexedDB simultaneously
Histogram computation offloaded to a dedicated Web Worker for non-blocking UI performance
LRU-based undo history pruning — automatically evicts oldest entries to bound memory usage
Changed
ARIA landmarks and keyboard-accessible skip links refined for improved screen reader navigation
0.2.0-beta.5 —
Added
Loupe photo viewer — Lightroom-style fullscreen culling view with star rating, color labels, and keyboard navigation
Full-resolution image loading in Loupe — loads the embedded JPEG preview (up to 6240×4160) from IndexedDB on-demand, with the thumbnail as instant placeholder
Prefetch of next/previous photos in the Loupe for instant arrow-key navigation
Multi-file recipe import — import multiple `.json` recipe files at once in the Cookbook
Skip-to-content link and ARIA landmarks (`main`, `banner`, `navigation`) for screen reader accessibility
Dutch translations for Loupe, recipe import, and accessibility labels
Changed
Extracted filter/sort logic from `ProjectDetail` into dedicated `useLibraryFilters` hook for maintainability
Extracted collapsible section state into `useSectionState` hook
Refactored editor component internals for reduced complexity
Fixed
Loupe now shows full-quality images immediately — previously only showed blurry 600px thumbnails until the photo was opened in the editor
0.2.0-beta.4 —
Added
Arrow key navigation in the filmstrip — press ← / → to cycle through photos like a carousel