diff --git a/TODO.md b/TODO.md index acd313b1..023979c1 100644 --- a/TODO.md +++ b/TODO.md @@ -10,7 +10,7 @@ - [ ] Bundle **compiled** code - [x] Get clear on paths - [x] ESLint root package dependency usage -- [ ] Move themes to `packages/themes` +- [x] Move themes to `packages/themes` ## Backend @@ -48,3 +48,7 @@ - [ ] Add Posthog - [ ] Add New relic + +## Migration Scripts + +- [ ] Migrate custom themes from `%APPDATA%/Shabad OS/themes` to `%APPDATA%/Shabad OS/themes/presenter` and `%APPDATA%/Shabad OS/themes/overlay` diff --git a/apps/backend/package.json b/apps/backend/package.json index ae27d98a..707d8cc6 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -14,6 +14,7 @@ "@presenter/contract": "*", "@presenter/node": "*", "@presenter/swiss-knife": "*", + "@presenter/themes": "*", "@shabados/database": "^4.8.7", "body-parser": "^1.20.0", "chalk": "^5.3.0", @@ -28,7 +29,7 @@ "express": "^4.18.1", "fp-ts": "^2.12.2", "gurmukhi-utils": "^3.2.1", - "helmet": "^5.0.2", + "helmet": "^7.1.0", "import-fresh": "^3.3.0", "lodash-es": "^4.17.21", "memoizee": "^0.4.15", diff --git a/apps/backend/src/features/actions/index.ts b/apps/backend/src/features/actions/index.ts index 438914b7..b01fe6dd 100644 --- a/apps/backend/src/features/actions/index.ts +++ b/apps/backend/src/features/actions/index.ts @@ -1,4 +1,4 @@ -import { CUSTOM_OVERLAY_THEMES_FOLDER, LOG_FOLDER } from '@presenter/node' +import { LOG_FOLDER, USER_OVERLAY_THEMES_FOLDER } from '@presenter/node' import open from 'open' import ipc from '~/services/ipc' @@ -9,7 +9,7 @@ type ActionsModuleOptions = { } const createActionsModule = ( { socketServer }: ActionsModuleOptions ) => { - socketServer.on( 'action:open-overlay-folder', () => void open( CUSTOM_OVERLAY_THEMES_FOLDER ) ) + socketServer.on( 'action:open-overlay-folder', () => void open( USER_OVERLAY_THEMES_FOLDER ) ) socketServer.on( 'action:open-logs-folder', () => void open( LOG_FOLDER ) ) socketServer.on( 'action:open-window', () => ipc.send( 'action:open-window', undefined ) ) socketServer.on( 'action:open-external-url', ( url: string ) => void open( url ) ) diff --git a/apps/backend/src/features/themes/api.ts b/apps/backend/src/features/themes/api.ts deleted file mode 100644 index 4f0b974b..00000000 --- a/apps/backend/src/features/themes/api.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Router } from 'express' - -import { getOverlayThemeNames, getPresenterThemeNames } from './themes' - -const createApi = () => { - const api = Router() - - api.get( '/presenter/themes', ( _, res ) => void getPresenterThemeNames().then( res.json ) ) - api.get( '/overlay/themes', ( _, res ) => void getOverlayThemeNames().then( res.json ) ) - - return api -} - -export default createApi diff --git a/apps/backend/src/features/themes/index.ts b/apps/backend/src/features/themes/index.ts index f12b28b0..46a727b7 100644 --- a/apps/backend/src/features/themes/index.ts +++ b/apps/backend/src/features/themes/index.ts @@ -1,27 +1,26 @@ import { copyFile } from 'node:fs/promises' import { join } from 'node:path' -import { CUSTOM_OVERLAY_THEMES_FOLDER, CUSTOM_THEMES_FOLDER } from '@presenter/node' +import { USER_OVERLAY_THEMES_FOLDER, USER_PRESENTER_THEMES_FOLDER } from '@presenter/node' import express, { Application } from 'express' -import { FRONTEND_OVERLAY_THEMES_FOLDER, FRONTEND_THEMES_FOLDER } from '~/helpers/consts' +import { OVERLAY_THEMES_FOLDER, PRESENTER_THEMES_FOLDER } from '~/helpers/consts' -import createApi from './api' +import { getOverlayThemeNames, getPresenterThemeNames } from './themes' const copyExampleThemes = () => Promise.all( [ - [ FRONTEND_OVERLAY_THEMES_FOLDER, CUSTOM_OVERLAY_THEMES_FOLDER ], - [ FRONTEND_THEMES_FOLDER, CUSTOM_THEMES_FOLDER ], + [ OVERLAY_THEMES_FOLDER, USER_OVERLAY_THEMES_FOLDER ], + [ PRESENTER_THEMES_FOLDER, USER_PRESENTER_THEMES_FOLDER ], ].map( ( [ src, dest ] ) => copyFile( join( src, 'Example.template' ), join( dest, 'Example.css' ), ) ) ) const mounts = [ - [ '/presenter/themes', FRONTEND_THEMES_FOLDER ], - [ '/presenter/themes', CUSTOM_THEMES_FOLDER ], - [ '/presenter/themes/*', join( FRONTEND_OVERLAY_THEMES_FOLDER, 'Day.css' ) ], - [ '/overlay/themes', FRONTEND_OVERLAY_THEMES_FOLDER ], - [ '/overlay/themes/', CUSTOM_OVERLAY_THEMES_FOLDER ], + [ 'presenter', PRESENTER_THEMES_FOLDER ], + [ 'presenter', USER_PRESENTER_THEMES_FOLDER ], + [ 'overlay', OVERLAY_THEMES_FOLDER ], + [ 'overlay', USER_OVERLAY_THEMES_FOLDER ], ] as const type ThemesModuleOptions = { @@ -29,12 +28,12 @@ type ThemesModuleOptions = { } const createThemesModule = async ( { api }: ThemesModuleOptions ) => { - mounts.forEach( ( [ prefix, dir ] ) => api.use( prefix, express.static( dir ) ) ) + mounts.forEach( ( [ prefix, dir ] ) => api.use( `/themes/${prefix}`, express.static( dir ) ) ) - api.use( createApi() ) + api.get( '/themes/presenter', ( _, res ) => void getPresenterThemeNames().then( ( r ) => res.json( r ) ) ) + api.get( '/themes/overlay', ( _, res ) => void getOverlayThemeNames().then( ( r ) => res.json( r ) ) ) - // TODO: uncomment when we have a way to copy example themes - // await copyExampleThemes() + await copyExampleThemes() } export default createThemesModule diff --git a/apps/backend/src/features/themes/list.ts b/apps/backend/src/features/themes/list.ts index af7c9631..b9c1085d 100644 --- a/apps/backend/src/features/themes/list.ts +++ b/apps/backend/src/features/themes/list.ts @@ -1,9 +1,9 @@ import { readdir } from 'node:fs/promises' import { basename, extname } from 'node:path' -import { CUSTOM_OVERLAY_THEMES_FOLDER, CUSTOM_THEMES_FOLDER } from '@presenter/node' +import { USER_OVERLAY_THEMES_FOLDER, USER_PRESENTER_THEMES_FOLDER } from '@presenter/node' -import { FRONTEND_OVERLAY_THEMES_FOLDER, FRONTEND_THEMES_FOLDER } from '~/helpers/consts' +import { OVERLAY_THEMES_FOLDER, PRESENTER_THEMES_FOLDER } from '~/helpers/consts' const listCSSFiles = ( path: string ) => readdir( path ) .then( ( files ) => files.map( extname ).filter( ( extension ) => extension === '.css' ) ) @@ -14,11 +14,11 @@ const getThemeNames = ( folders: string[] ) => Promise .then( ( files ) => files.map( ( filename ) => basename( filename, '.css' ) ) ) export const getPresenterThemeNames = () => getThemeNames( [ - FRONTEND_THEMES_FOLDER, - CUSTOM_THEMES_FOLDER, + PRESENTER_THEMES_FOLDER, + USER_PRESENTER_THEMES_FOLDER, ] ) export const getOverlayThemeNames = () => getThemeNames( [ - FRONTEND_OVERLAY_THEMES_FOLDER, - CUSTOM_OVERLAY_THEMES_FOLDER, + OVERLAY_THEMES_FOLDER, + USER_OVERLAY_THEMES_FOLDER, ] ) diff --git a/apps/backend/src/features/themes/themes.ts b/apps/backend/src/features/themes/themes.ts index f0cf0725..c63a7c36 100644 --- a/apps/backend/src/features/themes/themes.ts +++ b/apps/backend/src/features/themes/themes.ts @@ -1,9 +1,11 @@ import { copyFile, readdir } from 'node:fs/promises' -import { CUSTOM_OVERLAY_THEMES_FOLDER, CUSTOM_THEMES_FOLDER } from '@presenter/node' +import { getLogger, USER_OVERLAY_THEMES_FOLDER, USER_PRESENTER_THEMES_FOLDER } from '@presenter/node' import { basename, extname, join } from 'path' -import { FRONTEND_OVERLAY_THEMES_FOLDER, FRONTEND_THEMES_FOLDER } from '~/helpers/consts' +import { OVERLAY_THEMES_FOLDER, PRESENTER_THEMES_FOLDER } from '~/helpers/consts' + +const logger = getLogger( 'themes' ) const listCSSFiles = ( path: string ) => readdir( path ) .then( ( files ) => files.filter( ( path ) => extname( path ) === '.css' ) ) @@ -14,18 +16,22 @@ const getThemeNames = ( folders: string[] ) => Promise .then( ( files ) => files.map( ( filename ) => basename( filename, '.css' ) ) ) export const getPresenterThemeNames = () => getThemeNames( [ - FRONTEND_THEMES_FOLDER, - CUSTOM_THEMES_FOLDER, -] ) + PRESENTER_THEMES_FOLDER, + USER_PRESENTER_THEMES_FOLDER, +] ).catch( ( e ) => { + logger.error( e, 'Unable to get presenter theme names', e ) +} ) export const getOverlayThemeNames = () => getThemeNames( [ - FRONTEND_OVERLAY_THEMES_FOLDER, - CUSTOM_OVERLAY_THEMES_FOLDER, -] ) + OVERLAY_THEMES_FOLDER, + USER_OVERLAY_THEMES_FOLDER, +] ).catch( ( e ) => { + logger.error( e, 'Unable to get overlay theme names' ) +} ) export const copyExampleThemes = () => Promise.all( [ - [ FRONTEND_OVERLAY_THEMES_FOLDER, CUSTOM_OVERLAY_THEMES_FOLDER ], - [ FRONTEND_THEMES_FOLDER, CUSTOM_THEMES_FOLDER ], + [ OVERLAY_THEMES_FOLDER, USER_OVERLAY_THEMES_FOLDER ], + [ PRESENTER_THEMES_FOLDER, USER_PRESENTER_THEMES_FOLDER ], ].map( ( [ src, dest ] ) => copyFile( join( src, 'Example.template' ), join( dest, 'Example.css' ), diff --git a/apps/backend/src/helpers/consts.ts b/apps/backend/src/helpers/consts.ts index 478cc662..9c322de2 100644 --- a/apps/backend/src/helpers/consts.ts +++ b/apps/backend/src/helpers/consts.ts @@ -1,17 +1,19 @@ import { join, resolve } from 'node:path' -import { isProduction } from '@presenter/node' +import { isProduction, resolveModule } from '@presenter/node' // Check every 5 minutes export const UPDATE_CHECK_INTERVAL = 5000 * 60 // App folder locations -export const APP_FOLDER = resolve( '@shabados/presenter' ) -export const FRONTEND_FOLDER = resolve( '@presenter/frontend' ) +export const APP_FOLDER = resolve( '../../../' ) +export const FRONTEND_FOLDER = resolveModule( '@presenter/frontend' ) export const FRONTEND_SRC_FOLDER = join( FRONTEND_FOLDER, 'src' ) export const FRONTEND_BUILD_FOLDER = join( FRONTEND_FOLDER, 'dist' ) -export const FRONTEND_OVERLAY_THEMES_FOLDER = join( FRONTEND_SRC_FOLDER, 'overlay', 'themes' ) -export const FRONTEND_THEMES_FOLDER = join( FRONTEND_SRC_FOLDER, 'Presenter', 'themes' ) + +export const OVERLAY_THEMES_FOLDER = resolveModule( '@presenter/themes/overlay' ) +export const PRESENTER_THEMES_FOLDER = resolveModule( '@presenter/themes/presenter' ) + export const DATABASE_FOLDER = resolve( '@shabados/database' ) // Max Search results to return in one go diff --git a/apps/backend/src/services/express.ts b/apps/backend/src/services/express.ts index c38e842c..28d6ed06 100644 --- a/apps/backend/src/services/express.ts +++ b/apps/backend/src/services/express.ts @@ -11,7 +11,12 @@ import ipc from '~/services/ipc' const log = getLogger( 'express' ) -const middleware = [ helmet(), compression(), bodyParser.json(), cors() ] +const middleware = [ + helmet( { crossOriginResourcePolicy: false } ), + compression(), + bodyParser.json(), + cors(), +] const createExpress = () => { const api = express() diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 6bd368e5..f4db177e 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -10,6 +10,7 @@ "lint": "eslint .", "types": "tsc --noEmit" }, + "exports": "./build", "dependencies": { "@emotion/react": "^11.13.0", "@emotion/styled": "^11.13.0", @@ -19,6 +20,7 @@ "@fortawesome/free-solid-svg-icons": "^6.6.0", "@fortawesome/react-fontawesome": "^0.2.2", "@mui/material": "^5.16.6", + "@presenter/themes": "*", "@sentry/browser": "^6.19.7", "classnames": "^2.3.1", "copy-to-clipboard": "^3.3.1", diff --git a/apps/frontend/src/components/ThemeLoader.tsx b/apps/frontend/src/components/ThemeLoader.tsx index 7b7628b7..310a5dfa 100644 --- a/apps/frontend/src/components/ThemeLoader.tsx +++ b/apps/frontend/src/components/ThemeLoader.tsx @@ -1,7 +1,7 @@ +import defaultTheme from '@presenter/themes/presenter/Day.css?url' import { useContext } from 'react' -import defaultTheme from '~/features/presenter/themes/Day.css?url' -import { THEMES_URL } from '~/helpers/consts' +import { PRESENTER_THEMES_URL } from '~/helpers/consts' import { StatusContext } from '~/helpers/contexts' type ThemeLoaderProps = { name: string } @@ -13,7 +13,7 @@ const ThemeLoader = ( { name = 'Day' }: ThemeLoaderProps ) => { ) } diff --git a/apps/frontend/src/helpers/consts.ts b/apps/frontend/src/helpers/consts.ts index 3023c3d2..4e5f5f7b 100644 --- a/apps/frontend/src/helpers/consts.ts +++ b/apps/frontend/src/helpers/consts.ts @@ -36,8 +36,8 @@ export const BOOKMARKS_URL = `${CONTROLLER_URL}/bookmarks` export const NAVIGATOR_URL = `${CONTROLLER_URL}/navigator` export const HISTORY_URL = `${CONTROLLER_URL}/history` export const HISTORY_DOWNLOAD_URL = `${BACKEND_URL}/history.csv` -export const THEMES_URL = `${BACKEND_URL}/presenter/themes` -export const OVERLAY_THEMES_URL = `${BACKEND_URL}/overlay/themes` +export const PRESENTER_THEMES_URL = `${BACKEND_URL}/themes/presenter` +export const OVERLAY_THEMES_URL = `${BACKEND_URL}/themes/overlay` export const SETTINGS_URL = '/settings' export const SETTINGS_DEVICE_URL = `${SETTINGS_URL}/device` diff --git a/package-lock.json b/package-lock.json index 5ea37259..0ef2b4a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "@presenter/contract": "*", "@presenter/node": "*", "@presenter/swiss-knife": "*", + "@presenter/themes": "*", "@shabados/database": "^4.8.7", "body-parser": "^1.20.0", "chalk": "^5.3.0", @@ -52,7 +53,7 @@ "express": "^4.18.1", "fp-ts": "^2.12.2", "gurmukhi-utils": "^3.2.1", - "helmet": "^5.0.2", + "helmet": "^7.1.0", "import-fresh": "^3.3.0", "lodash-es": "^4.17.21", "memoizee": "^0.4.15", @@ -161,6 +162,7 @@ "@fortawesome/free-solid-svg-icons": "^6.6.0", "@fortawesome/react-fontawesome": "^0.2.2", "@mui/material": "^5.16.6", + "@presenter/themes": "*", "@sentry/browser": "^6.19.7", "classnames": "^2.3.1", "copy-to-clipboard": "^3.3.1", @@ -10008,12 +10010,12 @@ } }, "node_modules/helmet": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/helmet/-/helmet-5.1.1.tgz", - "integrity": "sha512-/yX0oVZBggA9cLJh8aw3PPCfedBnbd7J2aowjzsaWwZh7/UFY0nccn/aHAggIgWUFfnykX8GKd3a1pSbrmlcVQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.1.0.tgz", + "integrity": "sha512-g+HZqgfbpXdCkme/Cd/mZkV0aV3BZZZSugecH03kl38m/Kmdx8jKjBikpDj2cr+Iynv4KpYEviojNdTJActJAg==", "license": "MIT", "engines": { - "node": ">=12.0.0" + "node": ">=16.0.0" } }, "node_modules/help-me": { diff --git a/packages/node/src/paths.ts b/packages/node/src/paths.ts index a44917e2..160ac649 100644 --- a/packages/node/src/paths.ts +++ b/packages/node/src/paths.ts @@ -1,11 +1,16 @@ import { chmod, mkdir } from 'node:fs/promises' -import { join } from 'node:path' +import { dirname, join } from 'node:path' +import { fileURLToPath } from 'node:url' import getAppDataPath from 'appdata-path' +export const resolveModule = ( name: string ) => dirname( fileURLToPath( + import.meta.resolve( name ) +) ) + export const DATA_FOLDER = join( getAppDataPath(), 'Shabad OS' ) -export const CUSTOM_THEMES_FOLDER = join( DATA_FOLDER, 'themes' ) -export const CUSTOM_OVERLAY_THEMES_FOLDER = join( DATA_FOLDER, 'overlay' ) +export const USER_PRESENTER_THEMES_FOLDER = join( DATA_FOLDER, 'themes', 'presenter' ) +export const USER_OVERLAY_THEMES_FOLDER = join( DATA_FOLDER, 'themes', 'overlay' ) export const HISTORY_FOLDER = join( DATA_FOLDER, 'history' ) export const LOG_FOLDER = join( DATA_FOLDER, 'logs' ) export const TMP_FOLDER = join( DATA_FOLDER, 'temp' ) @@ -13,8 +18,8 @@ export const UPDATE_TMP_FOLDER = join( TMP_FOLDER, '@shabados', 'database' ) const REQUIRED_FOLDERS = [ LOG_FOLDER, - CUSTOM_THEMES_FOLDER, - CUSTOM_OVERLAY_THEMES_FOLDER, + USER_PRESENTER_THEMES_FOLDER, + USER_OVERLAY_THEMES_FOLDER, HISTORY_FOLDER, TMP_FOLDER, ] diff --git a/apps/frontend/src/features/overlay/themes/Avani Conference.css b/packages/themes/overlay/Avani Conference.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Avani Conference.css rename to packages/themes/overlay/Avani Conference.css diff --git a/apps/frontend/src/features/overlay/themes/Avani Presentation.css b/packages/themes/overlay/Avani Presentation.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Avani Presentation.css rename to packages/themes/overlay/Avani Presentation.css diff --git a/apps/frontend/src/features/overlay/themes/Avani Top Banner.css b/packages/themes/overlay/Avani Top Banner.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Avani Top Banner.css rename to packages/themes/overlay/Avani Top Banner.css diff --git a/apps/frontend/src/features/overlay/themes/Cinematic Presentation.css b/packages/themes/overlay/Cinematic Presentation.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Cinematic Presentation.css rename to packages/themes/overlay/Cinematic Presentation.css diff --git a/apps/frontend/src/features/overlay/themes/Cinematic Subtitles.css b/packages/themes/overlay/Cinematic Subtitles.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Cinematic Subtitles.css rename to packages/themes/overlay/Cinematic Subtitles.css diff --git a/apps/frontend/src/features/overlay/themes/Cinematic Top Captions.css b/packages/themes/overlay/Cinematic Top Captions.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Cinematic Top Captions.css rename to packages/themes/overlay/Cinematic Top Captions.css diff --git a/apps/frontend/src/features/overlay/themes/Example.template b/packages/themes/overlay/Example.template similarity index 100% rename from apps/frontend/src/features/overlay/themes/Example.template rename to packages/themes/overlay/Example.template diff --git a/apps/frontend/src/features/overlay/themes/Floating Presentation.css b/packages/themes/overlay/Floating Presentation.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Floating Presentation.css rename to packages/themes/overlay/Floating Presentation.css diff --git a/apps/frontend/src/features/overlay/themes/Floating Subtitles.css b/packages/themes/overlay/Floating Subtitles.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Floating Subtitles.css rename to packages/themes/overlay/Floating Subtitles.css diff --git a/apps/frontend/src/features/overlay/themes/Floating Top Captions.css b/packages/themes/overlay/Floating Top Captions.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Floating Top Captions.css rename to packages/themes/overlay/Floating Top Captions.css diff --git a/apps/frontend/src/features/overlay/themes/Windowed Subtitles.css b/packages/themes/overlay/Windowed Subtitles.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Windowed Subtitles.css rename to packages/themes/overlay/Windowed Subtitles.css diff --git a/apps/frontend/src/features/overlay/themes/Windowed Top Captions.css b/packages/themes/overlay/Windowed Top Captions.css similarity index 100% rename from apps/frontend/src/features/overlay/themes/Windowed Top Captions.css rename to packages/themes/overlay/Windowed Top Captions.css diff --git a/apps/frontend/src/features/overlay/themes/images/logo-avani.png b/packages/themes/overlay/images/logo-avani.png similarity index 100% rename from apps/frontend/src/features/overlay/themes/images/logo-avani.png rename to packages/themes/overlay/images/logo-avani.png diff --git a/packages/themes/package.json b/packages/themes/package.json index df537d8c..13f17dc4 100644 --- a/packages/themes/package.json +++ b/packages/themes/package.json @@ -1,5 +1,12 @@ { "name": "@presenter/themes", "private": true, - "type": "module" + "type": "module", + "exports": { + ".": "./package.json", + "./overlay": "./overlay", + "./overlay/*": "./overlay/*", + "./presenter": "./presenter", + "./presenter/*": "./presenter/*" + } } diff --git a/apps/frontend/src/features/presenter/themes/Avani.css b/packages/themes/presenter/Avani.css similarity index 100% rename from apps/frontend/src/features/presenter/themes/Avani.css rename to packages/themes/presenter/Avani.css diff --git a/apps/frontend/src/features/presenter/themes/Blue on White.css b/packages/themes/presenter/Blue on White.css similarity index 100% rename from apps/frontend/src/features/presenter/themes/Blue on White.css rename to packages/themes/presenter/Blue on White.css diff --git a/apps/frontend/src/features/presenter/themes/Darbar Sahib.css b/packages/themes/presenter/Darbar Sahib.css similarity index 100% rename from apps/frontend/src/features/presenter/themes/Darbar Sahib.css rename to packages/themes/presenter/Darbar Sahib.css diff --git a/apps/frontend/src/features/presenter/themes/Day.css b/packages/themes/presenter/Day.css similarity index 100% rename from apps/frontend/src/features/presenter/themes/Day.css rename to packages/themes/presenter/Day.css diff --git a/apps/frontend/src/features/presenter/themes/Example.template b/packages/themes/presenter/Example.template similarity index 100% rename from apps/frontend/src/features/presenter/themes/Example.template rename to packages/themes/presenter/Example.template diff --git a/apps/frontend/src/features/presenter/themes/Night.css b/packages/themes/presenter/Night.css similarity index 100% rename from apps/frontend/src/features/presenter/themes/Night.css rename to packages/themes/presenter/Night.css diff --git a/apps/frontend/src/features/presenter/themes/Yellow on Blue.css b/packages/themes/presenter/Yellow on Blue.css similarity index 100% rename from apps/frontend/src/features/presenter/themes/Yellow on Blue.css rename to packages/themes/presenter/Yellow on Blue.css diff --git a/apps/frontend/src/features/presenter/themes/images/darbar-sahib.jpg b/packages/themes/presenter/images/darbar-sahib.jpg similarity index 100% rename from apps/frontend/src/features/presenter/themes/images/darbar-sahib.jpg rename to packages/themes/presenter/images/darbar-sahib.jpg diff --git a/apps/frontend/src/features/presenter/themes/images/logo-avani.png b/packages/themes/presenter/images/logo-avani.png similarity index 100% rename from apps/frontend/src/features/presenter/themes/images/logo-avani.png rename to packages/themes/presenter/images/logo-avani.png diff --git a/apps/frontend/src/features/presenter/themes/images/logo-black-5.png b/packages/themes/presenter/images/logo-black-5.png similarity index 100% rename from apps/frontend/src/features/presenter/themes/images/logo-black-5.png rename to packages/themes/presenter/images/logo-black-5.png diff --git a/apps/frontend/src/features/presenter/themes/images/logo-grayscale.png b/packages/themes/presenter/images/logo-grayscale.png similarity index 100% rename from apps/frontend/src/features/presenter/themes/images/logo-grayscale.png rename to packages/themes/presenter/images/logo-grayscale.png diff --git a/apps/frontend/src/features/presenter/themes/images/logo-pastel.png b/packages/themes/presenter/images/logo-pastel.png similarity index 100% rename from apps/frontend/src/features/presenter/themes/images/logo-pastel.png rename to packages/themes/presenter/images/logo-pastel.png diff --git a/apps/frontend/src/features/presenter/themes/images/logo-white-5.png b/packages/themes/presenter/images/logo-white-5.png similarity index 100% rename from apps/frontend/src/features/presenter/themes/images/logo-white-5.png rename to packages/themes/presenter/images/logo-white-5.png