Files
lidify/frontend/next.config.ts
Your Name cc8d0f6969 Release v1.3.0: Multi-source downloads, audio analyzer resilience, mobile improvements
Major Features:
- Multi-source download system (Soulseek/Lidarr with fallback)
- Configurable enrichment speed control (1-5x)
- Mobile touch drag support for seek sliders
- iOS PWA media controls (Control Center, Lock Screen)
- Artist name alias resolution via Last.fm
- Circuit breaker pattern for audio analysis

Critical Fixes:
- Audio analyzer stability (non-ASCII, BrokenProcessPool, OOM)
- Discovery system race conditions and import failures
- Radio decade categorization using originalYear
- LastFM API response normalization
- Mood bucket infinite loop prevention

Security:
- Bull Board admin authentication
- Lidarr webhook signature verification
- JWT token expiration and refresh
- Encryption key validation on startup

Closes #2, #6, #9, #13, #21, #26, #31, #34, #35, #37, #40, #43
2026-01-06 20:07:33 -06:00

106 lines
2.9 KiB
TypeScript

import type { NextConfig } from "next";
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
});
const nextConfig: NextConfig = {
// Allow dev origins for local network testing
allowedDevOrigins: [
"http://127.0.0.1:3030",
"http://127.0.0.1",
"127.0.0.1",
"http://localhost:3030",
"http://localhost",
"localhost",
],
images: {
remotePatterns: [
{
protocol: "https",
hostname: "cdn-images.dzcdn.net",
pathname: "/**",
},
{
protocol: "https",
hostname: "e-cdns-images.dzcdn.net",
pathname: "/**",
},
{
protocol: "https",
hostname: "lastfm.freetls.fastly.net",
pathname: "/**",
},
{
protocol: "https",
hostname: "lastfm-img2.akamaized.net",
pathname: "/**",
},
{
protocol: "http",
hostname: "localhost",
port: "3006",
pathname: "/**",
},
{
protocol: "http",
hostname: "127.0.0.1",
port: "3006",
pathname: "/**",
},
{
protocol: "https",
hostname: "assets.pippa.io",
pathname: "/**",
},
{
protocol: "https",
hostname: "assets.fanart.tv",
pathname: "/**",
},
{
protocol: "https",
hostname: "is1-ssl.mzstatic.com",
pathname: "/**",
},
],
formats: ["image/avif", "image/webp"],
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
minimumCacheTTL: 60 * 60 * 24 * 7, // Cache for 7 days
dangerouslyAllowSVG: true,
},
reactStrictMode: true,
async headers() {
return [
{
source: "/(.*)",
headers: [
{
key: "Permissions-Policy",
value: "camera=(), microphone=(), geolocation=()",
},
],
},
];
},
// Proxy API requests to backend (for Docker all-in-one container)
async rewrites() {
const backendUrl = process.env.BACKEND_URL || "http://127.0.0.1:3006";
return [
{
source: "/api/:path*",
destination: `${backendUrl}/api/:path*`,
},
{
source: "/health",
destination: `${backendUrl}/health`,
},
];
},
};
export default withBundleAnalyzer(nextConfig);