Fixed TypeError when updatedAt field from JSON responses was incorrectly
treated as Date object. Added type guards to handle both string and Date
types in autosave callbacks across all admin forms.
- Refactor EssayForm to use useDraftRecovery and useFormGuards composables
- Refactor AlbumForm to add autosave and use composables
- Refactor posts edit page to use composables
- Replace inline draft recovery logic with useDraftRecovery composable
- Replace inline form guards with useFormGuards composable
- Replace inline draft banners with DraftPrompt component
- Remove ~200 lines of duplicated code across forms
- Maintain zero lint errors throughout refactoring
Co-Authored-By: Justin Edmund <justin@jedmund.com>
Fixed accessibility errors across multiple component categories:
**Admin Modal Components (7 errors fixed):**
- BaseModal: Added role="presentation" to backdrop, role="dialog" to modal
- BaseModal: Added tabindex and keyboard handlers
- MediaDetailsModal: Added track element for video captions
**Admin Form Components (2 errors fixed):**
- EssayForm: Changed label to div for Tags section
- PhotoPostForm: Changed label to div for Caption section
**File Upload Components (11 errors fixed):**
- FileUploadZone: Added role="region" and aria-label to drop zone
- GalleryManager: Changed label to div, added role="button" to draggable items
- GalleryUploader: Added role, aria-label, tabindex to drop zones and gallery items
- ImagePicker: Changed label to div
- ImageUploader: Changed label to div, added role/aria-label to drop zone
- MediaInput: Changed label to div
**Admin List Components (4 errors fixed):**
- PostDropdown: Added role="menuitem", tabindex, keyboard handler to menu items
- PostListItem: Changed article to div with role="button", added keyboard handler
**Public UI Components (14 errors fixed):**
- AppleMusicSearchModal: Added role="presentation" to overlay, role="dialog" to container
- Avatar: Added role="presentation" to hover container
- Lightbox: Added role="dialog", tabindex, keyboard handlers
- ProjectContent: Fixed redundant alt text on gallery images
- Slideshow: Added role="button", tabindex, keyboard handlers to clickable images
- TiltCard: Added role="presentation" to tilt container
**Editor Components (5 errors fixed):**
- LinkEditDialog: Added role="dialog" and tabindex
- UrlEmbedExtended: Changed role from "article" to "button" for interactive embed cards
**Route Pages (2 errors fixed):**
- admin/media/upload: Added role="region" and aria-label to drop zone
- photos/[id]: Added role="presentation" to mouse tracking container
Total: 45 accessibility errors fixed (109 → 64 errors remaining)
Phase 1 Batch 6: Apple Music Client type safety improvements
Fixed 10 any-type errors in 1 file:
src/lib/server/apple-music-client.ts (10 errors)
- Created ExtendedAppleMusicAlbum interface with _storefront property
- Created ExtendedAttributes interface for synthetic album attributes
- Created SyntheticAlbum interface for song-to-album conversions
- Fixed findAlbum: first matchedAlbum cast (line 336)
- Fixed findAlbum: second matchedAlbum cast (line 409)
- Fixed findAlbum: synthetic album return type (line 433)
- Fixed transformAlbumData: parameter type to AppleMusicAlbum | SyntheticAlbum
- Fixed transformAlbumData: isSingle check using ExtendedAttributes (lines 465-471)
- Fixed transformAlbumData: _storefront access using ExtendedAppleMusicAlbum (line 480)
- Fixed transformAlbumData: tracks filter/map to use AppleMusicTrack type (lines 498-499)
Progress: 22 any-type errors remaining (down from 32)
Phase 1 Batch 4: Metadata & Content type safety improvements
Fixed 16 any-type errors across 2 utility files:
1. src/lib/utils/metadata.ts (10 errors)
- Created JsonLdObject type (Record<string, unknown>)
- Updated MetaTagsOptions.jsonLd to use JsonLdObject
- Updated GeneratedMetaTags.jsonLd to use JsonLdObject
- Updated all JSON-LD generator functions:
* generatePersonJsonLd: return type and jsonLd variable
* generateArticleJsonLd: return type and jsonLd variable
* generateImageGalleryJsonLd: return type and jsonLd variable
* generateCreativeWorkJsonLd: return type and jsonLd variable
2. src/lib/utils/content.ts (6 errors)
- Added imports for TiptapNode and EditorData types
- Created Mark interface for text mark types
- Added marks field to ContentNode interface
- Fixed renderInlineContent: content parameter to ContentNode[]
- Fixed renderInlineContent: node parameter to ContentNode
- Fixed renderInlineContent: mark parameter to Mark
- Fixed getContentExcerpt: content parameter to EditorData | unknown
- Fixed extractTiptapText: doc parameter to Record<string, unknown>
- Fixed extractTiptapText: node parameter to ContentNode
Progress: 51 any-type errors remaining (down from 67)
Phase 1 Batch 3: Route Pages type safety improvements
Fixed 10 any-type errors across 7 route page files:
1. src/routes/+page.ts (1 error)
- Added PaginationInfo interface for fetchProjects return type
2. src/routes/admin/+layout.svelte (1 error)
- Changed children prop from any to Snippet type
3. src/routes/admin/albums/+page.svelte (1 error)
- Changed Album.content from any to EditorData type
4. src/routes/admin/universe/+page.svelte (1 error)
- Changed form prop from any to Record<string, unknown> | null | undefined
5. src/routes/albums/[slug]/+page.svelte (4 errors)
- Added AlbumPhoto and AlbumData interfaces
- Fixed photo map parameters to use AlbumPhoto
- Fixed extractContentPreview to accept EditorData | null
- Fixed generateAlbumJsonLd to accept AlbumData
6. src/routes/albums/+page.svelte (1 error)
- Changed coverPhoto.colors from any to ColorPalette[]
7. src/routes/photos/[id]/+page.svelte (1 error)
- Changed navigateToPhoto parameter from any to PhotoItem | null
Progress: 67 any-type errors remaining (down from 77)
Phase 1 Batch 2: Logger & Simple Utilities
Replaced any types with proper TypeScript types across 3 files:
- logger.ts: Created LogContext type, added RequestEvent import from SvelteKit
- Defined LogContext = Record<string, string | number | boolean | null | undefined>
- Changed all context parameters from Record<string, any> to LogContext
- Changed event parameter in createRequestLogger from any to RequestEvent
- extractEmbeds.ts: Used TiptapNode type from editor.ts
- Changed content and node parameters from any to TiptapNode
- global.d.ts: Improved SVG module declarations
- Changed *.svg from any to string (raw SVG content)
- Changed *.svg?component from any to Component<any> (Svelte component)
Progress: 199 → 185 errors (91 → 77 any-type errors)
Phase 1 Batch 1: Type Definitions
Replaced any types with proper TypeScript types across 5 type definition files:
- apple-music.ts: Added AppleMusicArtistAttributes, changed type guards to use unknown
- editor.ts: Changed any to unknown for flexible block/node attributes
- lastfm.ts: Defined editorialNotes structure, changed rawResponse to unknown
- project.ts: Changed caseStudyContent to EditorData type
- photos.ts: Defined ColorPalette interface for color data
Progress: 207 → 199 errors (103 → 91 any-type errors)
- Restore AlbumForm handleSave() and validateForm() functions
- Add back missing imports (goto, zod, Button, toast)
- Restore isSaving and validationErrors state
- Add back albumSchema validation
This fixes the critical issue where AlbumForm had no way to save albums
due to over-aggressive dead code removal in previous cleanup.
Also update docs/eslint-cleanup-plan.md to reflect:
- Current branch status (207 errors remaining)
- Quality review of previous LLM work (84% good, 1 critical issue fixed)
- Detailed breakdown of remaining errors
- Actionable roadmap for completing the cleanup
Fixes P0 production error where projects failed to load due to missing
database columns. The schema was updated in commit 12d2ba1 to add three
Boolean fields (showFeaturedImageInHeader, showBackgroundColorInHeader,
showLogoInHeader) but no migration was created.
This migration adds the missing columns to the Project table with their
proper defaults (all true), resolving the "column does not exist" error
in production.
- add ContentNode interface for content rendering
- replace any with proper types in content.ts (15 -> 6 errors)
- use Record<string, unknown> for dynamic content objects
- add type assertions for content arrays
- replace any with Prisma types (Post, Project, Album, Media)
- use Component type for Svelte component parameters
- use Snippet type for Svelte 5 render slots
- use Record<string, unknown> for dynamic objects
- add proper type guards for error handling
- fix editor extension types with proper generics
- all frontend components now have zero any type errors
- fix edra placeholder components with proper editor context types
- fix gallery image types with proper type assertions
- fix ProseMirror transaction types in link manager
- fix command types in composer toolbar
- replace any with unknown where type is dynamic
- use Leaflet types (L.Map, L.Marker, L.LeafletEvent) for map components
- use Post and Project types from Prisma for form components
- use JSONContent type for editor instances
- use Snippet type for Svelte 5 render functions
- use EditorView type for TipTap/ProseMirror views
- use proper type guards for error handling
- add editor interface types for save/clear methods
- use Prisma.JsonValue and Prisma input types throughout
- add proper type guards for array and object checks
- replace any with Record<string, unknown> where appropriate
- all API/RSS routes now have zero any type errors