diff --git a/README.md b/README.md
index 99637125ae..bcb0c53311 100644
--- a/README.md
+++ b/README.md
@@ -76,21 +76,24 @@ Jellyfin Web is the frontend used for most of the clients available for end user
```
.
└── src
- ├── assets # Static assets
- ├── components # Higher order visual components and React components
- ├── controllers # Legacy page views and controllers 🧹
- ├── elements # Basic webcomponents and React wrappers 🧹
- ├── hooks # Custom React hooks
- ├── legacy # Polyfills for legacy browsers
- ├── libraries # Third party libraries 🧹
- ├── plugins # Client plugins
- ├── routes # React routes/pages
- ├── scripts # Random assortment of visual components and utilities 🐉
- ├── strings # Translation files
- ├── styles # Common app Sass stylesheets
- ├── themes # CSS themes
- ├── types # Common TypeScript interfaces/types
- └── utils # Utility functions
+ ├── apps
+ │ ├── experimental # New experimental app layout
+ │ └── stable # Classic (stable) app layout
+ ├── assets # Static assets
+ ├── components # Higher order visual components and React components
+ ├── controllers # Legacy page views and controllers 🧹
+ ├── elements # Basic webcomponents and React wrappers 🧹
+ ├── hooks # Custom React hooks
+ ├── legacy # Polyfills for legacy browsers
+ ├── libraries # Third party libraries 🧹
+ ├── plugins # Client plugins
+ ├── routes # React routes/pages
+ ├── scripts # Random assortment of visual components and utilities 🐉
+ ├── strings # Translation files
+ ├── styles # Common app Sass stylesheets
+ ├── themes # CSS themes
+ ├── types # Common TypeScript interfaces/types
+ └── utils # Utility functions
```
- 🧹 — Needs cleanup
diff --git a/src/App.tsx b/src/RootApp.tsx
similarity index 60%
rename from src/App.tsx
rename to src/RootApp.tsx
index d72fd3831e..dddf31b5b1 100644
--- a/src/App.tsx
+++ b/src/RootApp.tsx
@@ -1,13 +1,16 @@
+import loadable from '@loadable/component';
import { History } from '@remix-run/router';
import React from 'react';
+import StableApp from './apps/stable/App';
import AppHeader from './components/AppHeader';
import Backdrop from './components/Backdrop';
import { HistoryRouter } from './components/HistoryRouter';
import { ApiProvider } from './hooks/useApi';
-import { AppRoutes, ExperimentalAppRoutes } from './routes';
-const App = ({ history }: { history: History }) => {
+const ExperimentalApp = loadable(() => import('./apps/experimental/App'));
+
+const RootApp = ({ history }: { history: History }) => {
const layoutMode = localStorage.getItem('layout');
return (
@@ -18,11 +21,15 @@ const App = ({ history }: { history: History }) => {
- {layoutMode === 'experimental' ?
:
}
+ {
+ layoutMode === 'experimental' ?
+
:
+
+ }
);
};
-export default App;
+export default RootApp;
diff --git a/src/apps/experimental/App.tsx b/src/apps/experimental/App.tsx
new file mode 100644
index 0000000000..842cdaf38a
--- /dev/null
+++ b/src/apps/experimental/App.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+
+import AppHeader from '../../components/AppHeader';
+import Backdrop from '../../components/Backdrop';
+import { ExperimentalAppRoutes } from './routes/AppRoutes';
+
+const ExperimentalApp = () => (
+ <>
+
+
+
+
+
+
+
+ >
+);
+
+export default ExperimentalApp;
diff --git a/src/routes/experimentalAppRoutes/index.tsx b/src/apps/experimental/routes/AppRoutes.tsx
similarity index 82%
rename from src/routes/experimentalAppRoutes/index.tsx
rename to src/apps/experimental/routes/AppRoutes.tsx
index bd4cf8a19f..e87476c554 100644
--- a/src/routes/experimentalAppRoutes/index.tsx
+++ b/src/apps/experimental/routes/AppRoutes.tsx
@@ -1,10 +1,10 @@
import React from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
-import ConnectionRequired from '../../components/ConnectionRequired';
-import ServerContentPage from '../../components/ServerContentPage';
-import { toAsyncPageRoute } from '../AsyncRoute';
-import { toViewManagerPageRoute } from '../LegacyRoute';
+import ConnectionRequired from '../../../components/ConnectionRequired';
+import ServerContentPage from '../../../components/ServerContentPage';
+import { toAsyncPageRoute } from '../../../components/router/AsyncRoute';
+import { toViewManagerPageRoute } from '../../../components/router/LegacyRoute';
import { ASYNC_ADMIN_ROUTES, ASYNC_USER_ROUTES } from './asyncRoutes';
import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
diff --git a/src/routes/experimentalAppRoutes/asyncRoutes/admin.ts b/src/apps/experimental/routes/asyncRoutes/admin.ts
similarity index 85%
rename from src/routes/experimentalAppRoutes/asyncRoutes/admin.ts
rename to src/apps/experimental/routes/asyncRoutes/admin.ts
index 3c75058288..0f2ec6b9cf 100644
--- a/src/routes/experimentalAppRoutes/asyncRoutes/admin.ts
+++ b/src/apps/experimental/routes/asyncRoutes/admin.ts
@@ -1,4 +1,4 @@
-import { AsyncRoute } from '../../AsyncRoute';
+import { AsyncRoute } from '../../../../components/router/AsyncRoute';
export const ASYNC_ADMIN_ROUTES: AsyncRoute[] = [
{ path: 'usernew.html', page: 'user/usernew' },
diff --git a/src/routes/experimentalAppRoutes/asyncRoutes/index.ts b/src/apps/experimental/routes/asyncRoutes/index.ts
similarity index 100%
rename from src/routes/experimentalAppRoutes/asyncRoutes/index.ts
rename to src/apps/experimental/routes/asyncRoutes/index.ts
diff --git a/src/routes/experimentalAppRoutes/asyncRoutes/user.ts b/src/apps/experimental/routes/asyncRoutes/user.ts
similarity index 77%
rename from src/routes/experimentalAppRoutes/asyncRoutes/user.ts
rename to src/apps/experimental/routes/asyncRoutes/user.ts
index 7126b0f2ad..44674e888c 100644
--- a/src/routes/experimentalAppRoutes/asyncRoutes/user.ts
+++ b/src/apps/experimental/routes/asyncRoutes/user.ts
@@ -1,4 +1,4 @@
-import { AsyncRoute } from '../../AsyncRoute';
+import { AsyncRoute } from '../../../../components/router/AsyncRoute';
export const ASYNC_USER_ROUTES: AsyncRoute[] = [
{ path: 'search.html', page: 'search' },
diff --git a/src/routes/experimentalAppRoutes/legacyRoutes/admin.ts b/src/apps/experimental/routes/legacyRoutes/admin.ts
similarity index 98%
rename from src/routes/experimentalAppRoutes/legacyRoutes/admin.ts
rename to src/apps/experimental/routes/legacyRoutes/admin.ts
index 16365e4fc8..dd1f95f6e5 100644
--- a/src/routes/experimentalAppRoutes/legacyRoutes/admin.ts
+++ b/src/apps/experimental/routes/legacyRoutes/admin.ts
@@ -1,4 +1,4 @@
-import { LegacyRoute } from '../../LegacyRoute';
+import { LegacyRoute } from '../../../../components/router/LegacyRoute';
export const LEGACY_ADMIN_ROUTES: LegacyRoute[] = [
{
diff --git a/src/routes/appRoutes/legacyRoutes/index.ts b/src/apps/experimental/routes/legacyRoutes/index.ts
similarity index 100%
rename from src/routes/appRoutes/legacyRoutes/index.ts
rename to src/apps/experimental/routes/legacyRoutes/index.ts
diff --git a/src/routes/appRoutes/legacyRoutes/public.ts b/src/apps/experimental/routes/legacyRoutes/public.ts
similarity index 96%
rename from src/routes/appRoutes/legacyRoutes/public.ts
rename to src/apps/experimental/routes/legacyRoutes/public.ts
index 15f8f0e8a9..4fdb6a9395 100644
--- a/src/routes/appRoutes/legacyRoutes/public.ts
+++ b/src/apps/experimental/routes/legacyRoutes/public.ts
@@ -1,4 +1,4 @@
-import { LegacyRoute } from '../../LegacyRoute';
+import { LegacyRoute } from '../../../../components/router/LegacyRoute';
export const LEGACY_PUBLIC_ROUTES: LegacyRoute[] = [
{
diff --git a/src/routes/experimentalAppRoutes/legacyRoutes/user.ts b/src/apps/experimental/routes/legacyRoutes/user.ts
similarity index 97%
rename from src/routes/experimentalAppRoutes/legacyRoutes/user.ts
rename to src/apps/experimental/routes/legacyRoutes/user.ts
index cc41c99957..49afc715f1 100644
--- a/src/routes/experimentalAppRoutes/legacyRoutes/user.ts
+++ b/src/apps/experimental/routes/legacyRoutes/user.ts
@@ -1,4 +1,4 @@
-import { LegacyRoute } from '../../LegacyRoute';
+import { LegacyRoute } from '../../../../components/router/LegacyRoute';
export const LEGACY_USER_ROUTES: LegacyRoute[] = [
{
diff --git a/src/apps/stable/App.tsx b/src/apps/stable/App.tsx
new file mode 100644
index 0000000000..7d619f6230
--- /dev/null
+++ b/src/apps/stable/App.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+
+import AppHeader from '../../components/AppHeader';
+import Backdrop from '../../components/Backdrop';
+import { AppRoutes } from './routes/AppRoutes';
+
+const StableApp = () => (
+ <>
+
+
+
+
+
+ >
+);
+
+export default StableApp;
diff --git a/src/routes/appRoutes/index.tsx b/src/apps/stable/routes/AppRoutes.tsx
similarity index 81%
rename from src/routes/appRoutes/index.tsx
rename to src/apps/stable/routes/AppRoutes.tsx
index 0136dc5531..cdeaedfe54 100644
--- a/src/routes/appRoutes/index.tsx
+++ b/src/apps/stable/routes/AppRoutes.tsx
@@ -1,10 +1,10 @@
import React from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
-import ConnectionRequired from '../../components/ConnectionRequired';
-import ServerContentPage from '../../components/ServerContentPage';
-import { toAsyncPageRoute } from '../AsyncRoute';
-import { toViewManagerPageRoute } from '../LegacyRoute';
+import ConnectionRequired from '../../../components/ConnectionRequired';
+import ServerContentPage from '../../../components/ServerContentPage';
+import { toAsyncPageRoute } from '../../../components/router/AsyncRoute';
+import { toViewManagerPageRoute } from '../../../components/router/LegacyRoute';
import { ASYNC_USER_ROUTES } from './asyncRoutes';
import { LEGACY_ADMIN_ROUTES, LEGACY_PUBLIC_ROUTES, LEGACY_USER_ROUTES } from './legacyRoutes';
diff --git a/src/routes/appRoutes/asyncRoutes/index.ts b/src/apps/stable/routes/asyncRoutes/index.ts
similarity index 100%
rename from src/routes/appRoutes/asyncRoutes/index.ts
rename to src/apps/stable/routes/asyncRoutes/index.ts
diff --git a/src/routes/appRoutes/asyncRoutes/user.ts b/src/apps/stable/routes/asyncRoutes/user.ts
similarity index 57%
rename from src/routes/appRoutes/asyncRoutes/user.ts
rename to src/apps/stable/routes/asyncRoutes/user.ts
index 23621101be..7b86c9c7c0 100644
--- a/src/routes/appRoutes/asyncRoutes/user.ts
+++ b/src/apps/stable/routes/asyncRoutes/user.ts
@@ -1,4 +1,4 @@
-import { AsyncRoute } from '../../AsyncRoute';
+import { AsyncRoute } from '../../../../components/router/AsyncRoute';
export const ASYNC_USER_ROUTES: AsyncRoute[] = [
{ path: 'search.html', page: 'search' }
diff --git a/src/routes/appRoutes/legacyRoutes/admin.ts b/src/apps/stable/routes/legacyRoutes/admin.ts
similarity index 98%
rename from src/routes/appRoutes/legacyRoutes/admin.ts
rename to src/apps/stable/routes/legacyRoutes/admin.ts
index 055f97c57f..0f358a5d65 100644
--- a/src/routes/appRoutes/legacyRoutes/admin.ts
+++ b/src/apps/stable/routes/legacyRoutes/admin.ts
@@ -1,4 +1,4 @@
-import { LegacyRoute } from '../../LegacyRoute';
+import { LegacyRoute } from '../../../../components/router/LegacyRoute';
export const LEGACY_ADMIN_ROUTES: LegacyRoute[] = [
{
diff --git a/src/routes/experimentalAppRoutes/legacyRoutes/index.ts b/src/apps/stable/routes/legacyRoutes/index.ts
similarity index 100%
rename from src/routes/experimentalAppRoutes/legacyRoutes/index.ts
rename to src/apps/stable/routes/legacyRoutes/index.ts
diff --git a/src/routes/experimentalAppRoutes/legacyRoutes/public.ts b/src/apps/stable/routes/legacyRoutes/public.ts
similarity index 96%
rename from src/routes/experimentalAppRoutes/legacyRoutes/public.ts
rename to src/apps/stable/routes/legacyRoutes/public.ts
index 15f8f0e8a9..4fdb6a9395 100644
--- a/src/routes/experimentalAppRoutes/legacyRoutes/public.ts
+++ b/src/apps/stable/routes/legacyRoutes/public.ts
@@ -1,4 +1,4 @@
-import { LegacyRoute } from '../../LegacyRoute';
+import { LegacyRoute } from '../../../../components/router/LegacyRoute';
export const LEGACY_PUBLIC_ROUTES: LegacyRoute[] = [
{
diff --git a/src/routes/appRoutes/legacyRoutes/user.ts b/src/apps/stable/routes/legacyRoutes/user.ts
similarity index 97%
rename from src/routes/appRoutes/legacyRoutes/user.ts
rename to src/apps/stable/routes/legacyRoutes/user.ts
index 4179907cb4..8f460dcbc2 100644
--- a/src/routes/appRoutes/legacyRoutes/user.ts
+++ b/src/apps/stable/routes/legacyRoutes/user.ts
@@ -1,4 +1,4 @@
-import { LegacyRoute } from '../../LegacyRoute';
+import { LegacyRoute } from '../../../../components/router/LegacyRoute';
export const LEGACY_USER_ROUTES: LegacyRoute[] = [
{
diff --git a/src/routes/AsyncRoute.tsx b/src/components/router/AsyncRoute.tsx
similarity index 89%
rename from src/routes/AsyncRoute.tsx
rename to src/components/router/AsyncRoute.tsx
index ba5bc90c42..6fb189e8bf 100644
--- a/src/routes/AsyncRoute.tsx
+++ b/src/components/router/AsyncRoute.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { Route } from 'react-router-dom';
-import AsyncPage from '../components/AsyncPage';
+import AsyncPage from '../AsyncPage';
export interface AsyncRoute {
/** The URL path for this route. */
diff --git a/src/routes/LegacyRoute.tsx b/src/components/router/LegacyRoute.tsx
similarity index 80%
rename from src/routes/LegacyRoute.tsx
rename to src/components/router/LegacyRoute.tsx
index f548a122cc..bba780a513 100644
--- a/src/routes/LegacyRoute.tsx
+++ b/src/components/router/LegacyRoute.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { Route } from 'react-router-dom';
-import ViewManagerPage, { ViewManagerPageProps } from '../components/viewManager/ViewManagerPage';
+import ViewManagerPage, { ViewManagerPageProps } from '../viewManager/ViewManagerPage';
export interface LegacyRoute {
path: string,
diff --git a/src/index.jsx b/src/index.jsx
index 87e4fde803..2b9aafbd5d 100644
--- a/src/index.jsx
+++ b/src/index.jsx
@@ -34,7 +34,7 @@ import './legacy/htmlMediaElement';
import './legacy/vendorStyles';
import { currentSettings } from './scripts/settings/userSettings';
import taskButton from './scripts/taskbutton';
-import App from './App.tsx';
+import RootApp from './RootApp.tsx';
import './styles/livetv.scss';
import './styles/dashboard.scss';
@@ -151,7 +151,7 @@ async function onAppReady() {
ReactDOM.render(
-
+
,
root
);
diff --git a/src/routes/index.tsx b/src/routes/index.tsx
deleted file mode 100644
index d06d48a747..0000000000
--- a/src/routes/index.tsx
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from './appRoutes';
-export * from './experimentalAppRoutes';