diff --git a/web/src/ui/MainScreen.tsx b/web/src/ui/MainScreen.tsx
index 029d20e..eb965a0 100644
--- a/web/src/ui/MainScreen.tsx
+++ b/web/src/ui/MainScreen.tsx
@@ -17,10 +17,10 @@ import { use, useCallback, useLayoutEffect, useMemo, useState } from "react"
import type { RoomID } from "@/api/types"
import ClientContext from "./ClientContext.ts"
import MainScreenContext, { MainScreenContextFields } from "./MainScreenContext.ts"
-import RoomView from "./RoomView.tsx"
import RightPanel, { RightPanelProps } from "./rightpanel/RightPanel.tsx"
import RoomList from "./roomlist/RoomList.tsx"
-import { useResizeHandle } from "./useResizeHandle.tsx"
+import RoomView from "./roomview/RoomView.tsx"
+import { useResizeHandle } from "./util/useResizeHandle.tsx"
import "./MainScreen.css"
const MainScreen = () => {
diff --git a/web/src/ui/composer/MessageComposer.tsx b/web/src/ui/composer/MessageComposer.tsx
index fe258de..10f60e0 100644
--- a/web/src/ui/composer/MessageComposer.tsx
+++ b/web/src/ui/composer/MessageComposer.tsx
@@ -31,7 +31,7 @@ import useEvent from "@/util/useEvent.ts"
import ClientContext from "../ClientContext.ts"
import EmojiPicker from "../emojipicker/EmojiPicker.tsx"
import { ModalContext } from "../modal/Modal.tsx"
-import { useRoomContext } from "../roomcontext.ts"
+import { useRoomContext } from "../roomview/roomcontext.ts"
import { ReplyBody } from "../timeline/ReplyBody.tsx"
import { useMediaContent } from "../timeline/content/useMediaContent.tsx"
import type { AutocompleteQuery } from "./Autocompleter.tsx"
diff --git a/web/src/ui/rightpanel/PinnedMessages.tsx b/web/src/ui/rightpanel/PinnedMessages.tsx
index 89f286c..42a52ea 100644
--- a/web/src/ui/rightpanel/PinnedMessages.tsx
+++ b/web/src/ui/rightpanel/PinnedMessages.tsx
@@ -18,7 +18,7 @@ import { RoomStateStore, useRoomEvent, useRoomState } from "@/api/statestore"
import { EventID, PinnedEventsContent } from "@/api/types"
import reverseMap from "@/util/reversemap.ts"
import ClientContext from "../ClientContext.ts"
-import { RoomContext } from "../roomcontext.ts"
+import { RoomContext } from "../roomview/roomcontext.ts"
import TimelineEvent from "../timeline/TimelineEvent.tsx"
interface PinnedMessageProps {
diff --git a/web/src/ui/RoomView.css b/web/src/ui/roomview/RoomView.css
similarity index 100%
rename from web/src/ui/RoomView.css
rename to web/src/ui/roomview/RoomView.css
diff --git a/web/src/ui/RoomView.tsx b/web/src/ui/roomview/RoomView.tsx
similarity index 90%
rename from web/src/ui/RoomView.tsx
rename to web/src/ui/roomview/RoomView.tsx
index 16567c2..d5e0cb7 100644
--- a/web/src/ui/RoomView.tsx
+++ b/web/src/ui/roomview/RoomView.tsx
@@ -15,11 +15,11 @@
// along with this program. If not, see .
import { JSX, useRef } from "react"
import { RoomStateStore } from "@/api/statestore"
+import MessageComposer from "../composer/MessageComposer.tsx"
+import RightPanel, { RightPanelProps } from "../rightpanel/RightPanel.tsx"
+import TimelineView from "../timeline/TimelineView.tsx"
import RoomViewHeader from "./RoomViewHeader.tsx"
-import MessageComposer from "./composer/MessageComposer.tsx"
-import RightPanel, { RightPanelProps } from "./rightpanel/RightPanel.tsx"
import { RoomContext, RoomContextData } from "./roomcontext.ts"
-import TimelineView from "./timeline/TimelineView.tsx"
import "./RoomView.css"
interface RoomViewProps {
diff --git a/web/src/ui/RoomViewHeader.css b/web/src/ui/roomview/RoomViewHeader.css
similarity index 100%
rename from web/src/ui/RoomViewHeader.css
rename to web/src/ui/roomview/RoomViewHeader.css
diff --git a/web/src/ui/RoomViewHeader.tsx b/web/src/ui/roomview/RoomViewHeader.tsx
similarity index 95%
rename from web/src/ui/RoomViewHeader.tsx
rename to web/src/ui/roomview/RoomViewHeader.tsx
index 94bcfe8..4bd243f 100644
--- a/web/src/ui/RoomViewHeader.tsx
+++ b/web/src/ui/roomview/RoomViewHeader.tsx
@@ -17,8 +17,8 @@ import { use } from "react"
import { getAvatarURL } from "@/api/media.ts"
import { RoomStateStore } from "@/api/statestore"
import { useEventAsState } from "@/util/eventdispatcher.ts"
-import MainScreenContext from "./MainScreenContext.ts"
-import { LightboxContext } from "./modal/Lightbox.tsx"
+import MainScreenContext from "../MainScreenContext.ts"
+import { LightboxContext } from "../modal/Lightbox.tsx"
import BackIcon from "@/icons/back.svg?react"
import PeopleIcon from "@/icons/group.svg?react"
import PinIcon from "@/icons/pin.svg?react"
diff --git a/web/src/ui/roomcontext.ts b/web/src/ui/roomview/roomcontext.ts
similarity index 100%
rename from web/src/ui/roomcontext.ts
rename to web/src/ui/roomview/roomcontext.ts
diff --git a/web/src/ui/timeline/TimelineEvent.tsx b/web/src/ui/timeline/TimelineEvent.tsx
index b979139..473d061 100644
--- a/web/src/ui/timeline/TimelineEvent.tsx
+++ b/web/src/ui/timeline/TimelineEvent.tsx
@@ -20,7 +20,7 @@ import { MemDBEvent, MemberEventContent, UnreadType } from "@/api/types"
import { isEventID } from "@/util/validation.ts"
import ClientContext from "../ClientContext.ts"
import { LightboxContext } from "../modal/Lightbox.tsx"
-import { useRoomContext } from "../roomcontext.ts"
+import { useRoomContext } from "../roomview/roomcontext.ts"
import { ReplyIDBody } from "./ReplyBody.tsx"
import { ContentErrorBoundary, HiddenEvent, getBodyType, isSmallEvent } from "./content"
import EventMenu from "./menu/EventMenu.tsx"
diff --git a/web/src/ui/timeline/TimelineView.tsx b/web/src/ui/timeline/TimelineView.tsx
index 6c7f307..a7c668e 100644
--- a/web/src/ui/timeline/TimelineView.tsx
+++ b/web/src/ui/timeline/TimelineView.tsx
@@ -18,7 +18,7 @@ import { useRoomTimeline } from "@/api/statestore"
import { MemDBEvent } from "@/api/types"
import useFocus from "@/util/focus.ts"
import ClientContext from "../ClientContext.ts"
-import { useRoomContext } from "../roomcontext.ts"
+import { useRoomContext } from "../roomview/roomcontext.ts"
import TimelineEvent from "./TimelineEvent.tsx"
import "./TimelineView.css"
diff --git a/web/src/ui/timeline/menu/EventExtraMenu.tsx b/web/src/ui/timeline/menu/EventExtraMenu.tsx
index b742016..77b459d 100644
--- a/web/src/ui/timeline/menu/EventExtraMenu.tsx
+++ b/web/src/ui/timeline/menu/EventExtraMenu.tsx
@@ -18,7 +18,7 @@ import { RoomStateStore, useRoomState } from "@/api/statestore"
import { MemDBEvent, PowerLevelEventContent } from "@/api/types"
import ClientContext from "../../ClientContext.ts"
import { ModalCloseContext, ModalContext } from "../../modal/Modal.tsx"
-import { RoomContext, RoomContextData } from "../../roomcontext.ts"
+import { RoomContext, RoomContextData } from "../../roomview/roomcontext.ts"
import ConfirmWithMessageModal from "./ConfirmWithMessageModal.tsx"
import ViewSourceModal from "./ViewSourceModal.tsx"
import ViewSourceIcon from "@/icons/code.svg?react"
diff --git a/web/src/ui/timeline/menu/EventMenu.tsx b/web/src/ui/timeline/menu/EventMenu.tsx
index 717473c..5406b44 100644
--- a/web/src/ui/timeline/menu/EventMenu.tsx
+++ b/web/src/ui/timeline/menu/EventMenu.tsx
@@ -20,7 +20,7 @@ import { useEventAsState } from "@/util/eventdispatcher.ts"
import ClientContext from "../../ClientContext.ts"
import EmojiPicker from "../../emojipicker/EmojiPicker.tsx"
import { ModalContext } from "../../modal/Modal.tsx"
-import { useRoomContext } from "../../roomcontext.ts"
+import { useRoomContext } from "../../roomview/roomcontext.ts"
import EventExtraMenu from "./EventExtraMenu.tsx"
import EditIcon from "@/icons/edit.svg?react"
import MoreIcon from "@/icons/more.svg?react"
diff --git a/web/src/ui/timeline/menu/ViewSourceModal.tsx b/web/src/ui/timeline/menu/ViewSourceModal.tsx
index 69da420..630929a 100644
--- a/web/src/ui/timeline/menu/ViewSourceModal.tsx
+++ b/web/src/ui/timeline/menu/ViewSourceModal.tsx
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
import { MemDBEvent } from "@/api/types"
-import JSONView from "../../JSONView.tsx"
+import JSONView from "../../util/JSONView.tsx"
interface ViewSourceModalProps {
evt: MemDBEvent
diff --git a/web/src/ui/JSONView.css b/web/src/ui/util/JSONView.css
similarity index 100%
rename from web/src/ui/JSONView.css
rename to web/src/ui/util/JSONView.css
diff --git a/web/src/ui/JSONView.tsx b/web/src/ui/util/JSONView.tsx
similarity index 100%
rename from web/src/ui/JSONView.tsx
rename to web/src/ui/util/JSONView.tsx
diff --git a/web/src/ui/ResizeHandle.css b/web/src/ui/util/ResizeHandle.css
similarity index 100%
rename from web/src/ui/ResizeHandle.css
rename to web/src/ui/util/ResizeHandle.css
diff --git a/web/src/ui/ResizeHandle.tsx b/web/src/ui/util/ResizeHandle.tsx
similarity index 100%
rename from web/src/ui/ResizeHandle.tsx
rename to web/src/ui/util/ResizeHandle.tsx
diff --git a/web/src/ui/useResizeHandle.tsx b/web/src/ui/util/useResizeHandle.tsx
similarity index 100%
rename from web/src/ui/useResizeHandle.tsx
rename to web/src/ui/util/useResizeHandle.tsx