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
106 lines
2.9 KiB
TypeScript
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);
|