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
- 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
- add ProjectUpdateBody interface for partial updates
- use Prisma.ProjectUpdateInput for update operations
- replace all remaining any types in projects endpoints
- consistent use of proper types across all API routes
- add AlbumPhoto, BlockContent, AppleMusicData types
- add ProjectCreateBody interface for request validation
- use Prisma.ProjectWhereInput for query filters
- use Prisma.JsonValue for JSON fields
- add proper type guards for content validation
- add ContentNode, GalleryItem, TextNode, ParagraphNode, DocContent types
- use Prisma.JsonValue for JSON column content
- use Prisma.ProjectUpdateInput and Prisma.PostUpdateInput for update payloads
- improve type guards for content filtering
- replace any[] with never[] for empty placeholder arrays
- add GalleryItem type for media/gallery item unions
- add EdraCommand import for editor command types
- add Post, Media imports from Prisma
- add BlockContent, DraftPayload, PostPayload, PhotoPayload types
- replace any with proper types in form handlers and callbacks
- use unknown for truly dynamic data, Record types for object props
Replace broken text extraction logic with renderEdraContent() which correctly handles TipTap marks including links, bold, italic, etc.
Before: Links were stripped from RSS content (only plain text extracted)
After: Full HTML with proper links, formatting preserved in CDATA sections
Files updated:
- src/routes/rss/+server.ts: Main RSS feed
- src/routes/rss/universe/+server.ts: Universe RSS feed
Fixes issue where content.blocks was expected but TipTap uses content.type='doc' format.
Migrate remaining Svelte 4 reactive statements to Svelte 5 $derived:
- media/audit/+page.svelte: Convert allSelected, hasSelection, selectedSize to $derived
- universe/compose/+page.svelte: Convert postType, initialContent to $derived
- Also migrated all let declarations to $state() in audit page for consistency
All reactive statements now use Svelte 5 runes mode.