From 680f7d887b2138d2338d59b6bfd151dcb5845840 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20K=C3=BCnzel?= <simonk@fsmpi.rwth-aachen.de>
Date: Sat, 10 May 2025 03:16:35 +0200
Subject: [PATCH] Simplify imports more

---
 README.md                                     |  1 +
 src/pages/404.tsx                             |  2 +-
 src/pages/_app.tsx                            | 16 ++++++------
 src/pages/courses.tsx                         | 19 ++++++--------
 src/pages/dynamic_course_listing.tsx          | 12 ++++-----
 src/pages/dynamic_player.tsx                  | 12 ++++-----
 src/pages/feedback.tsx                        |  8 +++---
 src/pages/index.tsx                           | 25 ++++++++-----------
 src/pages/internal/changelog.tsx              | 14 +++++------
 src/pages/internal/import.tsx                 | 10 ++++----
 src/pages/internal/jobs.tsx                   | 19 ++++++--------
 src/pages/internal/sorter_files.tsx           | 21 ++++++----------
 src/pages/internal/timetable.tsx              |  2 +-
 src/pages/internal/user.tsx                   | 12 ++++-----
 src/pages/licenses.tsx                        |  2 +-
 src/pages/search.tsx                          | 12 ++++-----
 src/videoag/api/Backend.tsx                   |  2 +-
 src/videoag/authentication/AuthStatus.tsx     |  4 +--
 .../authentication/ModeratorBarrier.tsx       |  2 +-
 src/videoag/authentication/UserField.tsx      | 12 ++++-----
 .../authentication/ViewPermissions.tsx        | 12 ++++-----
 src/videoag/course/Chapter.tsx                | 16 ++++++------
 src/videoag/course/CourseListing.tsx          | 10 ++++----
 src/videoag/course/DownloadManager.tsx        |  8 +++---
 src/videoag/course/Lecture.tsx                | 10 ++++----
 src/videoag/course/LiveLabel.tsx              |  4 +--
 src/videoag/course/Medium.tsx                 | 19 ++++++--------
 src/videoag/course/Player.tsx                 | 18 ++++++-------
 src/videoag/course/StatTracker.tsx            |  6 ++---
 src/videoag/error/ErrorDisplay.tsx            |  4 +--
 src/videoag/error/FallbackErrorBoundary.tsx   |  2 +-
 src/videoag/form/TypeEditor.tsx               |  6 ++---
 src/videoag/job/Job.tsx                       | 11 +++-----
 src/videoag/localization/LanguageProvider.tsx |  4 +--
 src/videoag/localization/i18n.tsx             |  2 +-
 src/videoag/miscellaneous/Util.tsx            |  2 +-
 .../object_management/FilteredData.tsx        |  8 +++---
 .../object_management/OMConfigComponent.tsx   | 12 ++++-----
 .../object_management/OMFieldEditor.tsx       |  4 +--
 .../object_management/ObjectEditor.tsx        |  8 +++---
 .../ViewPermissionsEditor.tsx                 |  8 +++---
 src/videoag/site/AnnouncementComponent.tsx    |  8 +++---
 src/videoag/site/DefaultLayout.tsx            | 18 ++++++-------
 .../miscellaneous => }/videojs-markers.js     |  0
 tsconfig.json                                 |  4 ++-
 45 files changed, 192 insertions(+), 219 deletions(-)
 rename src/{videoag/miscellaneous => }/videojs-markers.js (100%)

diff --git a/README.md b/README.md
index 0b2f5d7..a96fb13 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,7 @@ Stand: 14.04.25
   1. External imports
   2. Imports from other directories
     * With `@/`, no relative paths
+      * In some exceptional cases with `#src/`, `#basepath`
   3. Imports from own directory
     * With `./`
 * In each block type imports before other imports
diff --git a/src/pages/404.tsx b/src/pages/404.tsx
index 73386e6..3f53e5e 100644
--- a/src/pages/404.tsx
+++ b/src/pages/404.tsx
@@ -1,4 +1,4 @@
-import { Four04 } from "@/videoag/error";
+import { Four04 } from "@/error";
 
 export default function Four04Page() {
     return <Four04 />;
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index 2ecfa31..fe793a9 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -2,14 +2,14 @@ import type { AppProps } from "next/app";
 import { ToastContainer } from "react-toastify";
 import Head from "next/head";
 
-import { RealBackendProvider } from "@/videoag/api";
-import { AuthStatusProvider } from "@/videoag/authentication";
-import { showErrorToast } from "@/videoag/error";
-import { LanguageProvider } from "@/videoag/localization";
-import { ReloadBoundary, ThemeProvider, Title } from "@/videoag/miscellaneous";
-import { EditModeProvider } from "@/videoag/object_management";
-import { DefaultLayout } from "@/videoag/site";
-import "@/styles/globals.scss";
+import { RealBackendProvider } from "@/api";
+import { AuthStatusProvider } from "@/authentication";
+import { showErrorToast } from "@/error";
+import { LanguageProvider } from "@/localization";
+import { ReloadBoundary, ThemeProvider, Title } from "@/miscellaneous";
+import { EditModeProvider } from "@/object_management";
+import { DefaultLayout } from "@/site";
+import "#src/styles/globals.scss";
 
 export default function App({ Component, pageProps }: AppProps) {
     return (
diff --git a/src/pages/courses.tsx b/src/pages/courses.tsx
index 0908efe..cfc33fe 100644
--- a/src/pages/courses.tsx
+++ b/src/pages/courses.tsx
@@ -3,18 +3,13 @@ import Link from "next/link";
 import DropdownButton from "react-bootstrap/DropdownButton";
 import DropdownItem from "react-bootstrap/DropdownItem";
 
-import type { GetCoursesResponse, course } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { useAuthStatus } from "@/videoag/authentication";
-import { ErrorComponent, FallbackErrorBoundary } from "@/videoag/error";
-import { useLanguage } from "@/videoag/localization";
-import { ReloadBoundary, semesterToHuman, UpdateOverlay } from "@/videoag/miscellaneous";
-import {
-    useEditMode,
-    OMCreate,
-    OMEdit,
-    EmbeddedOMFieldComponent,
-} from "@/videoag/object_management";
+import type { GetCoursesResponse, course } from "@/api/types";
+import { useApi } from "@/api";
+import { useAuthStatus } from "@/authentication";
+import { ErrorComponent, FallbackErrorBoundary } from "@/error";
+import { useLanguage } from "@/localization";
+import { ReloadBoundary, semesterToHuman, UpdateOverlay } from "@/miscellaneous";
+import { useEditMode, OMCreate, OMEdit, EmbeddedOMFieldComponent } from "@/object_management";
 
 type GroupByTypes = "semester" | "full_name" | "organizer" | "topic";
 
diff --git a/src/pages/dynamic_course_listing.tsx b/src/pages/dynamic_course_listing.tsx
index bad62fd..9be4134 100644
--- a/src/pages/dynamic_course_listing.tsx
+++ b/src/pages/dynamic_course_listing.tsx
@@ -1,12 +1,12 @@
 import { useEffect, useRef, useState, useTransition } from "react";
 import { usePathname } from "next/navigation";
 
-import { GetCourseResponse } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { useAuthStatus } from "@/videoag/authentication";
-import { CourseListing } from "@/videoag/course";
-import { Four04, ErrorComponent, FallbackErrorBoundary } from "@/videoag/error";
-import { ReloadBoundary } from "@/videoag/miscellaneous";
+import { GetCourseResponse } from "@/api/types";
+import { useApi } from "@/api";
+import { useAuthStatus } from "@/authentication";
+import { CourseListing } from "@/course";
+import { Four04, ErrorComponent, FallbackErrorBoundary } from "@/error";
+import { ReloadBoundary } from "@/miscellaneous";
 
 function ActualRedirector() {
     const api = useApi();
diff --git a/src/pages/dynamic_player.tsx b/src/pages/dynamic_player.tsx
index 4c98c8a..6beb71c 100644
--- a/src/pages/dynamic_player.tsx
+++ b/src/pages/dynamic_player.tsx
@@ -1,12 +1,12 @@
 import { useEffect, useRef, useState, useTransition } from "react";
 import { usePathname } from "next/navigation";
 
-import { course, lecture } from "@/videoag/api/types";
-import { useApi, Backend } from "@/videoag/api";
-import { useAuthStatus } from "@/videoag/authentication";
-import { Player, EmbeddedPlayer } from "@/videoag/course";
-import { Four04, ErrorComponent, FallbackErrorBoundary } from "@/videoag/error";
-import { ReloadBoundary } from "@/videoag/miscellaneous";
+import { course, lecture } from "@/api/types";
+import { useApi, Backend } from "@/api";
+import { useAuthStatus } from "@/authentication";
+import { Player, EmbeddedPlayer } from "@/course";
+import { Four04, ErrorComponent, FallbackErrorBoundary } from "@/error";
+import { ReloadBoundary } from "@/miscellaneous";
 
 export interface PlayerData {
     course: course;
diff --git a/src/pages/feedback.tsx b/src/pages/feedback.tsx
index 7c72ade..c397e20 100644
--- a/src/pages/feedback.tsx
+++ b/src/pages/feedback.tsx
@@ -2,10 +2,10 @@ import type React from "react";
 import { useState } from "react";
 import Link from "next/link";
 
-import { useApi } from "@/videoag/api";
-import { showError } from "@/videoag/error";
-import { StringEditor, BooleanEditor } from "@/videoag/form";
-import { useLanguage } from "@/videoag/localization";
+import { useApi } from "@/api";
+import { showError } from "@/error";
+import { StringEditor, BooleanEditor } from "@/form";
+import { useLanguage } from "@/localization";
 
 export default function Feedback() {
     const api = useApi();
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index bfc6eed..f95c6e9 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -3,24 +3,19 @@ import { useEffect, useState } from "react";
 import { useSearchParams } from "next/navigation";
 import { useRouter } from "next/router";
 
-import type { GetHomepageResponse, featured, int } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { useAuthStatus } from "@/videoag/authentication";
-import { LectureCard, LectureLiveLabel } from "@/videoag/course";
-import {
-    ErrorComponent,
-    showError,
-    showWarningToast,
-    FallbackErrorBoundary,
-} from "@/videoag/error";
-import { useLanguage } from "@/videoag/localization/LanguageProvider";
+import type { GetHomepageResponse, featured, int } from "@/api/types";
+import { useApi } from "@/api";
+import { useAuthStatus } from "@/authentication";
+import { LectureCard, LectureLiveLabel } from "@/course";
+import { ErrorComponent, showError, showWarningToast, FallbackErrorBoundary } from "@/error";
+import { useLanguage } from "@/localization";
 import {
     datetimeToStringOnlyDate,
     datetimeToStringOnlyTime,
     ReloadBoundary,
     useReloadBoundary,
     useDebounceWithArgument,
-} from "@/videoag/miscellaneous";
+} from "@/miscellaneous";
 import {
     useEditMode,
     OMCreate,
@@ -28,9 +23,9 @@ import {
     OMEdit,
     OMHistory,
     EmbeddedOMFieldComponent,
-} from "@/videoag/object_management";
-import { Search } from "@/videoag/site";
-import { basePath } from "@/../basepath";
+} from "@/object_management";
+import { Search } from "@/site";
+import { basePath } from "#basepath";
 
 import { SearchResults } from "./search";
 
diff --git a/src/pages/internal/changelog.tsx b/src/pages/internal/changelog.tsx
index 68ae0f6..a22dd12 100644
--- a/src/pages/internal/changelog.tsx
+++ b/src/pages/internal/changelog.tsx
@@ -1,13 +1,13 @@
 import { useEffect, useState } from "react";
 import { DateTime } from "luxon";
 
-import type { changelog_entry, GetChangelogResponse, int, object_type } from "@/videoag/api/types";
-import { useApi, OBJECT_TYPES } from "@/videoag/api";
-import { ModeratorBarrier } from "@/videoag/authentication";
-import { showError, ErrorComponent } from "@/videoag/error";
-import { ChooserEditor, StringEditor, IntEditor } from "@/videoag/form";
-import { ReloadBoundary, useReloadBoundary } from "@/videoag/miscellaneous";
-import { useFilteredDataView, PagingNavigation, FilterInput } from "@/videoag/object_management";
+import type { changelog_entry, GetChangelogResponse, int, object_type } from "@/api/types";
+import { useApi, OBJECT_TYPES } from "@/api";
+import { ModeratorBarrier } from "@/authentication";
+import { showError, ErrorComponent } from "@/error";
+import { ChooserEditor, StringEditor, IntEditor } from "@/form";
+import { ReloadBoundary, useReloadBoundary } from "@/miscellaneous";
+import { useFilteredDataView, PagingNavigation, FilterInput } from "@/object_management";
 
 function ValToStr({ val }: { val: any }) {
     const [expand, setExpand] = useState(false);
diff --git a/src/pages/internal/import.tsx b/src/pages/internal/import.tsx
index ba7cf29..15f0f83 100644
--- a/src/pages/internal/import.tsx
+++ b/src/pages/internal/import.tsx
@@ -3,11 +3,11 @@ import Link from "next/link";
 import { useSearchParams } from "next/navigation";
 import { DateTime } from "luxon";
 
-import type { GetNewConfigurationResponse, course } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { ModeratorBarrier } from "@/videoag/authentication";
-import { showError, showErrorToast } from "@/videoag/error";
-import { ICalEvent, parseICal, ReloadBoundary, useReloadBoundary } from "@/videoag/miscellaneous";
+import type { GetNewConfigurationResponse, course } from "@/api/types";
+import { useApi } from "@/api";
+import { ModeratorBarrier } from "@/authentication";
+import { showError, showErrorToast } from "@/error";
+import { ICalEvent, parseICal, ReloadBoundary, useReloadBoundary } from "@/miscellaneous";
 
 function TerminBody({
     course,
diff --git a/src/pages/internal/jobs.tsx b/src/pages/internal/jobs.tsx
index aa31745..6b55ec1 100644
--- a/src/pages/internal/jobs.tsx
+++ b/src/pages/internal/jobs.tsx
@@ -1,15 +1,10 @@
-import type { int, job_state, GetJobsResponse } from "@/videoag/api/types";
-import { useApi, JOB_STATES } from "@/videoag/api";
-import { ModeratorBarrier } from "@/videoag/authentication";
-import { ErrorComponent } from "@/videoag/error";
-import { StringEditor, ChooserEditor } from "@/videoag/form";
-import {
-    ReloadBoundary,
-    ExpandableString,
-    datetimeToString,
-    Spinner,
-} from "@/videoag/miscellaneous";
-import { useFilteredDataView, PagingNavigation, FilterInput } from "@/videoag/object_management";
+import type { int, job_state, GetJobsResponse } from "@/api/types";
+import { useApi, JOB_STATES } from "@/api";
+import { ModeratorBarrier } from "@/authentication";
+import { ErrorComponent } from "@/error";
+import { StringEditor, ChooserEditor } from "@/form";
+import { ReloadBoundary, ExpandableString, datetimeToString, Spinner } from "@/miscellaneous";
+import { useFilteredDataView, PagingNavigation, FilterInput } from "@/object_management";
 
 function JobList({ jobsResp }: { jobsResp: GetJobsResponse }) {
     return (
diff --git a/src/pages/internal/sorter_files.tsx b/src/pages/internal/sorter_files.tsx
index 2b6044d..4628b46 100644
--- a/src/pages/internal/sorter_files.tsx
+++ b/src/pages/internal/sorter_files.tsx
@@ -1,24 +1,19 @@
 import { useState } from "react";
 import Link from "next/link";
 
-import type { int, GetSorterFilesResponse } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { ModeratorBarrier } from "@/videoag/authentication";
-import { showError, ErrorComponent } from "@/videoag/error";
-import { BooleanEditor } from "@/videoag/form";
-import { JobStatusCard } from "@/videoag/job";
-import {
-    ReloadBoundary,
-    ExpandableString,
-    datetimeToString,
-    showInfoToast,
-} from "@/videoag/miscellaneous";
+import type { int, GetSorterFilesResponse } from "@/api/types";
+import { useApi } from "@/api";
+import { ModeratorBarrier } from "@/authentication";
+import { showError, ErrorComponent } from "@/error";
+import { BooleanEditor } from "@/form";
+import { JobStatusCard } from "@/job";
+import { ReloadBoundary, ExpandableString, datetimeToString, showInfoToast } from "@/miscellaneous";
 import {
     useFilteredDataView,
     PagingNavigation,
     FilterInput,
     EmbeddedOMFieldComponent,
-} from "@/videoag/object_management";
+} from "@/object_management";
 
 function SorterFileList({ sorterFilesResp }: { sorterFilesResp: GetSorterFilesResponse }) {
     return (
diff --git a/src/pages/internal/timetable.tsx b/src/pages/internal/timetable.tsx
index 9473039..8d0611e 100644
--- a/src/pages/internal/timetable.tsx
+++ b/src/pages/internal/timetable.tsx
@@ -1,7 +1,7 @@
 import Link from "next/link";
 import { DateTime } from "luxon";
 
-import { ModeratorBarrier } from "@/videoag/authentication";
+import { ModeratorBarrier } from "@/authentication";
 
 interface Days {
     index: number;
diff --git a/src/pages/internal/user.tsx b/src/pages/internal/user.tsx
index 7ed93cf..dfa3987 100644
--- a/src/pages/internal/user.tsx
+++ b/src/pages/internal/user.tsx
@@ -1,12 +1,12 @@
 import type React from "react";
 import { useEffect, useState } from "react";
 
-import type { GetMySettingsResponse, settings_entry, settings_section } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { ModeratorBarrier } from "@/videoag/authentication";
-import { showError } from "@/videoag/error";
-import { useLanguage } from "@/videoag/localization";
-import { ReloadBoundary, useReloadBoundary } from "@/videoag/miscellaneous";
+import type { GetMySettingsResponse, settings_entry, settings_section } from "@/api/types";
+import { useApi } from "@/api";
+import { ModeratorBarrier } from "@/authentication";
+import { showError } from "@/error";
+import { useLanguage } from "@/localization";
+import { ReloadBoundary, useReloadBoundary } from "@/miscellaneous";
 
 function BoolEntry({ entry, disabled }: { entry: settings_entry; disabled: boolean }) {
     const reloadFunc = useReloadBoundary();
diff --git a/src/pages/licenses.tsx b/src/pages/licenses.tsx
index bca9ff3..5fc1824 100644
--- a/src/pages/licenses.tsx
+++ b/src/pages/licenses.tsx
@@ -1,4 +1,4 @@
-import licenseData from "@/data/licenses.json";
+import licenseData from "#src/data/licenses.json";
 
 type LicenseData = {
     [key: string]: {
diff --git a/src/pages/search.tsx b/src/pages/search.tsx
index 80e17ab..18e38bb 100644
--- a/src/pages/search.tsx
+++ b/src/pages/search.tsx
@@ -3,12 +3,12 @@ import { useEffect, useRef, useState } from "react";
 import { useSearchParams } from "next/navigation";
 import { useRouter } from "next/router";
 
-import type { SearchResponse, course, lecture } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { LectureListItem } from "@/videoag/course";
-import { ErrorComponent } from "@/videoag/error";
-import { useLanguage } from "@/videoag/localization";
-import { ReloadBoundary, useDebounce } from "@/videoag/miscellaneous";
+import type { SearchResponse, course, lecture } from "@/api/types";
+import { useApi } from "@/api";
+import { LectureListItem } from "@/course";
+import { ErrorComponent } from "@/error";
+import { useLanguage } from "@/localization";
+import { ReloadBoundary, useDebounce } from "@/miscellaneous";
 
 import { CourseItem } from "./courses";
 
diff --git a/src/videoag/api/Backend.tsx b/src/videoag/api/Backend.tsx
index 34a1d84..30bb559 100644
--- a/src/videoag/api/Backend.tsx
+++ b/src/videoag/api/Backend.tsx
@@ -1,4 +1,4 @@
-import { basePath } from "@/../basepath";
+import { basePath } from "#basepath";
 import { ApiError } from "./ApiError";
 
 import type {
diff --git a/src/videoag/authentication/AuthStatus.tsx b/src/videoag/authentication/AuthStatus.tsx
index ae29757..faefdc7 100644
--- a/src/videoag/authentication/AuthStatus.tsx
+++ b/src/videoag/authentication/AuthStatus.tsx
@@ -1,8 +1,8 @@
 import type React from "react";
 import { createContext, useContext, useState, useEffect, startTransition } from "react";
 
-import { int, user } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
+import { int, user } from "@/api/types";
+import { useApi } from "@/api";
 
 interface AuthStatusData {
     user: user | null;
diff --git a/src/videoag/authentication/ModeratorBarrier.tsx b/src/videoag/authentication/ModeratorBarrier.tsx
index a100085..dbd67e7 100644
--- a/src/videoag/authentication/ModeratorBarrier.tsx
+++ b/src/videoag/authentication/ModeratorBarrier.tsx
@@ -1,6 +1,6 @@
 import type React from "react";
 
-import { Four04 } from "@/videoag/error";
+import { Four04 } from "@/error";
 import { useAuthStatus } from "./AuthStatus";
 
 export default function ModeratorBarrier({ children }: { children: React.ReactNode }) {
diff --git a/src/videoag/authentication/UserField.tsx b/src/videoag/authentication/UserField.tsx
index 518839a..46ba5fd 100644
--- a/src/videoag/authentication/UserField.tsx
+++ b/src/videoag/authentication/UserField.tsx
@@ -3,12 +3,12 @@ import type React from "react";
 import { useState } from "react";
 import { Dropdown, Popover, OverlayTrigger } from "react-bootstrap";
 
-import { useApi, ApiError } from "@/videoag/api";
-import { useAuthStatus } from "@/videoag/authentication";
-import { showError } from "@/videoag/error";
-import { useLanguage } from "@/videoag/localization";
-import { TooltipButton } from "@/videoag/miscellaneous";
-import { useEditMode } from "@/videoag/object_management";
+import { useApi, ApiError } from "@/api";
+import { useAuthStatus } from "@/authentication";
+import { showError } from "@/error";
+import { useLanguage } from "@/localization";
+import { TooltipButton } from "@/miscellaneous";
+import { useEditMode } from "@/object_management";
 
 export default function UserField({ isUnavailable }: { isUnavailable: boolean }) {
     const api = useApi();
diff --git a/src/videoag/authentication/ViewPermissions.tsx b/src/videoag/authentication/ViewPermissions.tsx
index a666437..6f50d71 100644
--- a/src/videoag/authentication/ViewPermissions.tsx
+++ b/src/videoag/authentication/ViewPermissions.tsx
@@ -1,12 +1,12 @@
 import type React from "react";
 import { useEffect, useRef, useState } from "react";
 
-import { course, lecture } from "@/videoag/api/types";
-import { ApiError, useApi } from "@/videoag/api";
-import { useAuthStatus } from "@/videoag/authentication";
-import { showError, showErrorToast } from "@/videoag/error";
-import { useLanguage } from "@/videoag/localization";
-import { useReloadBoundary, StylizedText, useDebouncedCall } from "@/videoag/miscellaneous";
+import { course, lecture } from "@/api/types";
+import { ApiError, useApi } from "@/api";
+import { useAuthStatus } from "@/authentication";
+import { showError, showErrorToast } from "@/error";
+import { useLanguage } from "@/localization";
+import { useReloadBoundary, StylizedText, useDebouncedCall } from "@/miscellaneous";
 
 export function AuthenticationMethodIcons({
     authentication_methods,
diff --git a/src/videoag/course/Chapter.tsx b/src/videoag/course/Chapter.tsx
index 0b54c36..e145149 100644
--- a/src/videoag/course/Chapter.tsx
+++ b/src/videoag/course/Chapter.tsx
@@ -2,20 +2,20 @@ import type React from "react";
 import { useEffect, useRef, useState } from "react";
 import { Popover, OverlayTrigger } from "react-bootstrap";
 
-import { int, chapter } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { useAuthStatus } from "@/videoag/authentication";
-import { showError } from "@/videoag/error";
-import { StringEditor } from "@/videoag/form";
-import { useLanguage } from "@/videoag/localization";
-import { timestampToString, useReloadBoundary, showInfoToast } from "@/videoag/miscellaneous";
+import { int, chapter } from "@/api/types";
+import { useApi } from "@/api";
+import { useAuthStatus } from "@/authentication";
+import { showError } from "@/error";
+import { StringEditor } from "@/form";
+import { useLanguage } from "@/localization";
+import { timestampToString, useReloadBoundary, showInfoToast } from "@/miscellaneous";
 import {
     useEditMode,
     OMDelete,
     OMEdit,
     OMHistory,
     EmbeddedOMFieldComponent,
-} from "@/videoag/object_management";
+} from "@/object_management";
 
 export function Chapters({
     chapters,
diff --git a/src/videoag/course/CourseListing.tsx b/src/videoag/course/CourseListing.tsx
index a8247c8..aa3adbe 100644
--- a/src/videoag/course/CourseListing.tsx
+++ b/src/videoag/course/CourseListing.tsx
@@ -1,9 +1,9 @@
 import Link from "next/link";
 
-import type { GetCourseResponse } from "@/videoag/api/types";
-import { useAuthStatus, AuthenticationMethodIcons } from "@/videoag/authentication";
-import { useLanguage } from "@/videoag/localization";
-import { Title, UpdateOverlay } from "@/videoag/miscellaneous";
+import type { GetCourseResponse } from "@/api/types";
+import { useAuthStatus, AuthenticationMethodIcons } from "@/authentication";
+import { useLanguage } from "@/localization";
+import { Title, UpdateOverlay } from "@/miscellaneous";
 import {
     useEditMode,
     OMCreate,
@@ -11,7 +11,7 @@ import {
     OMEdit,
     OMHistory,
     EmbeddedOMFieldComponent,
-} from "@/videoag/object_management";
+} from "@/object_management";
 
 import { LectureListItem } from "./Lecture";
 import DownloadAllModal from "./DownloadManager";
diff --git a/src/videoag/course/DownloadManager.tsx b/src/videoag/course/DownloadManager.tsx
index 4df2b5b..3610582 100644
--- a/src/videoag/course/DownloadManager.tsx
+++ b/src/videoag/course/DownloadManager.tsx
@@ -3,10 +3,10 @@ import Modal from "react-bootstrap/Modal";
 import DropdownButton from "react-bootstrap/DropdownButton";
 import DropdownItem from "react-bootstrap/DropdownItem";
 
-import type { int, course, lecture } from "@/videoag/api/types";
-import { showWarningToast, showError } from "@/videoag/error";
-import { useLanguage } from "@/videoag/localization";
-import { StylizedText, filesizeToHuman } from "@/videoag/miscellaneous";
+import type { int, course, lecture } from "@/api/types";
+import { showWarningToast, showError } from "@/error";
+import { useLanguage } from "@/localization";
+import { StylizedText, filesizeToHuman } from "@/miscellaneous";
 
 import {
     getNamedPublishMedia,
diff --git a/src/videoag/course/Lecture.tsx b/src/videoag/course/Lecture.tsx
index 13125ee..e046d92 100644
--- a/src/videoag/course/Lecture.tsx
+++ b/src/videoag/course/Lecture.tsx
@@ -1,17 +1,17 @@
 import Link from "next/link";
 import { OverlayTrigger, Tooltip } from "react-bootstrap";
 
-import type { lecture, course } from "@/videoag/api/types";
-import { AuthenticationMethodIcons } from "@/videoag/authentication";
-import { datetimeToString, StylizedText } from "@/videoag/miscellaneous";
-import { useLanguage } from "@/videoag/localization";
+import type { lecture, course } from "@/api/types";
+import { AuthenticationMethodIcons } from "@/authentication";
+import { datetimeToString, StylizedText } from "@/miscellaneous";
+import { useLanguage } from "@/localization";
 import {
     useEditMode,
     OMDelete,
     OMEdit,
     OMHistory,
     EmbeddedOMFieldComponent,
-} from "@/videoag/object_management";
+} from "@/object_management";
 
 import {
     PublishMediumDownloadButton,
diff --git a/src/videoag/course/LiveLabel.tsx b/src/videoag/course/LiveLabel.tsx
index 9965e80..e012f30 100644
--- a/src/videoag/course/LiveLabel.tsx
+++ b/src/videoag/course/LiveLabel.tsx
@@ -1,7 +1,7 @@
 import { DateTime } from "luxon";
 
-import { lecture } from "@/videoag/api/types";
-import { useLanguage } from "@/videoag/localization";
+import { lecture } from "@/api/types";
+import { useLanguage } from "@/localization";
 
 export function LiveLabel({ nowlive }: { nowlive: boolean }) {
     const { language } = useLanguage();
diff --git a/src/videoag/course/Medium.tsx b/src/videoag/course/Medium.tsx
index 2082c43..76fa18c 100644
--- a/src/videoag/course/Medium.tsx
+++ b/src/videoag/course/Medium.tsx
@@ -1,16 +1,11 @@
 import { useEffect, useState } from "react";
 import { Dropdown, Modal } from "react-bootstrap";
 
-import {
-    int,
-    lecture,
-    publish_medium,
-    GetLectureMediaProcessOverviewResponse,
-} from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { showError, ErrorComponent } from "@/videoag/error";
-import { JobStatusCard } from "@/videoag/job";
-import { useLanguage } from "@/videoag/localization";
+import { int, lecture, publish_medium, GetLectureMediaProcessOverviewResponse } from "@/api/types";
+import { useApi } from "@/api";
+import { showError, ErrorComponent } from "@/error";
+import { JobStatusCard } from "@/job";
+import { useLanguage } from "@/localization";
 import {
     Spinner,
     ReloadBoundary,
@@ -22,8 +17,8 @@ import {
     filesizeToHuman,
     timestampToString,
     datetimeToString,
-} from "@/videoag/miscellaneous";
-import { useEditMode, OMDelete, EmbeddedOMFieldComponent } from "@/videoag/object_management";
+} from "@/miscellaneous";
+import { useEditMode, OMDelete, EmbeddedOMFieldComponent } from "@/object_management";
 
 export function getMediumQualityName(medium: publish_medium): string | undefined {
     switch (medium.medium_metadata.type) {
diff --git a/src/videoag/course/Player.tsx b/src/videoag/course/Player.tsx
index ac60277..c230610 100644
--- a/src/videoag/course/Player.tsx
+++ b/src/videoag/course/Player.tsx
@@ -8,21 +8,21 @@ import Popover from "react-bootstrap/Popover";
 import "video.js/dist/video-js.min.css";
 import VideoJsPlayerType from "video.js/dist/types/player";
 import "@silvermine/videojs-quality-selector/dist/css/quality-selector.css";
-import VideoJsMarkers from "@/videoag/miscellaneous/videojs-markers";
+import VideoJsMarkers from "#src/videojs-markers";
 
-import type { course, chapter, publish_medium, lecture } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { ViewPermissionAuthorization } from "@/videoag/authentication";
-import { useLanguage } from "@/videoag/localization";
-import { Title, UpdateOverlay, showInfoToast, parseApiDatetime } from "@/videoag/miscellaneous";
+import type { course, chapter, publish_medium, lecture } from "@/api/types";
+import { useApi } from "@/api";
+import { ViewPermissionAuthorization } from "@/authentication";
+import { useLanguage } from "@/localization";
+import { Title, UpdateOverlay, showInfoToast, parseApiDatetime } from "@/miscellaneous";
 import {
     useEditMode,
     OMDelete,
     OMEdit,
     OMHistory,
     EmbeddedOMFieldComponent,
-} from "@/videoag/object_management";
-import { basePath } from "@/../basepath";
+} from "@/object_management";
+import { basePath } from "#basepath";
 
 import { LectureCard, urlForLecture, getLectureThumbnailUrlNoPlaceholder } from "./Lecture";
 import {
@@ -33,7 +33,7 @@ import {
 import { Chapters, AddChapterButton } from "./Chapter";
 import { StatTracker } from "./StatTracker";
 
-import { PlayerData } from "@/pages/dynamic_player";
+import { PlayerData } from "#src/pages/dynamic_player";
 
 function initPlayer(
     player: VideoJsPlayerType,
diff --git a/src/videoag/course/StatTracker.tsx b/src/videoag/course/StatTracker.tsx
index 073c728..e747f8a 100644
--- a/src/videoag/course/StatTracker.tsx
+++ b/src/videoag/course/StatTracker.tsx
@@ -1,9 +1,9 @@
 import VideoJsPlayerType from "video.js/dist/types/player";
 import { DateTime } from "luxon";
 
-import type { int, datetime } from "@/videoag/api/types";
-import { Backend, ApiError } from "@/videoag/api";
-import { formatApiDatetime } from "@/videoag/miscellaneous";
+import type { int, datetime } from "@/api/types";
+import { Backend, ApiError } from "@/api";
+import { formatApiDatetime } from "@/miscellaneous";
 
 const MAX_SEGMENT_REALTIME_DURATION_SEC = 20;
 const MIN_SEGMENT_DURATION_SEC = 1.2;
diff --git a/src/videoag/error/ErrorDisplay.tsx b/src/videoag/error/ErrorDisplay.tsx
index 5abf82a..ff84327 100644
--- a/src/videoag/error/ErrorDisplay.tsx
+++ b/src/videoag/error/ErrorDisplay.tsx
@@ -3,8 +3,8 @@ import { toast, Bounce } from "react-toastify";
 import { useRouter } from "next/router";
 import Link from "next/link";
 
-import { ApiError } from "@/videoag/api";
-import { useReloadBoundary } from "@/videoag/miscellaneous";
+import { ApiError } from "@/api";
+import { useReloadBoundary } from "@/miscellaneous";
 
 export function showError(error: Error, prefix_message = "Ein Fehler ist aufgetreten") {
     if (error instanceof ApiError) {
diff --git a/src/videoag/error/FallbackErrorBoundary.tsx b/src/videoag/error/FallbackErrorBoundary.tsx
index 207a59b..4126430 100644
--- a/src/videoag/error/FallbackErrorBoundary.tsx
+++ b/src/videoag/error/FallbackErrorBoundary.tsx
@@ -1,7 +1,7 @@
 import React from "react";
 import { ErrorInfo } from "react";
 
-import { NestedReloadBoundary } from "@/videoag/miscellaneous";
+import { NestedReloadBoundary } from "@/miscellaneous";
 
 export class FallbackErrorBoundary extends React.Component<any, { error?: any }> {
     constructor(props: { fallback: (e: any) => React.ReactNode; children: React.ReactNode }) {
diff --git a/src/videoag/form/TypeEditor.tsx b/src/videoag/form/TypeEditor.tsx
index a9a0498..442fe5e 100644
--- a/src/videoag/form/TypeEditor.tsx
+++ b/src/videoag/form/TypeEditor.tsx
@@ -1,9 +1,9 @@
 import React, { useEffect, useRef, useState } from "react";
 import { DateTime } from "luxon";
 
-import type { int } from "@/videoag/api/types";
-import { useLanguage } from "@/videoag/localization";
-import { deepEquals, parseApiDatetime, formatApiDatetime } from "@/videoag/miscellaneous";
+import type { int } from "@/api/types";
+import { useLanguage } from "@/localization";
+import { deepEquals, parseApiDatetime, formatApiDatetime } from "@/miscellaneous";
 
 export type EditorArgs = {
     value?: any;
diff --git a/src/videoag/job/Job.tsx b/src/videoag/job/Job.tsx
index 480d4c1..20de7a6 100644
--- a/src/videoag/job/Job.tsx
+++ b/src/videoag/job/Job.tsx
@@ -1,13 +1,8 @@
 import { useState, useEffect, useRef } from "react";
 
-import type { int, job, job_state } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import {
-    datetimeToString,
-    Spinner,
-    useDebouncedCall,
-    useReloadBoundary,
-} from "@/videoag/miscellaneous";
+import type { int, job, job_state } from "@/api/types";
+import { useApi } from "@/api";
+import { datetimeToString, Spinner, useDebouncedCall, useReloadBoundary } from "@/miscellaneous";
 
 export function JobStatusCard({ jobId }: { jobId: int }) {
     const api = useApi();
diff --git a/src/videoag/localization/LanguageProvider.tsx b/src/videoag/localization/LanguageProvider.tsx
index 4624c1c..3ed56d4 100644
--- a/src/videoag/localization/LanguageProvider.tsx
+++ b/src/videoag/localization/LanguageProvider.tsx
@@ -1,8 +1,8 @@
 import type React from "react";
 import { createContext, useContext, useState, useEffect } from "react";
 
-import { useApi } from "@/videoag/api";
-import { storageGetOrDefault, storageSet } from "@/videoag/miscellaneous";
+import { useApi } from "@/api";
+import { storageGetOrDefault, storageSet } from "@/miscellaneous";
 
 import { Language } from "./i18n";
 
diff --git a/src/videoag/localization/i18n.tsx b/src/videoag/localization/i18n.tsx
index 06b764b..2ddb3f9 100644
--- a/src/videoag/localization/i18n.tsx
+++ b/src/videoag/localization/i18n.tsx
@@ -1,6 +1,6 @@
 import type React from "react";
 
-import { StylizedText } from "@/videoag/miscellaneous";
+import { StylizedText } from "@/miscellaneous";
 
 export class Language {
     constructor(
diff --git a/src/videoag/miscellaneous/Util.tsx b/src/videoag/miscellaneous/Util.tsx
index bfb869e..1113dab 100644
--- a/src/videoag/miscellaneous/Util.tsx
+++ b/src/videoag/miscellaneous/Util.tsx
@@ -3,7 +3,7 @@ import { OverlayTrigger, Tooltip } from "react-bootstrap";
 import { toast, Bounce } from "react-toastify";
 import { DateTime } from "luxon";
 
-import type { datetime } from "@/videoag/api/types";
+import type { datetime } from "@/api/types";
 
 export function zeropad(num: number, places: number) {
     var zero = places - num.toString().length + 1;
diff --git a/src/videoag/object_management/FilteredData.tsx b/src/videoag/object_management/FilteredData.tsx
index 290565b..b90c07c 100644
--- a/src/videoag/object_management/FilteredData.tsx
+++ b/src/videoag/object_management/FilteredData.tsx
@@ -1,11 +1,11 @@
-import { useApi } from "@/videoag/api/ApiProvider";
 import React, { useEffect, useState, useRef, ReactNode } from "react";
 import { useSearchParams } from "next/navigation";
 import { useRouter } from "next/router";
 
-import type { int } from "@/videoag/api/types";
-import { ChooserEditor } from "@/videoag/form";
-import { useDebounceWithArgument, mapMap } from "@/videoag/miscellaneous";
+import type { int } from "@/api/types";
+import { useApi } from "@/api";
+import { ChooserEditor } from "@/form";
+import { useDebounceWithArgument, mapMap } from "@/miscellaneous";
 
 // TODO sometimes search params are overridden with defaults on page load (e.g. sorter files). Redo this and use a
 // boundary instead of passing filters through the parent
diff --git a/src/videoag/object_management/OMConfigComponent.tsx b/src/videoag/object_management/OMConfigComponent.tsx
index 178c4ec..930a011 100644
--- a/src/videoag/object_management/OMConfigComponent.tsx
+++ b/src/videoag/object_management/OMConfigComponent.tsx
@@ -8,10 +8,10 @@ import type {
     field_description,
     field_value,
     int,
-} from "@/videoag/api/types";
-import { useApi, ApiError } from "@/videoag/api";
-import { showError, showErrorToast } from "@/videoag/error";
-import { useLanguage } from "@/videoag/localization";
+} from "@/api/types";
+import { useApi, ApiError } from "@/api";
+import { showError, showErrorToast } from "@/error";
+import { useLanguage } from "@/localization";
 import {
     useReloadBoundary,
     useDebouncedProcessing,
@@ -21,8 +21,8 @@ import {
     deepEquals,
     TooltipButton,
     StopNavigation,
-} from "@/videoag/miscellaneous";
-import { basePath } from "@/../basepath";
+} from "@/miscellaneous";
+import { basePath } from "#basepath";
 
 import { LockEditMode, useEditMode } from "./EditModeProvider";
 import { OMFieldEditor } from "./OMFieldEditor";
diff --git a/src/videoag/object_management/OMFieldEditor.tsx b/src/videoag/object_management/OMFieldEditor.tsx
index f165bd9..1ed1477 100644
--- a/src/videoag/object_management/OMFieldEditor.tsx
+++ b/src/videoag/object_management/OMFieldEditor.tsx
@@ -1,6 +1,6 @@
 import React from "react";
 
-import type { field_description } from "@/videoag/api/types";
+import type { field_description } from "@/api/types";
 import {
     EditorArgs,
     StringEditor,
@@ -9,7 +9,7 @@ import {
     DatetimeEditor,
     ChooserEditor,
     JsonEditor,
-} from "@/videoag/form";
+} from "@/form";
 
 import { UserIdListEditor } from "./ObjectEditor";
 import ViewPermissionsEditor from "./ViewPermissionsEditor";
diff --git a/src/videoag/object_management/ObjectEditor.tsx b/src/videoag/object_management/ObjectEditor.tsx
index 43ed67b..8bcc233 100644
--- a/src/videoag/object_management/ObjectEditor.tsx
+++ b/src/videoag/object_management/ObjectEditor.tsx
@@ -1,10 +1,10 @@
 import React, { useEffect, useRef, useState } from "react";
 import Dropdown from "react-bootstrap/Dropdown";
 
-import type { GetUsersResponse, user, int } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { EditorArgs } from "@/videoag/form";
-import { showError } from "@/videoag/error";
+import type { GetUsersResponse, user, int } from "@/api/types";
+import { useApi } from "@/api";
+import { EditorArgs } from "@/form";
+import { showError } from "@/error";
 
 export function UserIdListEditor({
     value,
diff --git a/src/videoag/object_management/ViewPermissionsEditor.tsx b/src/videoag/object_management/ViewPermissionsEditor.tsx
index 0085ca7..e484c86 100644
--- a/src/videoag/object_management/ViewPermissionsEditor.tsx
+++ b/src/videoag/object_management/ViewPermissionsEditor.tsx
@@ -1,9 +1,9 @@
 import React, { useEffect, useRef, useState } from "react";
 
-import type { view_permissions, int } from "@/videoag/api/types";
-import { EditorArgs } from "@/videoag/form";
-import { useLanguage } from "@/videoag/localization";
-import { deepEquals } from "@/videoag/miscellaneous";
+import type { view_permissions, int } from "@/api/types";
+import { EditorArgs } from "@/form";
+import { useLanguage } from "@/localization";
+import { deepEquals } from "@/miscellaneous";
 
 function createListEditor<V>(
     disabled: boolean,
diff --git a/src/videoag/site/AnnouncementComponent.tsx b/src/videoag/site/AnnouncementComponent.tsx
index 0ee5f4b..48f7300 100644
--- a/src/videoag/site/AnnouncementComponent.tsx
+++ b/src/videoag/site/AnnouncementComponent.tsx
@@ -1,15 +1,15 @@
 import { useRouter } from "next/router";
 
-import type { announcement } from "@/videoag/api/types";
-import { useLanguage } from "@/videoag/localization/";
-import { useLocalStorageState, StylizedText, TooltipButton } from "@/videoag/miscellaneous";
+import type { announcement } from "@/api/types";
+import { useLanguage } from "@/localization";
+import { useLocalStorageState, StylizedText, TooltipButton } from "@/miscellaneous";
 import {
     useEditMode,
     OMCreate,
     OMDelete,
     OMEdit,
     EmbeddedOMFieldComponent,
-} from "@/videoag/object_management";
+} from "@/object_management";
 
 // TODO mark non-visible (also check time) announcements for mods
 
diff --git a/src/videoag/site/DefaultLayout.tsx b/src/videoag/site/DefaultLayout.tsx
index 2f01340..1fc7fe5 100644
--- a/src/videoag/site/DefaultLayout.tsx
+++ b/src/videoag/site/DefaultLayout.tsx
@@ -6,15 +6,15 @@ import { DropdownButton } from "react-bootstrap";
 import Collapse from "react-bootstrap/Collapse";
 import Dropdown from "react-bootstrap/Dropdown";
 
-import type { GetStatusResponse } from "@/videoag/api/types";
-import { useApi } from "@/videoag/api";
-import { useAuthStatus, UserField } from "@/videoag/authentication";
-import { showErrorToast, ErrorComponent, FallbackErrorBoundary } from "@/videoag/error";
-import { useLanguage } from "@/videoag/localization";
-import { ReloadBoundary, StylizedText, useTheme } from "@/videoag/miscellaneous";
-import { useEditMode } from "@/videoag/object_management";
-import { AnnouncementComponent } from "@/videoag/site";
-import { basePath } from "@/../basepath";
+import type { GetStatusResponse } from "@/api/types";
+import { useApi } from "@/api";
+import { useAuthStatus, UserField } from "@/authentication";
+import { showErrorToast, ErrorComponent, FallbackErrorBoundary } from "@/error";
+import { useLanguage } from "@/localization";
+import { ReloadBoundary, StylizedText, useTheme } from "@/miscellaneous";
+import { useEditMode } from "@/object_management";
+import { AnnouncementComponent } from "@/site";
+import { basePath } from "#basepath";
 
 function NavBarIcon({
     children,
diff --git a/src/videoag/miscellaneous/videojs-markers.js b/src/videojs-markers.js
similarity index 100%
rename from src/videoag/miscellaneous/videojs-markers.js
rename to src/videojs-markers.js
diff --git a/tsconfig.json b/tsconfig.json
index 3ca6a9a..86c4bd0 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -14,7 +14,9 @@
     "jsx": "preserve",
     "incremental": true,
     "paths": {
-      "@/*": ["./src/*"]
+      "#src/*": ["./src/*"],
+      "#basepath": ["./basepath.js"],
+      "@/*": ["./src/videoag/*"]
     }
   },
   "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
-- 
GitLab