karaoke-gen 0.105.4__py3-none-any.whl → 0.107.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- backend/api/routes/users.py +14 -3
- backend/config.py +3 -0
- backend/services/encoding_interface.py +4 -0
- backend/services/job_notification_service.py +4 -21
- backend/tests/test_job_notification_service.py +24 -58
- backend/tests/test_video_worker_orchestrator.py +189 -0
- backend/workers/video_worker_orchestrator.py +7 -0
- karaoke_gen/instrumental_review/server.py +145 -35
- karaoke_gen/nextjs_frontend/__init__.py +98 -0
- karaoke_gen/nextjs_frontend/out/404/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/404.html +1 -0
- karaoke_gen/nextjs_frontend/out/__next.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/01a7f8fe40f1ff47.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/112f346e31f991df.js +4 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/16d1a4dd9d8a873a.js +3 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/1ab85c362b8b0e86.js +9 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/247eb132b7f7b574.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/2b80d15cc95e4818.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/32c7eba5cd46c1bc.js +7 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/483f26794eae53d0.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/550c3b02e85f196a.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/55c5ade44387bef8.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/5628d92b5893add2.css +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/56ebf7665e4341c8.js +7 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/5997132b61dec430.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/5ea55255bce3eb9e.js +5 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/5eda89a57490b3cd.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/692f5d9e0d700c76.js +3 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/71d7a05b14f9f0f4.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/81ac355749ef3302.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/95f7e5934dbb0e5d.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/9bce8f19eaa46940.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/a6dad97d9634a72d.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/a9ed54eed3e14c92.js +2 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/b35cd41238ecfb17.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5bc3c3d5ebd49eb.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/b5c078c08db5ae32.js +5 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/be9c44a178104187.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/c4c840e18cb4861c.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/c645af7d6b65f73e.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/d2c5e2575df784d4.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/d30af02b96d81462.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/d9bdf64f4ec1e9b7.js +7 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/dcde6ed684dacd0e.js +5 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/e422cbe931246000.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/e483af34fc792d38.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/e57422aad6b897da.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/ef02697fb404726a.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/ff1a16fafef87110.js +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/chunks/turbopack-2d9ca3017a9deedf.js +3 -0
- karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_buildManifest.js +11 -0
- karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_clientMiddlewareManifest.json +1 -0
- karaoke_gen/nextjs_frontend/out/_next/static/zpw_-rjFIDV5tlPPtnvRI/_ssgManifest.js +1 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._full.txt +18 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.__PAGE__.txt +5 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._not-found.txt +4 -0
- karaoke_gen/nextjs_frontend/out/_not-found/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/_not-found/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/_not-found/index.txt +18 -0
- karaoke_gen/nextjs_frontend/out/admin/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/__next.admin.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.beta.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/beta/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.jobs.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/jobs/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.rate-limits.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/rate-limits/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.searches.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/searches/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/users/__next.admin.users.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._full.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.txt +7 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.detail.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/__next.admin.users.txt +4 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/users/detail/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/admin/users/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/admin/users/index.txt +25 -0
- karaoke_gen/nextjs_frontend/out/app/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/app/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/app/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/app/__next.app.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/__next.app.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/app/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next._full.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.$oc$slug.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.jobs.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/__next.app.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/index.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._full.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.$oc$slug.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.jobs.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/__next.app.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/instrumental/index.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._full.txt +19 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.__PAGE__.txt +6 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.$oc$slug.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.jobs.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/__next.app.txt +4 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/app/jobs/local/review/index.txt +19 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.txt +4 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/__next.auth.verify.txt +4 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/auth/verify/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/manifest.webmanifest +31 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next.order.success.txt +4 -0
- karaoke_gen/nextjs_frontend/out/order/success/__next.order.txt +4 -0
- karaoke_gen/nextjs_frontend/out/order/success/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/order/success/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next._full.txt +22 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next._head.txt +8 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next._index.txt +9 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next._tree.txt +2 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.__PAGE__.txt +9 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.success.txt +4 -0
- karaoke_gen/nextjs_frontend/out/payment/success/__next.payment.txt +4 -0
- karaoke_gen/nextjs_frontend/out/payment/success/index.html +1 -0
- karaoke_gen/nextjs_frontend/out/payment/success/index.txt +22 -0
- karaoke_gen/nextjs_frontend/out/screenshots/email-action_reminder.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/email-beta_welcome.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/email-job_completion.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/example-output.avif +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/homepage-full.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/homepage-hero.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.avif +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/instrumental-review.png +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/job-dashboard.avif +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.avif +0 -0
- karaoke_gen/nextjs_frontend/out/screenshots/lyrics-review.png +0 -0
- karaoke_gen/nextjs_frontend/out/sw.js +183 -0
- karaoke_gen/utils/cli_args.py +3 -3
- karaoke_gen/utils/gen_cli.py +4 -0
- karaoke_gen/utils/remote_cli.py +8 -40
- {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/METADATA +1 -1
- {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/RECORD +227 -121
- {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/WHEEL +1 -1
- lyrics_transcriber/correction/agentic/agent.py +83 -60
- lyrics_transcriber/correction/anchor_sequence.py +48 -3
- lyrics_transcriber/correction/corrector.py +92 -58
- lyrics_transcriber/review/server.py +165 -33
- lyrics_transcriber/utils/tracing.py +214 -0
- karaoke_gen/instrumental_review/static/index.html +0 -1721
- lyrics_transcriber/frontend/.gitignore +0 -24
- lyrics_transcriber/frontend/.yarn/releases/yarn-4.7.0.cjs +0 -935
- lyrics_transcriber/frontend/.yarnrc.yml +0 -3
- lyrics_transcriber/frontend/README.md +0 -50
- lyrics_transcriber/frontend/REPLACE_ALL_FUNCTIONALITY.md +0 -210
- lyrics_transcriber/frontend/__init__.py +0 -25
- lyrics_transcriber/frontend/e2e/agentic-corrections.spec.ts +0 -207
- lyrics_transcriber/frontend/e2e/fixtures/agentic-correction-data.json +0 -226
- lyrics_transcriber/frontend/eslint.config.js +0 -28
- lyrics_transcriber/frontend/index.html +0 -22
- lyrics_transcriber/frontend/package-lock.json +0 -4553
- lyrics_transcriber/frontend/package.json +0 -48
- lyrics_transcriber/frontend/playwright.config.ts +0 -69
- lyrics_transcriber/frontend/public/android-chrome-192x192.png +0 -0
- lyrics_transcriber/frontend/public/android-chrome-512x512.png +0 -0
- lyrics_transcriber/frontend/src/App.tsx +0 -243
- lyrics_transcriber/frontend/src/api.ts +0 -262
- lyrics_transcriber/frontend/src/components/AIFeedbackModal.tsx +0 -111
- lyrics_transcriber/frontend/src/components/AddLyricsModal.tsx +0 -114
- lyrics_transcriber/frontend/src/components/AgenticCorrectionMetrics.tsx +0 -204
- lyrics_transcriber/frontend/src/components/AppHeader.tsx +0 -65
- lyrics_transcriber/frontend/src/components/AudioPlayer.tsx +0 -180
- lyrics_transcriber/frontend/src/components/CorrectedWordWithActions.tsx +0 -175
- lyrics_transcriber/frontend/src/components/CorrectionAnnotationModal.tsx +0 -359
- lyrics_transcriber/frontend/src/components/CorrectionDetailCard.tsx +0 -281
- lyrics_transcriber/frontend/src/components/CorrectionMetrics.tsx +0 -162
- lyrics_transcriber/frontend/src/components/DurationTimelineView.tsx +0 -257
- lyrics_transcriber/frontend/src/components/EditActionBar.tsx +0 -94
- lyrics_transcriber/frontend/src/components/EditModal.tsx +0 -720
- lyrics_transcriber/frontend/src/components/EditTimelineSection.tsx +0 -592
- lyrics_transcriber/frontend/src/components/EditWordList.tsx +0 -431
- lyrics_transcriber/frontend/src/components/FileUpload.tsx +0 -77
- lyrics_transcriber/frontend/src/components/FindReplaceModal.tsx +0 -467
- lyrics_transcriber/frontend/src/components/Header.tsx +0 -520
- lyrics_transcriber/frontend/src/components/LyricsAnalyzer.tsx +0 -1526
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/SyncControls.tsx +0 -216
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/TimelineCanvas.tsx +0 -721
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/UpcomingWordsBar.tsx +0 -80
- lyrics_transcriber/frontend/src/components/LyricsSynchronizer/index.tsx +0 -999
- lyrics_transcriber/frontend/src/components/MetricsDashboard.tsx +0 -51
- lyrics_transcriber/frontend/src/components/ModeSelectionModal.tsx +0 -127
- lyrics_transcriber/frontend/src/components/ModeSelector.tsx +0 -67
- lyrics_transcriber/frontend/src/components/ModelSelector.tsx +0 -23
- lyrics_transcriber/frontend/src/components/PreviewVideoSection.tsx +0 -177
- lyrics_transcriber/frontend/src/components/ReferenceView.tsx +0 -268
- lyrics_transcriber/frontend/src/components/ReplaceAllLyricsModal.tsx +0 -336
- lyrics_transcriber/frontend/src/components/ReviewChangesModal.tsx +0 -354
- lyrics_transcriber/frontend/src/components/SegmentDetailsModal.tsx +0 -64
- lyrics_transcriber/frontend/src/components/TimelineEditor.tsx +0 -383
- lyrics_transcriber/frontend/src/components/TimingOffsetModal.tsx +0 -131
- lyrics_transcriber/frontend/src/components/TranscriptionView.tsx +0 -266
- lyrics_transcriber/frontend/src/components/WordDivider.tsx +0 -191
- lyrics_transcriber/frontend/src/components/shared/components/HighlightedText.tsx +0 -466
- lyrics_transcriber/frontend/src/components/shared/components/SourceSelector.tsx +0 -56
- lyrics_transcriber/frontend/src/components/shared/components/Word.tsx +0 -89
- lyrics_transcriber/frontend/src/components/shared/constants.ts +0 -30
- lyrics_transcriber/frontend/src/components/shared/hooks/useWordClick.ts +0 -180
- lyrics_transcriber/frontend/src/components/shared/styles.ts +0 -13
- lyrics_transcriber/frontend/src/components/shared/types.js +0 -2
- lyrics_transcriber/frontend/src/components/shared/types.ts +0 -135
- lyrics_transcriber/frontend/src/components/shared/utils/keyboardHandlers.ts +0 -177
- lyrics_transcriber/frontend/src/components/shared/utils/localStorage.ts +0 -78
- lyrics_transcriber/frontend/src/components/shared/utils/referenceLineCalculator.ts +0 -75
- lyrics_transcriber/frontend/src/components/shared/utils/segmentOperations.ts +0 -360
- lyrics_transcriber/frontend/src/components/shared/utils/timingUtils.ts +0 -110
- lyrics_transcriber/frontend/src/components/shared/utils/wordUtils.ts +0 -22
- lyrics_transcriber/frontend/src/hooks/useManualSync.ts +0 -537
- lyrics_transcriber/frontend/src/main.tsx +0 -11
- lyrics_transcriber/frontend/src/theme.ts +0 -406
- lyrics_transcriber/frontend/src/types/global.d.ts +0 -9
- lyrics_transcriber/frontend/src/types.js +0 -2
- lyrics_transcriber/frontend/src/types.ts +0 -199
- lyrics_transcriber/frontend/src/validation.ts +0 -132
- lyrics_transcriber/frontend/src/vite-env.d.ts +0 -1
- lyrics_transcriber/frontend/tsconfig.app.json +0 -26
- lyrics_transcriber/frontend/tsconfig.json +0 -25
- lyrics_transcriber/frontend/tsconfig.node.json +0 -23
- lyrics_transcriber/frontend/tsconfig.tsbuildinfo +0 -1
- lyrics_transcriber/frontend/update_version.js +0 -11
- lyrics_transcriber/frontend/vite.config.d.ts +0 -2
- lyrics_transcriber/frontend/vite.config.js +0 -15
- lyrics_transcriber/frontend/vite.config.ts +0 -16
- lyrics_transcriber/frontend/web_assets/android-chrome-192x192.png +0 -0
- lyrics_transcriber/frontend/web_assets/android-chrome-512x512.png +0 -0
- lyrics_transcriber/frontend/web_assets/apple-touch-icon.png +0 -0
- lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js +0 -44465
- lyrics_transcriber/frontend/web_assets/assets/index-BSMgOq4Z.js.map +0 -1
- lyrics_transcriber/frontend/web_assets/favicon-16x16.png +0 -0
- lyrics_transcriber/frontend/web_assets/favicon-32x32.png +0 -0
- lyrics_transcriber/frontend/web_assets/favicon.ico +0 -0
- lyrics_transcriber/frontend/web_assets/index.html +0 -22
- lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.png +0 -0
- lyrics_transcriber/frontend/web_assets/nomad-karaoke-logo.svg +0 -5
- lyrics_transcriber/frontend/yarn.lock +0 -3711
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/apple-touch-icon.png +0 -0
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-16x16.png +0 -0
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon-32x32.png +0 -0
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/favicon.ico +0 -0
- {lyrics_transcriber/frontend/public → karaoke_gen/nextjs_frontend/out}/nomad-karaoke-logo.svg +0 -0
- /lyrics_transcriber/frontend/public/nomad-karaoke-logo.png → /karaoke_gen/nextjs_frontend/out/nomad-logo.png +0 -0
- {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/entry_points.txt +0 -0
- {karaoke_gen-0.105.4.dist-info → karaoke_gen-0.107.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -10,7 +10,6 @@ Similar pattern to LyricsTranscriber's ReviewServer.
|
|
|
10
10
|
|
|
11
11
|
import logging
|
|
12
12
|
import os
|
|
13
|
-
from pathlib import Path
|
|
14
13
|
import socket
|
|
15
14
|
import threading
|
|
16
15
|
import webbrowser
|
|
@@ -18,7 +17,7 @@ from typing import List, Optional
|
|
|
18
17
|
|
|
19
18
|
from fastapi import FastAPI, HTTPException, UploadFile, File
|
|
20
19
|
from fastapi.middleware.cors import CORSMiddleware
|
|
21
|
-
from fastapi.responses import FileResponse
|
|
20
|
+
from fastapi.responses import FileResponse
|
|
22
21
|
from pydantic import BaseModel
|
|
23
22
|
import shutil
|
|
24
23
|
import tempfile
|
|
@@ -104,7 +103,7 @@ class InstrumentalReviewServer:
|
|
|
104
103
|
def _create_app(self) -> FastAPI:
|
|
105
104
|
"""Create and configure the FastAPI application."""
|
|
106
105
|
app = FastAPI(title="Instrumental Review", docs_url=None, redoc_url=None)
|
|
107
|
-
|
|
106
|
+
|
|
108
107
|
# Configure CORS
|
|
109
108
|
app.add_middleware(
|
|
110
109
|
CORSMiddleware,
|
|
@@ -113,19 +112,138 @@ class InstrumentalReviewServer:
|
|
|
113
112
|
allow_methods=["*"],
|
|
114
113
|
allow_headers=["*"],
|
|
115
114
|
)
|
|
116
|
-
|
|
115
|
+
|
|
116
|
+
# Determine which frontend to use
|
|
117
|
+
self._use_nextjs_frontend = self._setup_nextjs_frontend(app)
|
|
118
|
+
|
|
117
119
|
# Register routes
|
|
118
120
|
self._register_routes(app)
|
|
119
|
-
|
|
121
|
+
|
|
120
122
|
return app
|
|
123
|
+
|
|
124
|
+
def _setup_nextjs_frontend(self, app: FastAPI) -> bool:
|
|
125
|
+
"""Set up the unified Next.js frontend.
|
|
126
|
+
|
|
127
|
+
Returns True if Next.js frontend is set up successfully.
|
|
128
|
+
Raises FileNotFoundError if Next.js assets are not available.
|
|
129
|
+
"""
|
|
130
|
+
import os
|
|
131
|
+
from karaoke_gen.nextjs_frontend import get_nextjs_assets_dir, is_nextjs_frontend_available
|
|
132
|
+
|
|
133
|
+
if not is_nextjs_frontend_available():
|
|
134
|
+
raise FileNotFoundError(
|
|
135
|
+
"Next.js frontend assets not found. Please ensure the frontend is built "
|
|
136
|
+
"and copied to karaoke_gen/nextjs_frontend/out/"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
frontend_dir = str(get_nextjs_assets_dir())
|
|
140
|
+
logger.info(f"Using Next.js frontend from {frontend_dir}")
|
|
141
|
+
|
|
142
|
+
# Mount static files for Next.js assets
|
|
143
|
+
from fastapi.staticfiles import StaticFiles
|
|
144
|
+
app.mount("/_next", StaticFiles(directory=os.path.join(frontend_dir, "_next")), name="nextjs_static")
|
|
145
|
+
|
|
146
|
+
return True
|
|
121
147
|
|
|
122
148
|
def _register_routes(self, app: FastAPI) -> None:
|
|
123
149
|
"""Register API routes."""
|
|
124
|
-
|
|
150
|
+
|
|
125
151
|
@app.get("/")
|
|
126
152
|
async def serve_frontend():
|
|
127
|
-
"""
|
|
128
|
-
|
|
153
|
+
"""Redirect to Next.js instrumental review route."""
|
|
154
|
+
from fastapi.responses import RedirectResponse
|
|
155
|
+
return RedirectResponse(url="/app/jobs/local/instrumental", status_code=302)
|
|
156
|
+
|
|
157
|
+
# Local instrumental route - serve pre-rendered HTML for local mode
|
|
158
|
+
@app.get("/app/jobs/local/instrumental")
|
|
159
|
+
async def serve_local_instrumental():
|
|
160
|
+
"""Serve pre-rendered local instrumental page with patched chunk loading."""
|
|
161
|
+
from karaoke_gen.nextjs_frontend import get_nextjs_assets_dir
|
|
162
|
+
from fastapi.responses import HTMLResponse
|
|
163
|
+
import glob
|
|
164
|
+
frontend_dir = get_nextjs_assets_dir()
|
|
165
|
+
if frontend_dir:
|
|
166
|
+
import os
|
|
167
|
+
local_instrumental_html = os.path.join(str(frontend_dir), "app", "jobs", "local", "instrumental", "index.html")
|
|
168
|
+
if os.path.exists(local_instrumental_html):
|
|
169
|
+
# Read the HTML and inject the missing chunk script
|
|
170
|
+
# This works around a Turbopack static export issue
|
|
171
|
+
with open(local_instrumental_html, 'r', encoding='utf-8') as f:
|
|
172
|
+
html_content = f.read()
|
|
173
|
+
|
|
174
|
+
# Find the chunk containing module 78280 (JobRouterClient)
|
|
175
|
+
chunks_dir = os.path.join(str(frontend_dir), "_next", "static", "chunks")
|
|
176
|
+
for chunk_file in glob.glob(os.path.join(chunks_dir, "*.js")):
|
|
177
|
+
chunk_name = os.path.basename(chunk_file)
|
|
178
|
+
with open(chunk_file, 'r', encoding='utf-8') as cf:
|
|
179
|
+
chunk_content = cf.read(500)
|
|
180
|
+
if ",78280," in chunk_content:
|
|
181
|
+
script_tag = f'<script src="/_next/static/chunks/{chunk_name}" async=""></script>'
|
|
182
|
+
if chunk_name not in html_content:
|
|
183
|
+
html_content = html_content.replace('</head>', f'{script_tag}</head>')
|
|
184
|
+
break
|
|
185
|
+
|
|
186
|
+
return HTMLResponse(content=html_content, media_type="text/html")
|
|
187
|
+
# Fallback to jobs index
|
|
188
|
+
jobs_html = os.path.join(str(frontend_dir), "app", "jobs", "index.html")
|
|
189
|
+
if os.path.exists(jobs_html):
|
|
190
|
+
return FileResponse(jobs_html, media_type="text/html")
|
|
191
|
+
raise HTTPException(status_code=404, detail="Instrumental page not found")
|
|
192
|
+
|
|
193
|
+
# Job routes - serve the jobs page HTML for client-side routing
|
|
194
|
+
@app.get("/app/jobs/{full_path:path}")
|
|
195
|
+
async def serve_jobs_routes(full_path: str):
|
|
196
|
+
"""Serve jobs index.html for all /app/jobs/* routes (SPA routing)."""
|
|
197
|
+
from karaoke_gen.nextjs_frontend import get_nextjs_assets_dir
|
|
198
|
+
frontend_dir = get_nextjs_assets_dir()
|
|
199
|
+
if frontend_dir:
|
|
200
|
+
import os
|
|
201
|
+
jobs_html = os.path.join(str(frontend_dir), "app", "jobs", "index.html")
|
|
202
|
+
if os.path.exists(jobs_html):
|
|
203
|
+
return FileResponse(jobs_html, media_type="text/html")
|
|
204
|
+
raise HTTPException(status_code=404, detail="Jobs page not found")
|
|
205
|
+
|
|
206
|
+
# Other app routes - serve the app index.html
|
|
207
|
+
@app.get("/app/{full_path:path}")
|
|
208
|
+
async def serve_app_routes(full_path: str):
|
|
209
|
+
"""Serve app index.html for other /app/* routes."""
|
|
210
|
+
from karaoke_gen.nextjs_frontend import get_nextjs_assets_dir
|
|
211
|
+
frontend_dir = get_nextjs_assets_dir()
|
|
212
|
+
if frontend_dir:
|
|
213
|
+
import os
|
|
214
|
+
app_html = os.path.join(str(frontend_dir), "app", "index.html")
|
|
215
|
+
if os.path.exists(app_html):
|
|
216
|
+
return FileResponse(app_html, media_type="text/html")
|
|
217
|
+
# Fallback to root index.html
|
|
218
|
+
index_html = os.path.join(str(frontend_dir), "index.html")
|
|
219
|
+
if os.path.exists(index_html):
|
|
220
|
+
return FileResponse(index_html, media_type="text/html")
|
|
221
|
+
raise HTTPException(status_code=404, detail="Frontend not found")
|
|
222
|
+
|
|
223
|
+
# Tenant config endpoint (returns default config for local mode)
|
|
224
|
+
@app.get("/api/tenant/config")
|
|
225
|
+
async def get_tenant_config():
|
|
226
|
+
"""Get tenant configuration for local mode."""
|
|
227
|
+
return {
|
|
228
|
+
"tenant": None,
|
|
229
|
+
"is_default": True
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
# Mock job endpoint for local mode (required by unified frontend)
|
|
233
|
+
@app.get("/api/jobs/local")
|
|
234
|
+
async def get_local_job():
|
|
235
|
+
"""Get mock job data for local mode."""
|
|
236
|
+
return {
|
|
237
|
+
"job_id": "local",
|
|
238
|
+
"status": "awaiting_instrumental_selection",
|
|
239
|
+
"progress": 50,
|
|
240
|
+
"created_at": None,
|
|
241
|
+
"updated_at": None,
|
|
242
|
+
"artist": self.base_name.split(" - ")[0] if " - " in self.base_name else "",
|
|
243
|
+
"title": self.base_name.split(" - ")[1] if " - " in self.base_name else self.base_name,
|
|
244
|
+
"user_email": "local@localhost",
|
|
245
|
+
"audio_hash": "local",
|
|
246
|
+
}
|
|
129
247
|
|
|
130
248
|
@app.get("/api/jobs/local/instrumental-analysis")
|
|
131
249
|
async def get_analysis():
|
|
@@ -188,9 +306,8 @@ class InstrumentalReviewServer:
|
|
|
188
306
|
logger.exception(f"Error generating waveform data: {e}")
|
|
189
307
|
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
190
308
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
"""Stream audio file."""
|
|
309
|
+
def _get_audio_path(stem_type: str) -> Optional[str]:
|
|
310
|
+
"""Get the path for a given stem type."""
|
|
194
311
|
path_map = {
|
|
195
312
|
"clean_instrumental": self.clean_instrumental_path,
|
|
196
313
|
"backing_vocals": self.backing_vocals_path,
|
|
@@ -199,11 +316,14 @@ class InstrumentalReviewServer:
|
|
|
199
316
|
"uploaded_instrumental": self.uploaded_instrumental_path,
|
|
200
317
|
"original": self.original_audio_path,
|
|
201
318
|
}
|
|
202
|
-
|
|
203
|
-
|
|
319
|
+
return path_map.get(stem_type)
|
|
320
|
+
|
|
321
|
+
def _stream_audio_file(stem_type: str):
|
|
322
|
+
"""Stream an audio file by stem type."""
|
|
323
|
+
audio_path = _get_audio_path(stem_type)
|
|
204
324
|
if not audio_path or not os.path.exists(audio_path):
|
|
205
325
|
raise HTTPException(status_code=404, detail=f"Audio file not found: {stem_type}")
|
|
206
|
-
|
|
326
|
+
|
|
207
327
|
# Determine content type
|
|
208
328
|
ext = os.path.splitext(audio_path)[1].lower()
|
|
209
329
|
content_types = {
|
|
@@ -212,8 +332,18 @@ class InstrumentalReviewServer:
|
|
|
212
332
|
".wav": "audio/wav",
|
|
213
333
|
}
|
|
214
334
|
content_type = content_types.get(ext, "application/octet-stream")
|
|
215
|
-
|
|
335
|
+
|
|
216
336
|
return FileResponse(audio_path, media_type=content_type)
|
|
337
|
+
|
|
338
|
+
@app.get("/api/audio/{stem_type}")
|
|
339
|
+
async def stream_audio(stem_type: str):
|
|
340
|
+
"""Stream audio file (legacy route)."""
|
|
341
|
+
return _stream_audio_file(stem_type)
|
|
342
|
+
|
|
343
|
+
@app.get("/api/jobs/{job_id}/audio-stream/{stem_type}")
|
|
344
|
+
async def stream_audio_cloud(job_id: str, stem_type: str):
|
|
345
|
+
"""Stream audio file (cloud-compatible route)."""
|
|
346
|
+
return _stream_audio_file(stem_type)
|
|
217
347
|
|
|
218
348
|
@app.get("/api/waveform")
|
|
219
349
|
async def get_waveform_image():
|
|
@@ -338,26 +468,6 @@ class InstrumentalReviewServer:
|
|
|
338
468
|
|
|
339
469
|
return {"status": "success", "selection": request.selection}
|
|
340
470
|
|
|
341
|
-
@staticmethod
|
|
342
|
-
def _get_static_dir() -> Path:
|
|
343
|
-
"""Get the path to the static assets directory."""
|
|
344
|
-
return Path(__file__).parent / "static"
|
|
345
|
-
|
|
346
|
-
def _get_frontend_html(self) -> str:
|
|
347
|
-
"""Return the frontend HTML by reading from the static file."""
|
|
348
|
-
static_file = self._get_static_dir() / "index.html"
|
|
349
|
-
if static_file.exists():
|
|
350
|
-
return static_file.read_text(encoding="utf-8")
|
|
351
|
-
else:
|
|
352
|
-
# Fallback error message if file is missing
|
|
353
|
-
return """<!DOCTYPE html>
|
|
354
|
-
<html>
|
|
355
|
-
<head><title>Error</title></head>
|
|
356
|
-
<body style="background:#1a1a1a;color:#fff;font-family:sans-serif;padding:2rem;">
|
|
357
|
-
<h1>Frontend assets not found</h1>
|
|
358
|
-
<p>The static/index.html file is missing from the instrumental_review module.</p>
|
|
359
|
-
</body>
|
|
360
|
-
</html>"""
|
|
361
471
|
|
|
362
472
|
@staticmethod
|
|
363
473
|
def _is_port_available(host: str, port: int) -> bool:
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Next.js frontend module for karaoke-gen unified web interface.
|
|
2
|
+
|
|
3
|
+
This module provides utilities for serving the consolidated Next.js frontend
|
|
4
|
+
for both lyrics review and instrumental selection in local CLI mode.
|
|
5
|
+
|
|
6
|
+
The Next.js frontend is built with `npm run build` in the frontend/ directory
|
|
7
|
+
and produces a static export in frontend/out/ which can be served by the
|
|
8
|
+
local review servers.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from typing import Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# Get the directory containing this module
|
|
17
|
+
_MODULE_DIR = Path(__file__).parent.absolute()
|
|
18
|
+
|
|
19
|
+
# The Next.js static export location relative to the repo root
|
|
20
|
+
# When packaged, it will be at karaoke_gen/nextjs_frontend/out/
|
|
21
|
+
# In development, it's at frontend/out/
|
|
22
|
+
_PACKAGED_DIR = _MODULE_DIR / "out"
|
|
23
|
+
_DEV_DIR = _MODULE_DIR.parent.parent / "frontend" / "out"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_nextjs_assets_dir() -> Optional[Path]:
|
|
27
|
+
"""Get the path to the Next.js static export directory.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Path to the frontend/out directory containing the Next.js static export,
|
|
31
|
+
or None if the assets are not available.
|
|
32
|
+
"""
|
|
33
|
+
# Check packaged location first
|
|
34
|
+
if _PACKAGED_DIR.exists() and (_PACKAGED_DIR / "index.html").exists():
|
|
35
|
+
return _PACKAGED_DIR
|
|
36
|
+
|
|
37
|
+
# Check development location
|
|
38
|
+
if _DEV_DIR.exists() and (_DEV_DIR / "index.html").exists():
|
|
39
|
+
return _DEV_DIR
|
|
40
|
+
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def is_nextjs_frontend_available() -> bool:
|
|
45
|
+
"""Check if the Next.js frontend is available for serving."""
|
|
46
|
+
return get_nextjs_assets_dir() is not None
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_spa_index_html(assets_dir: Path) -> Path:
|
|
50
|
+
"""Get the path to the SPA index.html file for routing."""
|
|
51
|
+
return assets_dir / "index.html"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def get_route_html_path(assets_dir: Path, route: str) -> Optional[Path]:
|
|
55
|
+
"""Get the path to a specific route's HTML file.
|
|
56
|
+
|
|
57
|
+
For Next.js static export, routes like /app/jobs/local/review
|
|
58
|
+
are pre-rendered to /app/jobs/[...slug].html or similar.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
assets_dir: Path to the Next.js static export directory
|
|
62
|
+
route: The URL route being requested (e.g., "/app/jobs/local/review")
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Path to the HTML file for this route, or None if not found.
|
|
66
|
+
"""
|
|
67
|
+
# Clean the route
|
|
68
|
+
route = route.strip("/")
|
|
69
|
+
if not route:
|
|
70
|
+
return assets_dir / "index.html"
|
|
71
|
+
|
|
72
|
+
# Try exact path match first
|
|
73
|
+
exact_path = assets_dir / route / "index.html"
|
|
74
|
+
if exact_path.exists():
|
|
75
|
+
return exact_path
|
|
76
|
+
|
|
77
|
+
# Try .html extension
|
|
78
|
+
html_path = assets_dir / f"{route}.html"
|
|
79
|
+
if html_path.exists():
|
|
80
|
+
return html_path
|
|
81
|
+
|
|
82
|
+
# For dynamic routes like /app/jobs/[[...slug]],
|
|
83
|
+
# Next.js creates /app/jobs.html or /app/jobs/[[...slug]].html
|
|
84
|
+
# We need to fall back to the catch-all route
|
|
85
|
+
parts = route.split("/")
|
|
86
|
+
for i in range(len(parts), 0, -1):
|
|
87
|
+
parent = "/".join(parts[:i])
|
|
88
|
+
# Try the [...slug] catch-all pattern
|
|
89
|
+
catch_all = assets_dir / parent / "[[...slug]].html"
|
|
90
|
+
if catch_all.exists():
|
|
91
|
+
return catch_all
|
|
92
|
+
# Try parent index
|
|
93
|
+
parent_index = assets_dir / parent / "index.html"
|
|
94
|
+
if parent_index.exists():
|
|
95
|
+
return parent_index
|
|
96
|
+
|
|
97
|
+
# Fallback to main index.html for SPA routing
|
|
98
|
+
return assets_dir / "index.html"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!DOCTYPE html><!--zpw__rjFIDV5tlPPtnvRI--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/5628d92b5893add2.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/95f7e5934dbb0e5d.js"/><script src="/_next/static/chunks/112f346e31f991df.js" async=""></script><script src="/_next/static/chunks/a9ed54eed3e14c92.js" async=""></script><script src="/_next/static/chunks/c645af7d6b65f73e.js" async=""></script><script src="/_next/static/chunks/5997132b61dec430.js" async=""></script><script src="/_next/static/chunks/turbopack-2d9ca3017a9deedf.js" async=""></script><script src="/_next/static/chunks/ef02697fb404726a.js" async=""></script><script src="/_next/static/chunks/e483af34fc792d38.js" async=""></script><script src="/_next/static/chunks/247eb132b7f7b574.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Nomad Karaoke: Generator</title><meta name="description" content="Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics"/><link rel="manifest" href="/manifest.webmanifest"/><link rel="icon" href="/favicon.ico" sizes="any"/><link rel="icon" href="/favicon-16x16.png" sizes="16x16" type="image/png"/><link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="font-sans antialiased" style="background:var(--bg);color:var(--text)"><div hidden=""><!--$--><!--/$--></div><script>((a,b,c,d,e,f,g,h)=>{let i=document.documentElement,j=["light","dark"];function k(b){var c;(Array.isArray(a)?a:[a]).forEach(a=>{let c="class"===a,d=c&&f?e.map(a=>f[a]||a):e;c?(i.classList.remove(...d),i.classList.add(f&&f[b]?f[b]:b)):i.setAttribute(a,b)}),c=b,h&&j.includes(c)&&(i.style.colorScheme=c)}if(d)k(d);else try{let a=localStorage.getItem(b)||c,d=g&&"system"===a?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a;k(d)}catch(a){}})("class","theme","dark",null,["light","dark"],null,true,true)</script><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/95f7e5934dbb0e5d.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[72285,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ServiceWorkerRegistration\"]\n3:I[89554,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ThemeProvider\"]\n4:I[57091,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"TenantProvider\"]\n5:I[48030,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ImpersonationBannerWrapper\"]\n6:I[39756,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n7:I[37457,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n8:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"OutletBoundary\"]\n9:\"$Sreact.suspense\"\nb:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ViewportBoundary\"]\nd:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"MetadataBoundary\"]\nf:I[68027,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n:HL[\"/_next/static/chunks/5628d92b5893add2.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"zpw_-rjFIDV5tlPPtnvRI\",\"c\":[\"\",\"_not-found\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/5628d92b5893add2.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/ef02697fb404726a.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/e483af34fc792d38.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-2\",{\"src\":\"/_next/static/chunks/247eb132b7f7b574.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"className\":\"font-sans antialiased\",\"style\":{\"background\":\"var(--bg)\",\"color\":\"var(--text)\"},\"children\":[[\"$\",\"$L2\",null,{}],[\"$\",\"$L3\",null,{\"attribute\":\"class\",\"defaultTheme\":\"dark\",\"enableSystem\":true,\"disableTransitionOnChange\":true,\"children\":[\"$\",\"$L4\",null,{\"children\":[[\"$\",\"$L5\",null,{}],[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L8\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@a\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$Lb\",null,{\"children\":\"$@c\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.Metadata\",\"children\":\"$@e\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"c:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[27201,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"IconMark\"]\ne:[[\"$\",\"title\",\"0\",{\"children\":\"Nomad Karaoke: Generator\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics\"}],[\"$\",\"link\",\"2\",{\"rel\":\"manifest\",\"href\":\"/manifest.webmanifest\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"sizes\":\"any\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"sizes\":\"16x16\",\"type\":\"image/png\"}],[\"$\",\"link\",\"5\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"6\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$L10\",\"7\",{}]]\na:null\n"])</script></body></html>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<!DOCTYPE html><!--zpw__rjFIDV5tlPPtnvRI--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/5628d92b5893add2.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/95f7e5934dbb0e5d.js"/><script src="/_next/static/chunks/112f346e31f991df.js" async=""></script><script src="/_next/static/chunks/a9ed54eed3e14c92.js" async=""></script><script src="/_next/static/chunks/c645af7d6b65f73e.js" async=""></script><script src="/_next/static/chunks/5997132b61dec430.js" async=""></script><script src="/_next/static/chunks/turbopack-2d9ca3017a9deedf.js" async=""></script><script src="/_next/static/chunks/ef02697fb404726a.js" async=""></script><script src="/_next/static/chunks/e483af34fc792d38.js" async=""></script><script src="/_next/static/chunks/247eb132b7f7b574.js" async=""></script><meta name="robots" content="noindex"/><title>404: This page could not be found.</title><title>Nomad Karaoke: Generator</title><meta name="description" content="Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics"/><link rel="manifest" href="/manifest.webmanifest"/><link rel="icon" href="/favicon.ico" sizes="any"/><link rel="icon" href="/favicon-16x16.png" sizes="16x16" type="image/png"/><link rel="icon" href="/favicon-32x32.png" sizes="32x32" type="image/png"/><link rel="apple-touch-icon" href="/apple-touch-icon.png"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body class="font-sans antialiased" style="background:var(--bg);color:var(--text)"><div hidden=""><!--$--><!--/$--></div><script>((a,b,c,d,e,f,g,h)=>{let i=document.documentElement,j=["light","dark"];function k(b){var c;(Array.isArray(a)?a:[a]).forEach(a=>{let c="class"===a,d=c&&f?e.map(a=>f[a]||a):e;c?(i.classList.remove(...d),i.classList.add(f&&f[b]?f[b]:b)):i.setAttribute(a,b)}),c=b,h&&j.includes(c)&&(i.style.colorScheme=c)}if(d)k(d);else try{let a=localStorage.getItem(b)||c,d=g&&"system"===a?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a;k(d)}catch(a){}})("class","theme","dark",null,["light","dark"],null,true,true)</script><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/95f7e5934dbb0e5d.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[72285,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ServiceWorkerRegistration\"]\n3:I[89554,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ThemeProvider\"]\n4:I[57091,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"TenantProvider\"]\n5:I[48030,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ImpersonationBannerWrapper\"]\n6:I[39756,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n7:I[37457,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n8:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"OutletBoundary\"]\n9:\"$Sreact.suspense\"\nb:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"ViewportBoundary\"]\nd:I[97367,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"MetadataBoundary\"]\nf:I[68027,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"default\"]\n:HL[\"/_next/static/chunks/5628d92b5893add2.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"zpw_-rjFIDV5tlPPtnvRI\",\"c\":[\"\",\"_not-found\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"/_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/5628d92b5893add2.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/ef02697fb404726a.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-1\",{\"src\":\"/_next/static/chunks/e483af34fc792d38.js\",\"async\":true,\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-2\",{\"src\":\"/_next/static/chunks/247eb132b7f7b574.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"className\":\"font-sans antialiased\",\"style\":{\"background\":\"var(--bg)\",\"color\":\"var(--text)\"},\"children\":[[\"$\",\"$L2\",null,{}],[\"$\",\"$L3\",null,{\"attribute\":\"class\",\"defaultTheme\":\"dark\",\"enableSystem\":true,\"disableTransitionOnChange\":true,\"children\":[\"$\",\"$L4\",null,{\"children\":[[\"$\",\"$L5\",null,{}],[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}]}]]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L6\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L7\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:children:props:children:1:props:children:props:children:1:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L8\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@a\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$Lb\",null,{\"children\":\"$@c\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.Metadata\",\"children\":\"$@e\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",\"$undefined\"],\"S\":true}\n"])</script><script>self.__next_f.push([1,"c:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[27201,[\"/_next/static/chunks/ef02697fb404726a.js\",\"/_next/static/chunks/e483af34fc792d38.js\",\"/_next/static/chunks/247eb132b7f7b574.js\"],\"IconMark\"]\ne:[[\"$\",\"title\",\"0\",{\"children\":\"Nomad Karaoke: Generator\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics\"}],[\"$\",\"link\",\"2\",{\"rel\":\"manifest\",\"href\":\"/manifest.webmanifest\",\"crossOrigin\":\"$undefined\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/favicon.ico\",\"sizes\":\"any\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/favicon-16x16.png\",\"sizes\":\"16x16\",\"type\":\"image/png\"}],[\"$\",\"link\",\"5\",{\"rel\":\"icon\",\"href\":\"/favicon-32x32.png\",\"sizes\":\"32x32\",\"type\":\"image/png\"}],[\"$\",\"link\",\"6\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-touch-icon.png\"}],[\"$\",\"$L10\",\"7\",{}]]\na:null\n"])</script></body></html>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
1:"$Sreact.fragment"
|
|
2
|
+
2:I[47257,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"ClientPageRoot"]
|
|
3
|
+
3:I[31713,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js","/_next/static/chunks/55c5ade44387bef8.js","/_next/static/chunks/692f5d9e0d700c76.js","/_next/static/chunks/dcde6ed684dacd0e.js"],"default"]
|
|
4
|
+
6:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"OutletBoundary"]
|
|
5
|
+
7:"$Sreact.suspense"
|
|
6
|
+
0:{"buildId":"zpw_-rjFIDV5tlPPtnvRI","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/55c5ade44387bef8.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/692f5d9e0d700c76.js","async":true}],["$","script","script-2",{"src":"/_next/static/chunks/dcde6ed684dacd0e.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
|
|
7
|
+
4:{}
|
|
8
|
+
5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
|
|
9
|
+
8:null
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
1:"$Sreact.fragment"
|
|
2
|
+
2:I[72285,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ServiceWorkerRegistration"]
|
|
3
|
+
3:I[89554,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ThemeProvider"]
|
|
4
|
+
4:I[57091,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"TenantProvider"]
|
|
5
|
+
5:I[48030,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ImpersonationBannerWrapper"]
|
|
6
|
+
6:I[39756,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
|
|
7
|
+
7:I[37457,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
|
|
8
|
+
8:I[47257,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"ClientPageRoot"]
|
|
9
|
+
9:I[31713,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js","/_next/static/chunks/55c5ade44387bef8.js","/_next/static/chunks/692f5d9e0d700c76.js","/_next/static/chunks/dcde6ed684dacd0e.js"],"default"]
|
|
10
|
+
c:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"OutletBoundary"]
|
|
11
|
+
d:"$Sreact.suspense"
|
|
12
|
+
f:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"ViewportBoundary"]
|
|
13
|
+
11:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"MetadataBoundary"]
|
|
14
|
+
13:I[68027,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
|
|
15
|
+
:HL["/_next/static/chunks/5628d92b5893add2.css","style"]
|
|
16
|
+
0:{"P":null,"b":"zpw_-rjFIDV5tlPPtnvRI","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/5628d92b5893add2.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/01a7f8fe40f1ff47.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/e483af34fc792d38.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"font-sans antialiased","style":{"background":"var(--bg)","color":"var(--text)"},"children":[["$","$L2",null,{}],["$","$L3",null,{"attribute":"class","defaultTheme":"dark","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L4",null,{"children":[["$","$L5",null,{}],["$","$L6",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L7",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]]}]}]]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L8",null,{"Component":"$9","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@a","$@b"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/55c5ade44387bef8.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/692f5d9e0d700c76.js","async":true,"nonce":"$undefined"}],["$","script","script-2",{"src":"/_next/static/chunks/dcde6ed684dacd0e.js","async":true,"nonce":"$undefined"}]],["$","$Lc",null,{"children":["$","$d",null,{"name":"Next.MetadataOutlet","children":"$@e"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lf",null,{"children":"$@10"}],["$","div",null,{"hidden":true,"children":["$","$L11",null,{"children":["$","$d",null,{"name":"Next.Metadata","children":"$@12"}]}]}],null]}],false]],"m":"$undefined","G":["$13",[]],"S":true}
|
|
17
|
+
a:{}
|
|
18
|
+
b:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
|
|
19
|
+
10:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
|
20
|
+
14:I[27201,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"IconMark"]
|
|
21
|
+
12:[["$","title","0",{"children":"Nomad Karaoke: Generator"}],["$","meta","1",{"name":"description","content":"Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics"}],["$","link","2",{"rel":"manifest","href":"/manifest.webmanifest","crossOrigin":"$undefined"}],["$","link","3",{"rel":"icon","href":"/favicon.ico","sizes":"any"}],["$","link","4",{"rel":"icon","href":"/favicon-16x16.png","sizes":"16x16","type":"image/png"}],["$","link","5",{"rel":"icon","href":"/favicon-32x32.png","sizes":"32x32","type":"image/png"}],["$","link","6",{"rel":"apple-touch-icon","href":"/apple-touch-icon.png"}],["$","$L14","7",{}]]
|
|
22
|
+
e:null
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
1:"$Sreact.fragment"
|
|
2
|
+
2:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"ViewportBoundary"]
|
|
3
|
+
4:I[97367,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"MetadataBoundary"]
|
|
4
|
+
5:"$Sreact.suspense"
|
|
5
|
+
7:I[27201,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"IconMark"]
|
|
6
|
+
0:{"buildId":"zpw_-rjFIDV5tlPPtnvRI","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":"$@3"}],["$","div",null,{"hidden":true,"children":["$","$L4",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$@6"}]}]}],null]}],"loading":null,"isPartial":false}
|
|
7
|
+
3:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
|
8
|
+
6:[["$","title","0",{"children":"Nomad Karaoke: Generator"}],["$","meta","1",{"name":"description","content":"Generate professional karaoke videos with AI-powered vocal separation and synchronized lyrics"}],["$","link","2",{"rel":"manifest","href":"/manifest.webmanifest"}],["$","link","3",{"rel":"icon","href":"/favicon.ico","sizes":"any"}],["$","link","4",{"rel":"icon","href":"/favicon-16x16.png","sizes":"16x16","type":"image/png"}],["$","link","5",{"rel":"icon","href":"/favicon-32x32.png","sizes":"32x32","type":"image/png"}],["$","link","6",{"rel":"apple-touch-icon","href":"/apple-touch-icon.png"}],["$","$L7","7",{}]]
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
1:"$Sreact.fragment"
|
|
2
|
+
2:I[72285,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ServiceWorkerRegistration"]
|
|
3
|
+
3:I[89554,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ThemeProvider"]
|
|
4
|
+
4:I[57091,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"TenantProvider"]
|
|
5
|
+
5:I[48030,["/_next/static/chunks/01a7f8fe40f1ff47.js","/_next/static/chunks/e483af34fc792d38.js"],"ImpersonationBannerWrapper"]
|
|
6
|
+
6:I[39756,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
|
|
7
|
+
7:I[37457,["/_next/static/chunks/ff1a16fafef87110.js","/_next/static/chunks/247eb132b7f7b574.js"],"default"]
|
|
8
|
+
:HL["/_next/static/chunks/5628d92b5893add2.css","style"]
|
|
9
|
+
0:{"buildId":"zpw_-rjFIDV5tlPPtnvRI","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/5628d92b5893add2.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/01a7f8fe40f1ff47.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/e483af34fc792d38.js","async":true}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"font-sans antialiased","style":{"background":"var(--bg)","color":"var(--text)"},"children":[["$","$L2",null,{}],["$","$L3",null,{"attribute":"class","defaultTheme":"dark","enableSystem":true,"disableTransitionOnChange":true,"children":["$","$L4",null,{"children":[["$","$L5",null,{}],["$","$L6",null,{"parallelRouterKey":"children","template":["$","$L7",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]]}]}]]}]}]]}],"loading":null,"isPartial":false}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
:HL["/_next/static/chunks/5628d92b5893add2.css","style"]
|
|
2
|
+
0:{"buildId":"zpw_-rjFIDV5tlPPtnvRI","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,41947,e=>{"use strict";let t=(0,e.i(75254).default)("X",[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]]);e.s(["default",()=>t])},37727,e=>{"use strict";var t=e.i(41947);e.s(["X",()=>t.default])},54858,e=>{"use strict";var t=e.i(47167);let a="localhost"===window.location.hostname?"":t.default.env.NEXT_PUBLIC_API_URL||"https://api.nomadkaraoke.com";function r(e){localStorage.setItem("karaoke_access_token",e)}function i(){return localStorage.getItem("karaoke_access_token")}function n(){localStorage.removeItem("karaoke_access_token")}function s(){let e={},t=i();return t&&(e.Authorization=`Bearer ${t}`),e}class o extends Error{status;data;constructor(e,t,a){super(e),this.name="ApiError",this.status=t,this.data=a}}async function l(e){if(!e.ok){let t;try{t=await e.json()}catch{t={detail:e.statusText}}throw new o(function(e,t){if("string"==typeof e?.detail)return e.detail;if("string"==typeof e?.message)return e.message;if("string"==typeof e?.error)return e.error;if(e?.detail?.message)return String(e.detail.message);if(e?.detail?.error)return String(e.detail.error);if(e?.detail&&"object"==typeof e.detail)try{return JSON.stringify(e.detail)}catch{}return t}(t,`Request failed with status ${e.status}`),e.status,t)}return e.json()}function c(e){return{async submitCorrections(t){let r=await fetch(`${a}/api/jobs/${e}/corrections`,{method:"PUT",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(t)});await l(r)},async submitAnnotations(t){let r=await fetch(`${a}/api/jobs/${e}/annotations`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({annotations:t})});await l(r)},updateHandlers:async t=>l(await fetch(`${a}/api/jobs/${e}/handlers`,{method:"PATCH",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({enabled_handlers:t})})),addLyrics:async(t,r)=>l(await fetch(`${a}/api/jobs/${e}/lyrics`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({source:t,lyrics:r})})),getAudioUrl(e){let t=i(),r=`${a}/api/audio/${e}`;return t?`${r}?token=${encodeURIComponent(t)}`:r},generatePreviewVideo:async t=>l(await fetch(`${a}/api/jobs/${e}/preview-video`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(t)})),getPreviewVideoUrl(e){let t=i(),r=`${a}/api/preview-video/${e}`;return t?`${r}?token=${encodeURIComponent(t)}`:r}}}e.s(["API_BASE_URL",0,a,"ApiError",()=>o,"adminApi",0,{async getStats(e){let t=new URLSearchParams;e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/admin/stats/overview${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},async listUsers(e){let t=new URLSearchParams;e?.limit&&t.set("limit",String(e.limit)),e?.offset&&t.set("offset",String(e.offset)),e?.search&&t.set("search",e.search),e?.sort_by&&t.set("sort_by",e.sort_by),e?.sort_order&&t.set("sort_order",e.sort_order),e?.include_inactive&&t.set("include_inactive","true"),e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/users/admin/users${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},getUserDetail:async e=>l(await fetch(`${a}/api/users/admin/users/${encodeURIComponent(e)}/detail`,{headers:s()})),addCredits:async(e,t,r)=>l(await fetch(`${a}/api/users/admin/credits`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({email:e,amount:t,reason:r})})),impersonateUser:async e=>l(await fetch(`${a}/api/admin/users/${encodeURIComponent(e)}/impersonate`,{method:"POST",headers:s()})),enableUser:async e=>l(await fetch(`${a}/api/users/admin/users/${encodeURIComponent(e)}/enable`,{method:"POST",headers:s()})),disableUser:async e=>l(await fetch(`${a}/api/users/admin/users/${encodeURIComponent(e)}/disable`,{method:"POST",headers:s()})),async listAllJobs(e){let t=new URLSearchParams;e?.status&&t.set("status",e.status),e?.user_email&&t.set("user_email",e.user_email),e?.environment&&t.set("environment",e.environment),e?.created_after&&t.set("created_after",e.created_after),e?.created_before&&t.set("created_before",e.created_before),e?.limit&&t.set("limit",String(e.limit)),e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/jobs${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},async getBetaStats(e){let t=new URLSearchParams;e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/users/admin/beta/stats${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},getBetaFeedback:async(e=50)=>l(await fetch(`${a}/api/users/admin/beta/feedback?limit=${e}`,{headers:s()})),deleteJob:async(e,t=!0)=>l(await fetch(`${a}/api/jobs/${e}?delete_files=${t}`,{method:"DELETE",headers:s()})),async listAudioSearches(e){let t=new URLSearchParams;e?.limit&&t.set("limit",String(e.limit)),e?.status_filter&&t.set("status_filter",e.status_filter),e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/admin/audio-searches${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},clearAudioSearchCache:async e=>l(await fetch(`${a}/api/admin/audio-searches/${e}/clear-cache`,{method:"POST",headers:s()})),clearAllCache:async()=>l(await fetch(`${a}/api/admin/cache`,{method:"DELETE",headers:s()})),getCacheStats:async()=>l(await fetch(`${a}/api/admin/cache/stats`,{headers:s()})),getCompletionMessage:async e=>l(await fetch(`${a}/api/admin/jobs/${e}/completion-message`,{headers:s()})),sendCompletionEmail:async(e,t,r=!0)=>l(await fetch(`${a}/api/admin/jobs/${e}/send-completion-email`,{method:"POST",headers:{...s(),"Content-Type":"application/json"},body:JSON.stringify({to_email:t,cc_admin:r})})),getJobFiles:async e=>l(await fetch(`${a}/api/admin/jobs/${e}/files`,{headers:s()})),updateJob:async(e,t)=>l(await fetch(`${a}/api/admin/jobs/${e}`,{method:"PATCH",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(t)})),resetJob:async(e,t)=>l(await fetch(`${a}/api/admin/jobs/${e}/reset`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({target_state:t})})),deleteJobOutputs:async e=>l(await fetch(`${a}/api/admin/jobs/${e}/delete-outputs`,{method:"POST",headers:s()})),getRateLimitStats:async()=>l(await fetch(`${a}/api/admin/rate-limits/stats`,{headers:s()})),getUserRateLimitStatus:async e=>l(await fetch(`${a}/api/admin/rate-limits/users/${encodeURIComponent(e)}`,{headers:s()})),getBlocklists:async()=>l(await fetch(`${a}/api/admin/rate-limits/blocklists`,{headers:s()})),addDisposableDomain:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/disposable-domains`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({domain:e})})),removeDisposableDomain:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/disposable-domains/${encodeURIComponent(e)}`,{method:"DELETE",headers:s()})),addBlockedEmail:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/blocked-emails`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({email:e})})),removeBlockedEmail:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/blocked-emails/${encodeURIComponent(e)}`,{method:"DELETE",headers:s()})),addBlockedIP:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/blocked-ips`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({ip_address:e})})),removeBlockedIP:async e=>l(await fetch(`${a}/api/admin/rate-limits/blocklists/blocked-ips/${encodeURIComponent(e)}`,{method:"DELETE",headers:s()})),getUserOverrides:async()=>l(await fetch(`${a}/api/admin/rate-limits/overrides`,{headers:s()})),setUserOverride:async(e,t)=>l(await fetch(`${a}/api/admin/rate-limits/overrides/${encodeURIComponent(e)}`,{method:"PUT",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(t)})),removeUserOverride:async e=>l(await fetch(`${a}/api/admin/rate-limits/overrides/${encodeURIComponent(e)}`,{method:"DELETE",headers:s()}))},"api",0,{async listJobs(e){let t=new URLSearchParams;e?.status&&t.set("status",e.status),e?.limit&&t.set("limit",String(e.limit)),e?.exclude_test!==void 0&&t.set("exclude_test",String(e.exclude_test));let r=`${a}/api/jobs${t.toString()?"?"+t.toString():""}`;return l(await fetch(r,{headers:s()}))},getJob:async e=>l(await fetch(`${a}/api/jobs/${e}`,{headers:s()})),async uploadJob(e,t,r,i){let n=new FormData;return n.append("file",e),n.append("artist",t),n.append("title",r),i?.enable_cdg!==void 0&&n.append("enable_cdg",String(i.enable_cdg)),i?.enable_txt!==void 0&&n.append("enable_txt",String(i.enable_txt)),i?.brand_prefix&&n.append("brand_prefix",i.brand_prefix),i?.enable_youtube_upload!==void 0&&n.append("enable_youtube_upload",String(i.enable_youtube_upload)),i?.theme_id&&n.append("theme_id",i.theme_id),i?.color_overrides&&n.append("color_overrides",JSON.stringify(i.color_overrides)),i?.non_interactive!==void 0&&n.append("non_interactive",String(i.non_interactive)),l(await fetch(`${a}/api/jobs/upload`,{method:"POST",headers:s(),body:n}))},async createJobFromUrl(e,t,r,i){let n={url:e};return t&&(n.artist=t),r&&(n.title=r),i?.enable_cdg!==void 0&&(n.enable_cdg=i.enable_cdg),i?.enable_txt!==void 0&&(n.enable_txt=i.enable_txt),i?.brand_prefix&&(n.brand_prefix=i.brand_prefix),i?.enable_youtube_upload!==void 0&&(n.enable_youtube_upload=i.enable_youtube_upload),i?.theme_id&&(n.theme_id=i.theme_id),i?.color_overrides&&(n.color_overrides=i.color_overrides),i?.non_interactive!==void 0&&(n.non_interactive=i.non_interactive),l(await fetch(`${a}/api/jobs/create-from-url`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(n)}))},getReviewData:async e=>l(await fetch(`${a}/api/jobs/${e}/review-data`,{headers:s()})),completeReview:async e=>l(await fetch(`${a}/api/jobs/${e}/complete-review`,{method:"POST",headers:s()})),getInstrumentalOptions:async e=>l(await fetch(`${a}/api/jobs/${e}/instrumental-options`,{headers:s()})),selectInstrumental:async(e,t)=>l(await fetch(`${a}/api/jobs/${e}/select-instrumental`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({selection:t})})),getInstrumentalAnalysis:async e=>l(await fetch(`${a}/api/jobs/${e}/instrumental-analysis`,{headers:s()})),getWaveformData:async(e,t=1e3)=>l(await fetch(`${a}/api/jobs/${e}/waveform-data?num_points=${t}`,{headers:s()})),async uploadCustomInstrumental(e,t){let r=new FormData;return r.append("file",t),l(await fetch(`${a}/api/jobs/${e}/upload-instrumental`,{method:"POST",headers:s(),body:r}))},createCustomInstrumental:async(e,t)=>l(await fetch(`${a}/api/jobs/${e}/create-custom-instrumental`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({mute_regions:t})})),getAudioStreamUrl(e,t){let r=i(),n=`${a}/api/jobs/${e}/audio-stream/${t}`;return r?`${n}?token=${encodeURIComponent(r)}`:n},getDownloadUrls:async e=>l(await fetch(`${a}/api/jobs/${e}/download-urls`,{headers:s()})),cancelJob:async(e,t)=>l(await fetch(`${a}/api/jobs/${e}/cancel`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({reason:t||"Cancelled by user"})})),deleteJob:async(e,t=!0)=>l(await fetch(`${a}/api/jobs/${e}?delete_files=${t}`,{method:"DELETE",headers:s()})),getDownloadUrl(e,t,r){let n=`${a}/api/jobs/${e}/download/${t}/${r}`,s=i();return s?`${n}?token=${encodeURIComponent(s)}`:n},async searchAudio(e,t,r=!1,i){let n={artist:e,title:t,auto_download:r};return i?.enable_cdg!==void 0&&(n.enable_cdg=i.enable_cdg),i?.enable_txt!==void 0&&(n.enable_txt=i.enable_txt),i?.brand_prefix&&(n.brand_prefix=i.brand_prefix),i?.enable_youtube_upload!==void 0&&(n.enable_youtube_upload=i.enable_youtube_upload),i?.theme_id&&(n.theme_id=i.theme_id),i?.color_overrides&&(n.color_overrides=i.color_overrides),i?.non_interactive!==void 0&&(n.non_interactive=i.non_interactive),i?.display_artist&&(n.display_artist=i.display_artist),i?.display_title&&(n.display_title=i.display_title),l(await fetch(`${a}/api/audio-search/search`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify(n)}))},getAudioSearchResults:async e=>l(await fetch(`${a}/api/audio-search/${e}/results`,{headers:s()})),selectAudioResult:async(e,t)=>l(await fetch(`${a}/api/audio-search/${e}/select`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({selection_index:t})})),async getJobLogs(e,t=100){let r=await fetch(`${a}/api/jobs/${e}/logs?limit=${t}`,{headers:s()});return(await l(r)).logs||[]},retryJob:async e=>l(await fetch(`${a}/api/jobs/${e}/retry`,{method:"POST",headers:s()})),async listThemes(){let e=await fetch(`${a}/api/themes`,{headers:s()});return(await l(e)).themes},async getTheme(e){let t=await fetch(`${a}/api/themes/${e}`,{headers:s()});return(await l(t)).theme},async getThemePreview(e){let t=await fetch(`${a}/api/themes/${e}/preview`,{headers:s()});return(await l(t)).preview_url},async getThemeYoutubeDescription(e){let t=await fetch(`${a}/api/themes/${e}/youtube-description`,{headers:s()});return(await l(t)).description},sendMagicLink:async e=>l(await fetch(`${a}/api/users/auth/magic-link`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:e})})),verifyMagicLink:async e=>l(await fetch(`${a}/api/users/auth/verify?token=${encodeURIComponent(e)}`,{method:"GET"})),getCurrentUser:async()=>l(await fetch(`${a}/api/users/me`,{headers:s()})),logout:async()=>l(await fetch(`${a}/api/users/auth/logout`,{method:"POST",headers:s()})),async getBackendInfo(){let e=a?`${a}/`:"/backend-info";return l(await fetch(e,{headers:s()}))},getEncodingWorkerHealth:async()=>l(await fetch(`${a}/api/health/encoding-worker`)),async getCreditPackages(){let e=await fetch(`${a}/api/users/credits/packages`);return(await l(e)).packages},async createCheckout(e,t){let r=await fetch(`${a}/api/users/credits/checkout`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({package_id:e,email:t.toLowerCase()})});return(await l(r)).checkout_url},async createMadeForYouCheckout(e){let t=await fetch(`${a}/api/users/made-for-you/checkout`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:e.email.toLowerCase(),artist:e.artist,title:e.title,source_type:e.source_type,youtube_url:e.youtube_url,notes:e.notes})}),r=await l(t);if(!r.checkout_url)throw Error("No checkout URL received");return r.checkout_url},enrollBetaTester:async(e,t,r)=>l(await fetch(`${a}/api/users/beta/enroll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:e.toLowerCase(),promise_text:t,accept_corrections_work:r})})),getVapidPublicKey:async()=>l(await fetch(`${a}/api/push/vapid-public-key`)),subscribePush:async(e,t,r)=>l(await fetch(`${a}/api/push/subscribe`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({endpoint:e,keys:t,device_name:r})})),unsubscribePush:async e=>l(await fetch(`${a}/api/push/unsubscribe`,{method:"POST",headers:{"Content-Type":"application/json",...s()},body:JSON.stringify({endpoint:e})})),listPushSubscriptions:async()=>l(await fetch(`${a}/api/push/subscriptions`,{headers:s()}))},"clearAccessToken",()=>n,"createLyricsReviewApiClient",()=>c,"getAccessToken",()=>i,"lyricsReviewApi",0,{getCorrectionData:async e=>l(await fetch(`${a}/api/jobs/${e}/corrections`,{headers:s()})),getAudioUrl(e){let t=i(),r=`${a}/api/audio/${e}`;return t?`${r}?token=${encodeURIComponent(t)}`:r}},"setAccessToken",()=>r])},68834,e=>{"use strict";var t=e.i(71645);let a=e=>{let t,a=new Set,r=(e,r)=>{let i="function"==typeof e?e(t):e;if(!Object.is(i,t)){let e=t;t=(null!=r?r:"object"!=typeof i||null===i)?i:Object.assign({},t,i),a.forEach(a=>a(t,e))}},i=()=>t,n={setState:r,getState:i,getInitialState:()=>s,subscribe:e=>(a.add(e),()=>a.delete(e))},s=t=e(r,i,n);return n},r=e=>{let r=e?a(e):a,i=e=>(function(e,a=e=>e){let r=t.default.useSyncExternalStore(e.subscribe,t.default.useCallback(()=>a(e.getState()),[e,a]),t.default.useCallback(()=>a(e.getInitialState()),[e,a]));return t.default.useDebugValue(r),r})(r,e);return Object.assign(i,r),i},i=e=>e?r(e):r;e.s(["create",()=>i],68834)},79473,e=>{"use strict";let t=e=>a=>{try{let r=e(a);if(r instanceof Promise)return r;return{then:e=>t(e)(r),catch(e){return this}}}catch(e){return{then(e){return this},catch:a=>t(a)(e)}}},a=(e,a)=>(r,i,n)=>{let s,o={storage:function(e,t){let a;try{a=e()}catch(e){return}return{getItem:e=>{var t;let r=e=>null===e?null:JSON.parse(e,void 0),i=null!=(t=a.getItem(e))?t:null;return i instanceof Promise?i.then(r):r(i)},setItem:(e,t)=>a.setItem(e,JSON.stringify(t,void 0)),removeItem:e=>a.removeItem(e)}}(()=>localStorage),partialize:e=>e,version:0,merge:(e,t)=>({...t,...e}),...a},l=!1,c=new Set,d=new Set,u=o.storage;if(!u)return e((...e)=>{console.warn(`[zustand persist middleware] Unable to update item '${o.name}', the given storage is currently unavailable.`),r(...e)},i,n);let m=()=>{let e=o.partialize({...i()});return u.setItem(o.name,{state:e,version:o.version})},p=n.setState;n.setState=(e,t)=>(p(e,t),m());let h=e((...e)=>(r(...e),m()),i,n);n.getInitialState=()=>h;let y=()=>{var e,a;if(!u)return;l=!1,c.forEach(e=>{var t;return e(null!=(t=i())?t:h)});let n=(null==(a=o.onRehydrateStorage)?void 0:a.call(o,null!=(e=i())?e:h))||void 0;return t(u.getItem.bind(u))(o.name).then(e=>{if(e)if("number"!=typeof e.version||e.version===o.version)return[!1,e.state];else{if(o.migrate){let t=o.migrate(e.state,e.version);return t instanceof Promise?t.then(e=>[!0,e]):[!0,t]}console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}return[!1,void 0]}).then(e=>{var t;let[a,n]=e;if(r(s=o.merge(n,null!=(t=i())?t:h),!0),a)return m()}).then(()=>{null==n||n(s,void 0),s=i(),l=!0,d.forEach(e=>e(s))}).catch(e=>{null==n||n(void 0,e)})};return n.persist={setOptions:e=>{o={...o,...e},e.storage&&(u=e.storage)},clearStorage:()=>{null==u||u.removeItem(o.name)},getOptions:()=>o,rehydrate:()=>y(),hasHydrated:()=>l,onHydrate:e=>(c.add(e),()=>{c.delete(e)}),onFinishHydration:e=>(d.add(e),()=>{d.delete(e)})},o.skipHydration||y(),s||h};e.s(["persist",()=>a])},38036,e=>{"use strict";var t=e.i(68834),a=e.i(79473),r=e.i(54858);let i=(0,t.create)()((0,a.persist)((e,t)=>({user:null,isLoading:!1,error:null,isImpersonating:!1,originalAdminToken:null,impersonatedUserEmail:null,sendMagicLink:async t=>{e({isLoading:!0,error:null});try{return await r.api.sendMagicLink(t),e({isLoading:!1}),!0}catch(t){return e({isLoading:!1,error:t instanceof Error?t.message:"Failed to send magic link"}),!1}},verifyMagicLink:async t=>{e({isLoading:!0,error:null});try{let a=await r.api.verifyMagicLink(t);(0,r.setAccessToken)(a.session_token);let i={token:a.session_token,email:a.user.email,role:a.user.role,credits:a.user.credits,display_name:a.user.display_name,total_jobs_created:a.user.total_jobs_created,total_jobs_completed:a.user.total_jobs_completed};return e({user:i,isLoading:!1}),!0}catch(t){return e({isLoading:!1,error:t instanceof Error?t.message:"Invalid or expired link"}),!1}},fetchUser:async()=>{let t=(0,r.getAccessToken)();if(!t)return e({user:null}),!1;e({isLoading:!0});try{let a=await r.api.getCurrentUser(),i={token:t,email:a.user.email,role:a.user.role,credits:a.user.credits,display_name:a.user.display_name,total_jobs_created:a.user.total_jobs_created,total_jobs_completed:a.user.total_jobs_completed};return e({user:i,isLoading:!1}),!0}catch{return(0,r.clearAccessToken)(),e({user:null,isLoading:!1}),!1}},logout:async()=>{try{await r.api.logout()}catch{}(0,r.clearAccessToken)(),e({user:null,error:null})},updateCredits:t=>e(e=>({user:e.user?{...e.user,credits:t}:null})),clearError:()=>e({error:null}),loginWithToken:async t=>{e({isLoading:!0,error:null});try{(0,r.setAccessToken)(t);let a=await r.api.getCurrentUser(),i={token:t,email:a.user.email,role:a.user.role,credits:a.user.credits,display_name:a.user.display_name,total_jobs_created:a.user.total_jobs_created,total_jobs_completed:a.user.total_jobs_completed};return e({user:i,isLoading:!1}),!0}catch{return(0,r.clearAccessToken)(),e({user:null,isLoading:!1,error:"Invalid token or server unavailable"}),!1}},startImpersonation:async a=>{if(t().isImpersonating)return e({error:"Already impersonating a user. End current impersonation first."}),!1;e({isLoading:!0,error:null});let i=(0,r.getAccessToken)();try{let t;if(!i)throw Error("No active session to preserve");let n=await r.adminApi.impersonateUser(a);(0,r.setAccessToken)(n.session_token);try{t=await r.api.getCurrentUser()}catch(e){throw(0,r.setAccessToken)(i),e}let s={token:n.session_token,email:t.user.email,role:t.user.role,credits:t.user.credits,display_name:t.user.display_name,total_jobs_created:t.user.total_jobs_created,total_jobs_completed:t.user.total_jobs_completed};return e({user:s,isLoading:!1,isImpersonating:!0,originalAdminToken:i,impersonatedUserEmail:a}),!0}catch(t){return e({isLoading:!1,error:t instanceof Error?t.message:"Failed to impersonate user"}),!1}},endImpersonation:()=>{let{originalAdminToken:a}=t();a&&((0,r.setAccessToken)(a),e({isImpersonating:!1,originalAdminToken:null,impersonatedUserEmail:null}),t().fetchUser())}}),{name:"nomad-karaoke-auth",partialize:e=>({user:e.user})}));(0,r.getAccessToken)()&&i.getState().fetchUser(),e.s(["useAuth",0,i])},86536,e=>{"use strict";let t=(0,e.i(75254).default)("Eye",[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]);e.s(["Eye",()=>t],86536)},24672,e=>{"use strict";var t=e.i(68834),a=e.i(54858);let r={logo_url:null,logo_height:40,primary_color:"#ff5bb8",secondary_color:"#8b5cf6",accent_color:"#ffdf6b",background_color:null,favicon_url:null,site_title:"Nomad Karaoke Generator",tagline:null},i={audio_search:!0,file_upload:!0,youtube_url:!0,youtube_upload:!0,dropbox_upload:!0,gdrive_upload:!0,theme_selection:!0,color_overrides:!0,enable_cdg:!0,enable_4k:!0,admin_access:!0},n={theme_id:null,locked_theme:null,distribution_mode:"all"},s=(0,t.create)()((e,t)=>({tenant:null,isDefault:!0,isLoading:!1,error:null,isInitialized:!1,get branding(){let{tenant:e}=t();return e?.branding??r},get features(){let{tenant:e}=t();return e?.features??i},get defaults(){let{tenant:e}=t();return e?.defaults??n},get tenantId(){let{tenant:e}=t();return e?.id??null},fetchTenantConfig:async()=>{if(!t().isLoading){e({isLoading:!0,error:null});try{let t=function(){let e=window.location.hostname.toLowerCase();if("localhost"===e||"127.0.0.1"===e)return new URLSearchParams(window.location.search).get("tenant");if(e.includes("nomadkaraoke.com")){let t=e.split(".");if((3===t.length||4===t.length&&"gen"===t[1])&&!["gen","api","www","buy","admin","app","beta"].includes(t[0]))return t[0]}return null}(),r=`${a.API_BASE_URL}/api/tenant/config`;t&&(r+=`?tenant=${encodeURIComponent(t)}`);let i=await fetch(r,{method:"GET",headers:{"Content-Type":"application/json",...t?{"X-Tenant-ID":t}:{}}});if(!i.ok)throw Error("Failed to fetch tenant configuration");let n=await i.json();e({tenant:n.tenant,isDefault:n.is_default,isLoading:!1,isInitialized:!0}),n.tenant&&o(n.tenant.branding)}catch(t){console.error("Failed to fetch tenant config:",t),e({tenant:null,isDefault:!0,isLoading:!1,error:t instanceof Error?t.message:"Failed to load tenant configuration",isInitialized:!0})}}},setTenant:(t,a)=>{e({tenant:t,isDefault:a,isInitialized:!0}),t&&o(t.branding)},clearError:()=>e({error:null})}));function o(e){if("undefined"==typeof document)return;let t=document.documentElement;if(t.style.setProperty("--tenant-primary",e.primary_color),t.style.setProperty("--tenant-secondary",e.secondary_color),e.accent_color&&t.style.setProperty("--tenant-accent",e.accent_color),e.background_color&&t.style.setProperty("--tenant-background",e.background_color),e.site_title&&(document.title=e.site_title),e.favicon_url){let t=document.querySelector("link[rel~='icon']");t&&(t.href=e.favicon_url)}}e.s(["useTenant",0,s])},89554,e=>{"use strict";var t=e.i(43476),a=e.i(71645),r=(e,t,a,r,i,n,s,o)=>{let l=document.documentElement,c=["light","dark"];function d(t){var a;(Array.isArray(e)?e:[e]).forEach(e=>{let a="class"===e,r=a&&n?i.map(e=>n[e]||e):i;a?(l.classList.remove(...r),l.classList.add(n&&n[t]?n[t]:t)):l.setAttribute(e,t)}),a=t,o&&c.includes(a)&&(l.style.colorScheme=a)}if(r)d(r);else try{let e=localStorage.getItem(t)||a,r=s&&"system"===e?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e;d(r)}catch(e){}},i=["light","dark"],n="(prefers-color-scheme: dark)",s="undefined"==typeof window,o=a.createContext(void 0),l=e=>a.useContext(o)?a.createElement(a.Fragment,null,e.children):a.createElement(d,{...e}),c=["light","dark"],d=({forcedTheme:e,disableTransitionOnChange:t=!1,enableSystem:r=!0,enableColorScheme:s=!0,storageKey:l="theme",themes:d=c,defaultTheme:y=r?"system":"light",attribute:f="data-theme",value:g,children:b,nonce:_,scriptProps:w})=>{let[v,$]=a.useState(()=>m(l,y)),[S,k]=a.useState(()=>"system"===v?h():v),T=g?Object.values(g):d,j=a.useCallback(e=>{let a=e;if(!a)return;"system"===e&&r&&(a=h());let n=g?g[a]:a,o=t?p(_):null,l=document.documentElement,c=e=>{"class"===e?(l.classList.remove(...T),n&&l.classList.add(n)):e.startsWith("data-")&&(n?l.setAttribute(e,n):l.removeAttribute(e))};if(Array.isArray(f)?f.forEach(c):c(f),s){let e=i.includes(y)?y:null,t=i.includes(a)?a:e;l.style.colorScheme=t}null==o||o()},[_]),C=a.useCallback(e=>{let t="function"==typeof e?e(v):e;$(t);try{localStorage.setItem(l,t)}catch(e){}},[v]),O=a.useCallback(t=>{k(h(t)),"system"===v&&r&&!e&&j("system")},[v,e]);a.useEffect(()=>{let e=window.matchMedia(n);return e.addListener(O),O(e),()=>e.removeListener(O)},[O]),a.useEffect(()=>{let e=e=>{e.key===l&&(e.newValue?$(e.newValue):C(y))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)},[C]),a.useEffect(()=>{j(null!=e?e:v)},[e,v]);let E=a.useMemo(()=>({theme:v,setTheme:C,forcedTheme:e,resolvedTheme:"system"===v?S:v,themes:r?[...d,"system"]:d,systemTheme:r?S:void 0}),[v,C,e,S,r,d]);return a.createElement(o.Provider,{value:E},a.createElement(u,{forcedTheme:e,storageKey:l,attribute:f,enableSystem:r,enableColorScheme:s,defaultTheme:y,value:g,themes:d,nonce:_,scriptProps:w}),b)},u=a.memo(({forcedTheme:e,storageKey:t,attribute:i,enableSystem:n,enableColorScheme:s,defaultTheme:o,value:l,themes:c,nonce:d,scriptProps:u})=>{let m=JSON.stringify([i,t,o,e,c,l,n,s]).slice(1,-1);return a.createElement("script",{...u,suppressHydrationWarning:!0,nonce:"undefined"==typeof window?d:"",dangerouslySetInnerHTML:{__html:`(${r.toString()})(${m})`}})}),m=(e,t)=>{let a;if(!s){try{a=localStorage.getItem(e)||void 0}catch(e){}return a||t}},p=e=>{let t=document.createElement("style");return e&&t.setAttribute("nonce",e),t.appendChild(document.createTextNode("*,*::before,*::after{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}")),document.head.appendChild(t),()=>{window.getComputedStyle(document.body),setTimeout(()=>{document.head.removeChild(t)},1)}},h=e=>(e||(e=window.matchMedia(n)),e.matches?"dark":"light");function y({children:e,...a}){return(0,t.jsx)(l,{...a,children:e})}e.s(["ThemeProvider",()=>y],89554)},57091,e=>{"use strict";var t=e.i(43476),a=e.i(71645),r=e.i(24672);function i({children:e}){let{fetchTenantConfig:i,isInitialized:n}=(0,r.useTenant)();return(0,a.useEffect)(()=>{n||i()},[i,n]),(0,t.jsx)(t.Fragment,{children:e})}function n(){let{isInitialized:e,isLoading:t}=(0,r.useTenant)();return e&&!t}function s({children:e,fallback:a}){return n()?(0,t.jsx)(t.Fragment,{children:e}):a??null}e.s(["TenantProvider",()=>i,"TenantReady",()=>s,"useTenantReady",()=>n])},48030,e=>{"use strict";var t=e.i(43476),a=e.i(38036),r=e.i(67881),i=e.i(37727),n=e.i(86536);function s(){let{isImpersonating:e,impersonatedUserEmail:s,endImpersonation:o}=(0,a.useAuth)();return e?(0,t.jsxs)("div",{className:"bg-amber-500 text-amber-950 px-4 py-2 flex items-center justify-between gap-4 text-sm font-medium",children:[(0,t.jsxs)("div",{className:"flex items-center gap-2",children:[(0,t.jsx)(n.Eye,{className:"w-4 h-4"}),(0,t.jsxs)("span",{children:["Viewing as ",(0,t.jsx)("strong",{children:s})]})]}),(0,t.jsxs)(r.Button,{variant:"outline",size:"sm",onClick:o,className:"bg-amber-100 hover:bg-amber-200 text-amber-950 border-amber-600 h-7 px-3",children:[(0,t.jsx)(i.X,{className:"w-3 h-3 mr-1"}),"Stop Impersonating"]})]}):null}function o(){return(0,t.jsx)(s,{})}e.s(["ImpersonationBannerWrapper",()=>o],48030)},72285,e=>{"use strict";var t=e.i(71645);function a(){return(0,t.useEffect)(()=>{let e="localhost"===window.location.hostname;"https:"===window.location.protocol||e?"serviceWorker"in navigator?navigator.serviceWorker.register("/sw.js",{scope:"/"}).then(e=>{console.log("[SW] Service worker registered:",e.scope),e.addEventListener("updatefound",()=>{let t=e.installing;t&&(console.log("[SW] New service worker installing..."),t.addEventListener("statechange",()=>{"installed"===t.state&&navigator.serviceWorker.controller&&console.log("[SW] New service worker installed, refresh for updates")}))})}).catch(e=>{console.error("[SW] Service worker registration failed:",e)}):console.log("[SW] Service workers not supported"):console.log("[SW] Skipping service worker registration: requires HTTPS")},[]),null}e.s(["ServiceWorkerRegistration",()=>a])}]);
|