diff --git a/README.md b/README.md
index 0b2f5d740a187eb003ea3fd47696537de6e37b80..a96fb136e218688d5137cee930d891ebef921953 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 73386e65f66884649b28e2acf047eaadfba5a9e2..3f53e5e7e7ad5c1b1460e39342279fdeb5019f3e 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 2ecfa31bbbb6a0f2dd533b411af4d37921eec0d1..fe793a9694137db4d9c607aa74ee6bd9aa4d993e 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 0908efedfe8965fd8227d27e807eec75a353e03b..cfc33fef79e9a1ec016081b91de05d7026f58c06 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 bad62fd2cc74c2612ad11bdb56fb5f4df33951ed..9be41348046accc4a3dbb677cbf998d8896807de 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 4c98c8a0efbc3a18930c5ca9b855b6a0059d4980..6beb71cd33889ca32636f403db6b68ea626a4880 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 7c72adee2b503aad2087d196a163cc9a8fab76f4..c397e202d45397c6d64f7d3550029c0f29345f4c 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 bfc6eed86c5f3a28143baebbe6baae9bec8b108d..f95c6e9fbd8e9e84ae36423dcb17a011405ad60d 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 68ae0f68d05d4cdb372feb050b8b34cf4e623c2d..a22dd121958eb8224e5302771c3cbe2e3b7d7120 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 ba7cf29ad35e9fe5fa6ad2e9b2c907ecdd77c6e1..15f0f836c8db7db143123dbbb9149d4d5efb0c05 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 aa317459a68a21c5c64f8258fa5516e58e20f904..6b55ec14c8a5fb68ca62573ef705dac848c7d0b8 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 2b6044d7ba100b0366204e6d132c01058862f5fc..4628b4655431b36b3f19e4a2deaf611013e97d95 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 947303976f8d8b2951c5f618629818f90e3e9987..8d0611eb40c74e114112d893ea3fb32ef3ee46ff 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 7ed93cf825e59ee7bc7d7a2ee2092e11daf4c8be..dfa3987ee0b95dddd09a0725af7a6036ddf3280f 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 bca9ff3ce87941cf4660b6781ba7a74f1dfe6f53..5fc18246213dfdd44538d5bd7b9017347677bc28 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 80e17ab69650f9fa4c9013811f40568de4a7f304..18e38bb016d7d9679c17f583f7acf094287c10c5 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 34a1d843fc5e65c476a2404bd02f527cce6b8808..30bb55976a95e074736b6f5104fb6156a4c2d43f 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 ae297576f4778759e10723b37a4e2dbbacf33a08..faefdc7f5fdb286ff8681391b4c0cf59827b1d01 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 a1000851e0e2f609b019ccd965911751bc5ca8ba..dbd67e7776442571067524a38a8d6f3e374e2d9d 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 518839ac5b3d02b8a1b7bd64243b18e7f11fde04..46ba5fdb0a59f0ee903efadd2b2f776b06bc32aa 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 a6664371c8db930b87bd5ac734158124b73bb5c8..6f50d711b34aac3884f1f0e2062af93f1f4f5dab 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 0b54c365c48b4678679d113d3ce2d2b917d7d482..e145149908ef9e11bef8ec52171c6352df0fdb74 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 a8247c88eee1b0436635acd0b5df0ad326751ef1..aa3adbe529d493a9883f19a41447f507ced160d5 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 4df2b5bf15c8c5331b23ff8774f3c095a425a859..3610582b3f53443bb9400f011602adb0928c7efe 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 13125ee083e5c3f50a466ad44ab2d8c86bf8289e..e046d926b6b74477bc1a41fb56fd11ed6d2f2767 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 9965e808f80036220edd83c9f546de7d879118ea..e012f307afa1e4b1d6dcc1eeb51f0e60792979b6 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 2082c43e218ac6d3a4e9d2d6c4687bb6accb3bfe..76fa18c23c4a87b86b2a9002db8d51f3d371421e 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 ac6027716a441a282fec70258d85e5b9b4dffe2d..c2306106e85560dc3516cdebc035ac7acd0473fa 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 073c7284d9e50dfabd7f1eb555481bbb43231c25..e747f8af5325338bba3670516a6bdb209c083140 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 5abf82afd7ac5833daa71e6b35965d3f8944740a..ff84327956aa3a930974a9923db474544b301d63 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 207a59b66b49e691b0bb1b67a28f6c7bcb8f61a7..41264307613078c1f6f5f50c8d31ed2ca0116db0 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 a9a049852c391b130f40b98ce9818c9ca826487b..442fe5e8a829447e7befad5ad2860e8bb92f9d7c 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 480d4c1a949af168473984d1851124c66b6884b4..20de7a6711ca218ada56d62982230f14ba0c424c 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 4624c1cb0d5bce6960e2dddc6d3ba692a3e0df8e..3ed56d4f9ad1ff6aa8beb1d2594add83acdcc6f7 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 06b764bc1e115bc69575040711ddc77ced0eab33..2ddb3f9708d640e884bc41ea3fa4ace95de0d122 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 bfb869ed49138bedad6112edeac4271762e62456..1113dabe9fbd78badddf950d21d6561c6a9fca69 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 290565b72681e2fc7c7af5d9e697e06c1c83fab0..b90c07cba718b080b6c338f847b05ed4f75af411 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 178c4ec2b18625be025ad3e360553a84d993aa81..930a0119c92667107a39ab0816c30c4f9d7f8072 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 f165bd964c47888c9348af8f7489f5eacb2f089c..1ed147796963f2e072c7dfb21cbc7d15366e4aa5 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 43ed67b9cf90223966bbb4e513405a8303794fd2..8bcc233fa1c01b1829a85ebbeea60d2ade4d1827 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 0085ca7d4807fd2f97740e08bd98bc4655eb07df..e484c8608b7bff489f47f99822afb89c24bc801a 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 0ee5f4b61ccafddaeb14ffbc2d0a185775aafb9c..48f7300d9a7441f01acd58b1c33be116b9afcd75 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 2f013406dab2aef463d46007b2d6c13caaa244a6..1fc7fe5f1da377668cbecf5e2604b32ff97623bf 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 3ca6a9a50cbba3f7aa913e3d3ff1049e19da034c..86c4bd02b3a365a2a9af46dde361d617cbbd8371 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"],