- Change OG HTML redirect to use ?_spa=1 query param instead of redirecting to /
- Simplify vercel.json rewrites: serve SPA when _spa=1, otherwise serve OG HTML
- Remove brittle user-agent detection patterns
- Add cleanup effect to strip _spa param from URL after SPA loads
- Fixes refresh redirect regression while maintaining OG preview support
- Add fetchFirstEvent helper that resolves on first event (not waiting for complete)
- Add fetchAuthorProfile helper for DRY author fetching
- Refactor fetchArticleMetadataViaRelays to:
- Return immediately when first article event arrives (no 7s wait)
- Fetch author profile with 400ms micro-wait (connections already warm)
- Optional hedge: try again with 600ms if first attempt fails
- Fallback to pubkey prefix if profile not found
- Add logging to track article fetch and author resolution source
This dramatically improves first-request latency by returning as soon as
any relay responds, while still attempting to get author name with
minimal additional delay (400-600ms total).
- Add tags field to ArticleMetadata type (extracted from 't' tags)
- Add imageAlt field to ArticleMetadata type (uses title as fallback)
- Extract 't' tags from article events in fetchArticleMetadataViaRelays
- Generate multiple article:tag meta tags in HTML output
- Add og:image:alt meta tag for better accessibility
This improves SEO and social media previews by including
article categorization tags and image descriptions.
Remove Promise.race timeout wrapper and let relay fetch use its natural
timeouts (7s for article, 5s for profile). Remove background refresh
complexity entirely.
Flow is now simple:
1. Check Redis cache
2. If miss, fetch from relays (up to 7s)
3. Cache result
4. Subsequent requests hit cache
First request may take 7-8 seconds, but after that it's cached and fast.
Much simpler and more reliable.
Add more detailed logging to diagnose background refresh issues:
- Log the exact URL being called
- Log whether secret is present
- Better error handling for non-JSON responses
- More detailed error messages
This will help identify if the refresh endpoint is being called
and why we're not seeing logs from it.
Relays can be slow, especially on first connection. Increase timeout
to 5 seconds to give relays more time to respond before falling back
to default metadata.
Add detailed logging to verify background refresh is working:
- Log when background refresh is triggered
- Log the response status and result from refresh endpoint
- Log errors if refresh fetch fails
- Add logging in refresh endpoint to track:
- When refresh starts
- When metadata is found
- When metadata is cached
- Any errors during refresh
This will help diagnose if background refresh is actually
populating the Redis cache after timeouts.
- Remove gateway HTTP fetch entirely
- Fetch directly from relays on cache miss with 3s timeout
- If relay fetch succeeds: cache and return article metadata
- If relay fetch fails/times out: return default OG and trigger background refresh
- Update logging to reflect relay-first strategy
- Keep background refresh endpoint for eventual consistency
This simplifies the code and removes dependency on unreliable gateway,
while ensuring fast responses and eventual correctness via background refresh.
Add comprehensive logging to diagnose why gateway fetch is failing:
- Log the exact URL being fetched
- Log HTTP status on failure
- Log response length on success
- Log which OG tags were found/missing
- Add detailed error information
This will help identify if the issue is:
- Fetch timeout/failure
- Missing OG tags in response
- Regex pattern mismatch
- Support both KV_* and UPSTASH_* env var names for Redis
- Add error handling for Redis get operations
- Add console logging to track cache hits/misses and gateway fetches
- Fix syntax error in background refresh trigger
This will help diagnose why article metadata isn't being returned correctly.
ESM requires explicit file extensions in import paths. Add .js
extensions to all relative imports in API files and services,
even though source files are .ts (they compile to .js).
This fixes ERR_MODULE_NOT_FOUND errors on Vercel.
- Move ogStore, ogHtml, and articleMeta from src/services/ to api/services/
- Update imports in article-og.ts and article-og-refresh.ts
- Update import paths in articleMeta.ts (lib/profile and src/config/relays)
- Remove old files from src/services/
- Clean up ESLint config to only reference api/**/*.ts
This fixes the ERR_MODULE_NOT_FOUND error on Vercel by ensuring
serverless functions can access the service modules.
- Add ogStore service for Redis get/set operations
- Extract shared logic: ogHtml (generateHtml, escapeHtml) and articleMeta (relay/gateway fetching)
- Refactor article-og endpoint to read from Redis, try gateway on miss, trigger background refresh
- Add article-og-refresh endpoint for background relay fetching and caching
- Update vercel.json with refresh function config
- Remove WebSocket dependencies from main OG endpoint for faster crawler responses
- Add YouTube thumbnail extraction using existing getYouTubeThumbnail utility
- Add Vimeo thumbnail support using vumbnail.com service
- Update VideoView to use video thumbnails as cover images in ReaderHeader
- Update Vimeo API to include thumbnail_url in response
- Fallback to original image prop if no video thumbnail available
- Supports both YouTube and Vimeo video thumbnails
- Add actual YouTube title and description fetching via web scraping
- Fix syntax error in video-meta.ts (missing opening brace)
- Complete Vimeo metadata implementation
- Both APIs now properly extract title and description from video pages
- Caption extraction remains functional for supported videos
- Update HTML title and meta tags in index.html
- Update PWA manifest in public/manifest.webmanifest
- Update Vite PWA manifest in vite.config.ts
- Update article OG title fallback in api/article-og.ts
- Reflects the core functionality: reading, highlighting, and exploring content
Use named parameter syntax in Vercel rewrite and add <base href="/"> tag to ensure assets load correctly from root when serving index.html through the API.
Instead of redirecting, serve the static index.html file directly. The Vercel rewrite preserves the /a/{naddr} URL, allowing client-side SPA routing to work correctly.
Browsers get 302 redirect to / where the SPA handles routing client-side with the original /a/{naddr} URL preserved. Crawlers/bots get the full HTML with OG meta tags.
- Remove non-existent getVideoDetails import from youtube-caption-extractor
- Add Subtitle type definition for proper type conversion
- Remove invalid 'auto' parameter from getSubtitles call
- Convert Subtitle[] to Caption[] with proper type casting
- Simplify title/description extraction for YouTube metadata
- Remove non-existent getVideoDetails import and usage
- Fix getSubtitles API call to match actual package interface
- Add proper Subtitle type to replace any usage
- Convert subtitle data types to match Caption interface
- Install missing @vercel/node dependency
- Create unified video-meta.ts API handler for both YouTube and Vimeo
- Add Vimeo oEmbed API integration for server-side metadata extraction
- Implement URL pattern matching for YouTube and Vimeo video detection
- Support both URL and videoId parameters for backward compatibility
- Add proper TypeScript types for Vimeo oEmbed response
- Include caching mechanism for Vimeo metadata (7-day cache)
- Remove unused @vimeo/player package dependency
The new API endpoint supports:
- YouTube: /api/video-meta?url=https://youtube.com/watch?v=ID or ?videoId=ID
- Vimeo: /api/video-meta?url=https://vimeo.com/ID
- Returns consistent response format for both platforms
- Replace 'any' type with proper type annotations
- Add explicit type checking for video details response
- Improve description field extraction with better type safety
- Add comments for better code documentation