Repository: atomicdata-dev/atomic-server (language: rust)

Issue:
Upgrade to React 19
React 19 has been released. We should check if it is possible for us to upgrade or if any dependency needs upgrading first. Then we can look into upgrading @tomic/react to react 19 and see if we can use any of the new features like `use` for example.

There aren't many breaking changes. Most of the breaking changes are legacy features we don't use anyway.
https://react.dev/blog/2024/04/25/react-19-upgrade-guide 


Discussion / hints:
I’m running into a type compatibility issue with `Image`. The error indicates that Image's types are incompatible with React 19:
```sh
Type error: 'Image' cannot be used as a JSX component.
  Its type 'FC<ImageProps>' is not a valid JSX element type.
    Type 'FunctionComponent<ImageProps>' is not assignable to type '(props: any) => ReactNode'.
      Type 'import("/node_modules/.pnpm/@types+react@18.3.12/node_modules/@types/react/index").ReactNode' is not assignable to type 'React.ReactNode'.
        Type 'ReactElement<any, string | JSXElementConstructor<any>>' is not assignable to type 'ReactNode'.
          Property 'children' is missing in type 'ReactElement<any, string | JSXElementConstructor<any>>' but required in type 'ReactPortal'.

   7 |   return (
>  8 |       <Image subject={subject} alt={alt} {...props} />
     |        ^
   9 |   );
  10 | };
```

I think this is related to [React changing the jsx namespace](https://react.dev/blog/2024/04/25/react-19-upgrade-guide#the-jsx-namespace-in-typescript) as part of the React 19 changes.

Fix patch:
diff --git a/browser/.eslintrc.cjs b/browser/.eslintrc.cjs
index ca5d3e6fc..79356d657 100644
--- a/browser/.eslintrc.cjs
+++ b/browser/.eslintrc.cjs
@@ -38,7 +38,7 @@ module.exports = {
       'create-template/tsconfig.json',
     ],
   },
-  plugins: ['react', '@typescript-eslint', 'prettier', 'react-hooks', 'jsx-a11y'],
+  plugins: ['react', '@typescript-eslint', 'prettier', 'react-hooks', 'jsx-a11y', 'eslint-plugin-react-compiler'],
   settings: {
     react: {
       version: 'detect', // Tells eslint-plugin-react to automatically detect the version of React to use
@@ -114,5 +114,6 @@ module.exports = {
     "@typescript-eslint/no-shadow": ["error"],
     "@typescript-eslint/member-ordering": "error",
     "react/no-unknown-property": ["error", { "ignore": ["about"] }],
+    'react-compiler/react-compiler': 'error',
   },
 };
diff --git a/browser/CHANGELOG.md b/browser/CHANGELOG.md
index eebf839de..4c9c67cf9 100644
--- a/browser/CHANGELOG.md
+++ b/browser/CHANGELOG.md
@@ -28,7 +28,11 @@ This changelog covers all five packages, as they are (for now) updated as a whol
 
 ### @tomic/react
 
-- Add cjs build.
+- BREAKING CHANGE: `useCanWrite` now only returns a boolean. There is no longer a message returned.
+- BREAKING CHANGE: `useCanWrite` does not take an agent as argument any more and only checks the agent set in the store. If you need to explicitly check a different agent, use `await resource.canWrite(agent)`.
+- BREAKING CHANGE: `useDebounce` and `useDebouncedCallback` are no longer exported.
+- Added `useDebouncedSave` hook.
+- Add a cjs build.
 
 ### @tomic/cli
 
diff --git a/browser/data-browser/index.html b/browser/data-browser/index.html
index 1ceb99ce8..d64ce0c51 100644
--- a/browser/data-browser/index.html
+++ b/browser/data-browser/index.html
@@ -12,6 +12,7 @@
   <link color="#1e43a3" href="/app_data/images/mask-icon.svg" rel="mask-icon" />
   <meta content="yes" name="apple-mobile-web-app-capable" />
   <meta content="yes" name="mobile-web-app-capable" />
+  <link rel="preconnect" crossorigin="anonymous" href="https://atomicdata.dev">
   <!-- Custom fonts -->
   <link rel="preconnect" crossorigin="anonymous" href="https://fonts.googleapis.com">
   <link rel="preconnect" crossorigin="anonymous" href="https://fonts.gstatic.com">
diff --git a/browser/data-browser/package.json b/browser/data-browser/package.json
index 2ed450463..152422103 100644
--- a/browser/data-browser/package.json
+++ b/browser/data-browser/package.json
@@ -17,6 +17,7 @@
     "@radix-ui/react-popover": "^1.1.2",
     "@radix-ui/react-scroll-area": "^1.2.0",
     "@radix-ui/react-tabs": "^1.1.1",
+    "@tanstack/react-router": "^1.95.1",
     "@tiptap/extension-image": "^2.9.1",
     "@tiptap/extension-link": "^2.9.1",
     "@tiptap/extension-placeholder": "^2.9.1",
@@ -31,38 +32,36 @@
     "prismjs": "^1.29.0",
     "query-string": "^7.1.3",
     "quick-score": "^0.2.0",
-    "react": "^18.3.1",
+    "react": "^19.0.0",
     "react-colorful": "^5.6.1",
-    "react-dom": "^18.3.1",
+    "react-dom": "^19.0.0",
     "react-dropzone": "^11.7.1",
-    "react-helmet-async": "^1.3.0",
     "react-hot-toast": "^2.4.1",
     "react-hotkeys-hook": "^3.4.7",
     "react-icons": "^4.12.0",
     "react-intersection-observer": "^9.13.1",
-    "react-is": "^18.3.1",
-    "react-markdown": "^8.0.7",
+    "react-is": "^19.0.0",
+    "react-markdown": "^9.0.3",
     "react-pdf": "^9.1.1",
-    "react-router": "^6.27.0",
-    "react-router-dom": "^6.27.0",
     "react-virtualized-auto-sizer": "^1.0.24",
     "react-window": "^1.8.10",
     "reactflow": "^11.11.4",
-    "remark-gfm": "^3.0.1",
+    "remark-gfm": "^4.0.0",
     "styled-components": "^6.1.13",
     "stylis": "4.3.0",
     "tippy.js": "^6.3.7",
     "tiptap-markdown": "^0.8.10"
   },
   "devDependencies": {
-    "@swc/plugin-styled-components": "^2.0.12",
+    "@tanstack/router-devtools": "^1.95.1",
     "@types/prismjs": "^1.26.5",
-    "@types/react": "^18.3.12",
-    "@types/react-dom": "^18.3.1",
+    "@types/react": "^19.0.0",
+    "@types/react-dom": "^19.0.0",
     "@types/react-pdf": "^7.0.0",
-    "@types/react-router-dom": "^5.3.3",
     "@types/react-window": "^1.8.8",
-    "@vitejs/plugin-react-swc": "^3.7.1",
+    "@vitejs/plugin-react": "^4.3.4",
+    "babel-plugin-react-compiler": "19.0.0-beta-37ed2a7-20241206",
+    "babel-plugin-styled-components": "^2.1.4",
     "csstype": "^3.1.3",
     "gh-pages": "^5.0.0",
     "lint-staged": "^10.5.4",
diff --git a/browser/data-browser/src/App.tsx b/browser/data-browser/src/App.tsx
index 32755ec6c..e0b8a4256 100644
--- a/browser/data-browser/src/App.tsx
+++ b/browser/data-browser/src/App.tsx
@@ -1,33 +1,15 @@
-import { BrowserRouter } from 'react-router-dom';
-import { HelmetProvider } from 'react-helmet-async';
 import { StoreContext, Store } from '@tomic/react';
-import { StyleSheetManager, type ShouldForwardProp } from 'styled-components';
 
-import { GlobalStyle, ThemeWrapper } from './styling';
-import { AppRoutes } from './routes/Routes';
-import { NavWrapper } from './components/Navigation';
-import { MetaSetter } from './components/MetaSetter';
-import { Toaster } from './components/Toaster';
 import { isDev } from './config';
-import { initBugsnag } from './helpers/loggingHandlers';
-import HotKeysWrapper from './components/HotKeyWrapper';
-import { AppSettingsContextProvider } from './helpers/AppSettings';
-import CrashPage from './views/CrashPage';
-import { DialogGlobalContextProvider } from './components/Dialog/DialogGlobalContextProvider';
 import { registerHandlers } from './handlers';
-import { ErrorBoundary } from './views/ErrorPage';
-import { NetworkIndicator } from './components/NetworkIndicator';
 import { getAgentFromLocalStorage } from './helpers/agentStorage';
-import { DropdownContainer } from './components/Dropdown/DropdownContainer';
-import { PopoverContainer } from './components/Popover';
-import { SkipNav } from './components/SkipNav';
-import { ControlLockProvider } from './hooks/useControlLock';
-import { FormValidationContextProvider } from './components/forms/formValidation/FormValidationContextProvider';
 import { registerCustomCreateActions } from './components/forms/NewForm/CustomCreateActions';
-import isPropValid from '@emotion/is-prop-valid';
-import { NewResourceUIProvider } from './components/forms/NewForm/useNewResourceUI';
 import { serverURLStorage } from './helpers/serverURLStorage';
 
+import type { JSX } from 'react';
+import { RouterProvider } from '@tanstack/react-router';
+import { router } from './routes/Router';
+
 function fixDevUrl(url: string) {
   if (isDev()) {
     return url.replace('5173', '9883');
@@ -57,10 +39,6 @@ declare global {
     bugsnagApiKey: string;
   }
 }
-// Setup bugsnag for error handling, but only if there's an API key
-const ErrBoundary = window.bugsnagApiKey
-  ? initBugsnag(window.bugsnagApiKey)
-  : ErrorBoundary;
 
 // Fetch all the Properties and Classes - this helps speed up the app.
 store.preloadPropsAndClasses();
@@ -74,62 +52,11 @@ if (isDev()) {
   window.store = store;
 }
 
-// This implements the default behavior from styled-components v5
-const shouldForwardProp: ShouldForwardProp<'web'> = (propName, target) => {
-  if (typeof target === 'string') {
-    // For HTML elements, forward the prop if it is a valid HTML attribute
-    return isPropValid(propName);
-  }
-
-  // For other elements, forward all props
-  return true;
-};
-
 /** Entrypoint of the application. This is where providers go. */
 function App(): JSX.Element {
   return (
     <StoreContext.Provider value={store}>
-      <AppSettingsContextProvider>
-        <HelmetProvider>
-          {/* Basename is for hosting on GitHub pages */}
-          <BrowserRouter basename='/'>
-            <ControlLockProvider>
-              <HotKeysWrapper>
-                <StyleSheetManager shouldForwardProp={shouldForwardProp}>
-                  <ThemeWrapper>
-                    <GlobalStyle />
-                    {/* @ts-ignore fallback component type too strict */}
-                    <ErrBoundary FallbackComponent={CrashPage}>
-                      {/* Default form validation provider. Does not do anything on its own but will make sure useValidation works without context*/}
-                      <FormValidationContextProvider
-                        onValidationChange={() => undefined}
-                      >
-                        <Toaster />
-                        <MetaSetter />
-                        <DropdownContainer>
-                          <DialogGlobalContextProvider>
-                            <PopoverContainer>
-                              <DropdownContainer>
-                                <NewResourceUIProvider>
-                                  <SkipNav />
-                                  <NavWrapper>
-                                    <AppRoutes />
-                                  </NavWrapper>
-                                </NewResourceUIProvider>
-                              </DropdownContainer>
-                            </PopoverContainer>
-                            <NetworkIndicator />
-                          </DialogGlobalContextProvider>
-                        </DropdownContainer>
-                      </FormValidationContextProvider>
-                    </ErrBoundary>
-                  </ThemeWrapper>
-                </StyleSheetManager>
-              </HotKeysWrapper>
-            </ControlLockProvider>
-          </BrowserRouter>
-        </HelmetProvider>
-      </AppSettingsContextProvider>
+      <RouterProvider router={router}></RouterProvider>
     </StoreContext.Provider>
   );
 }
diff --git a/browser/data-browser/src/Providers.tsx b/browser/data-browser/src/Providers.tsx
new file mode 100644
index 000000000..d8afdb885
--- /dev/null
+++ b/browser/data-browser/src/Providers.tsx
@@ -0,0 +1,76 @@
+import { Toaster } from 'react-hot-toast';
+import { StyleSheetManager, type ShouldForwardProp } from 'styled-components';
+import { DialogGlobalContextProvider } from './components/Dialog/DialogGlobalContextProvider';
+import { DropdownContainer } from './components/Dropdown/DropdownContainer';
+import { FormValidationContextProvider } from './components/forms/formValidation/FormValidationContextProvider';
+import { NewResourceUIProvider } from './components/forms/NewForm/useNewResourceUI';
+import HotKeysWrapper from './components/HotKeyWrapper';
+import { MetaSetter } from './components/MetaSetter';
+import { NavWrapper } from './components/Navigation';
+import { NetworkIndicator } from './components/NetworkIndicator';
+import { PopoverContainer } from './components/Popover';
+import { SkipNav } from './components/SkipNav';
+import { ControlLockProvider } from './hooks/useControlLock';
+import { ThemeWrapper, GlobalStyle } from './styling';
+import isPropValid from '@emotion/is-prop-valid';
+import { initBugsnag } from './helpers/loggingHandlers';
+import { ErrorBoundary } from './views/ErrorPage';
+import CrashPage from './views/CrashPage';
+import { AppSettingsContextProvider } from './helpers/AppSettings';
+import { NavStateProvider } from './components/NavState';
+
+// Setup bugsnag for error handling, but only if there's an API key
+const ErrBoundary = window.bugsnagApiKey
+  ? initBugsnag(window.bugsnagApiKey)
+  : ErrorBoundary;
+
+// This implements the default behavior from styled-components v5
+const shouldForwardProp: ShouldForwardProp<'web'> = (propName, target) => {
+  if (typeof target === 'string') {
+    // For HTML elements, forward the prop if it is a valid HTML attribute
+    return isPropValid(propName);
+  }
+
+  // For other elements, forward all props
+  return true;
+};
+
+export const Providers: React.FC<React.PropsWithChildren> = ({ children }) => {
+  return (
+    <NavStateProvider>
+      <AppSettingsContextProvider>
+        <ControlLockProvider>
+          <HotKeysWrapper>
+            <StyleSheetManager shouldForwardProp={shouldForwardProp}>
+              <ThemeWrapper>
+                <GlobalStyle />
+                <ErrBoundary FallbackComponent={CrashPage}>
+                  {/* Default form validation provider. Does not do anything on its own but will make sure useValidation works without context*/}
+                  <FormValidationContextProvider
+                    onValidationChange={() => undefined}
+                  >
+                    <Toaster />
+                    <MetaSetter />
+                    <DropdownContainer>
+                      <DialogGlobalContextProvider>
+                        <PopoverContainer>
+                          <DropdownContainer>
+                            <NewResourceUIProvider>
+                              <SkipNav />
+                              <NavWrapper>{children}</NavWrapper>
+                            </NewResourceUIProvider>
+                          </DropdownContainer>
+                        </PopoverContainer>
+                        <NetworkIndicator />
+                      </DialogGlobalContextProvider>
+                    </DropdownContainer>
+                  </FormValidationContextProvider>
+                </ErrBoundary>
+              </ThemeWrapper>
+            </StyleSheetManager>
+          </HotKeysWrapper>
+        </ControlLockProvider>
+      </AppSettingsContextProvider>
+    </NavStateProvider>
+  );
+};
diff --git a/browser/data-browser/src/chunks/EmojiInput/EmojiInput.tsx b/browser/data-browser/src/chunks/EmojiInput/EmojiInput.tsx
index 5610abe7a..62c0b95ea 100644
--- a/browser/data-browser/src/chunks/EmojiInput/EmojiInput.tsx
+++ b/browser/data-browser/src/chunks/EmojiInput/EmojiInput.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useState } from 'react';
+import { useCallback, useState, type JSX } from 'react';
 import Picker from '@emoji-mart/react';
 import { styled } from 'styled-components';
 import * as RadixPopover from '@radix-ui/react-popover';
diff --git a/browser/data-browser/src/chunks/GraphViewer/FloatingEdge.tsx b/browser/data-browser/src/chunks/GraphViewer/FloatingEdge.tsx
index 942fc25af..8df314018 100644
--- a/browser/data-browser/src/chunks/GraphViewer/FloatingEdge.tsx
+++ b/browser/data-browser/src/chunks/GraphViewer/FloatingEdge.tsx
@@ -1,4 +1,4 @@
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import {
   useStore as useFlowStore,
   getBezierPath,
diff --git a/browser/data-browser/src/chunks/GraphViewer/OntologyGraph.tsx b/browser/data-browser/src/chunks/GraphViewer/OntologyGraph.tsx
index 37183124e..c6cd0f8e3 100644
--- a/browser/data-browser/src/chunks/GraphViewer/OntologyGraph.tsx
+++ b/browser/data-browser/src/chunks/GraphViewer/OntologyGraph.tsx
@@ -1,5 +1,5 @@
 import { Resource, useStore } from '@tomic/react';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import ReactFlow, {
   Controls,
   useReactFlow,
diff --git a/browser/data-browser/src/chunks/PDFViewer/index.tsx b/browser/data-browser/src/chunks/PDFViewer/index.tsx
index 98dbd3c15..771e03316 100644
--- a/browser/data-browser/src/chunks/PDFViewer/index.tsx
+++ b/browser/data-browser/src/chunks/PDFViewer/index.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useMemo, useState } from 'react';
+import { useCallback, useMemo, useState, type JSX } from 'react';
 import { pdfjs, Document, Page } from 'react-pdf';
 import 'react-pdf/dist/esm/Page/TextLayer.css';
 import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
diff --git a/browser/data-browser/src/components/AllProps.tsx b/browser/data-browser/src/components/AllProps.tsx
index 8f398a18e..a3b97f3cc 100644
--- a/browser/data-browser/src/components/AllProps.tsx
+++ b/browser/data-browser/src/components/AllProps.tsx
@@ -4,6 +4,8 @@ import { styled, css } from 'styled-components';
 import PropVal from './PropVal';
 import { ALL_PROPS_CONTAINER } from '../helpers/containers';
 
+import type { JSX } from 'react';
+
 type Props = {
   resource: Resource;
   /** A list of property subjects (URLs) that need not be rendered */
diff --git a/browser/data-browser/src/components/AllPropsSimple.tsx b/browser/data-browser/src/components/AllPropsSimple.tsx
index 0b0fc09fc..1b8b8b514 100644
--- a/browser/data-browser/src/components/AllPropsSimple.tsx
+++ b/browser/data-browser/src/components/AllPropsSimple.tsx
@@ -7,7 +7,7 @@ import {
   useSubject,
   useTitle,
 } from '@tomic/react';
-import { useMemo } from 'react';
+import { useMemo, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { InlineFormattedResourceList } from './InlineFormattedResourceList';
 
diff --git a/browser/data-browser/src/components/AtomicLink.tsx b/browser/data-browser/src/components/AtomicLink.tsx
index cf4a608f6..cec0f1c8d 100644
--- a/browser/data-browser/src/components/AtomicLink.tsx
+++ b/browser/data-browser/src/components/AtomicLink.tsx
@@ -1,4 +1,4 @@
-import { ReactNode, forwardRef } from 'react';
+import { ReactNode, forwardRef, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { constructOpenURL, pathToURL } from '../helpers/navigation';
 import { FaExternalLinkAlt } from 'react-icons/fa';
@@ -33,7 +33,7 @@ export const AtomicLink = forwardRef<HTMLAnchorElement, AtomicLinkProps>(
   ): JSX.Element => {
     const navigate = useNavigateWithTransition();
 
-    if (!subject && !href && !path) {
+    if (subject === undefined && href === undefined && path === undefined) {
       return (
         <ErrorLook>
           No `subject`, `path` or `href` passed to this AtomicLink.
diff --git a/browser/data-browser/src/components/BetaBadge.tsx b/browser/data-browser/src/components/BetaBadge.tsx
index a48056e64..06686a79c 100644
--- a/browser/data-browser/src/components/BetaBadge.tsx
+++ b/browser/data-browser/src/components/BetaBadge.tsx
@@ -1,5 +1,7 @@
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 export function BetaBadge(): JSX.Element {
   return <Badge>BETA</Badge>;
 }
diff --git a/browser/data-browser/src/components/Button.tsx b/browser/data-browser/src/components/Button.tsx
index c67c7b36d..9eb7ff001 100644
--- a/browser/data-browser/src/components/Button.tsx
+++ b/browser/data-browser/src/components/Button.tsx
@@ -1,4 +1,4 @@
-import { forwardRef, PropsWithChildren } from 'react';
+import { forwardRef, PropsWithChildren, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { transition } from '../helpers/transition';
 import { Spinner } from './Spinner';
diff --git a/browser/data-browser/src/components/ButtonGroup.tsx b/browser/data-browser/src/components/ButtonGroup.tsx
index a8d3f9ecd..6266a15b9 100644
--- a/browser/data-browser/src/components/ButtonGroup.tsx
+++ b/browser/data-browser/src/components/ButtonGroup.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useId, useState } from 'react';
+import { useCallback, useId, useState, type JSX } from 'react';
 import { styled } from 'styled-components';
 
 export interface ButtonGroupOption {
diff --git a/browser/data-browser/src/components/ClassDetail.tsx b/browser/data-browser/src/components/ClassDetail.tsx
index 1d0678e0c..70942f844 100644
--- a/browser/data-browser/src/components/ClassDetail.tsx
+++ b/browser/data-browser/src/components/ClassDetail.tsx
@@ -1,9 +1,10 @@
-import React from 'react';
+import React, { type JSX } from 'react';
 import { Resource, useResource } from '@tomic/react';
 import { Detail } from './Detail';
 import { getIconForClass } from '../helpers/iconMap';
 import { InlineFormattedResourceList } from './InlineFormattedResourceList';
 import { AtomicLink } from './AtomicLink';
+import { Row } from './Row';
 
 type ClassDetailProps = {
   resource: Resource;
@@ -16,12 +17,12 @@ export const ClassDetail: React.FC<ClassDetailProps> = ({ resource }) => {
   }
 
   return (
-    <Detail>
+    <Row gap='1ch'>
       <InlineFormattedResourceList
         subjects={resource.getClasses()}
         RenderComp={ClassItem}
       />
-    </Detail>
+    </Row>
   );
 };
 
diff --git a/browser/data-browser/src/components/ClassSelectorDialog.tsx b/browser/data-browser/src/components/ClassSelectorDialog.tsx
index 7509d6b6c..52047727e 100644
--- a/browser/data-browser/src/components/ClassSelectorDialog.tsx
+++ b/browser/data-browser/src/components/ClassSelectorDialog.tsx
@@ -1,4 +1,4 @@
-import { useEffect } from 'react';
+import { useEffect, type JSX } from 'react';
 import { Dialog, DialogContent, DialogTitle, useDialog } from './Dialog';
 import { OutlinedSection } from './OutlinedSection';
 import { useServerSearch, core, type Core, useResource } from '@tomic/react';
diff --git a/browser/data-browser/src/components/Collapse.tsx b/browser/data-browser/src/components/Collapse.tsx
index 43d4b6aab..5326301fd 100644
--- a/browser/data-browser/src/components/Collapse.tsx
+++ b/browser/data-browser/src/components/Collapse.tsx
@@ -1,4 +1,4 @@
-import { useEffect, useState } from 'react';
+import { useEffect, useState, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { timeoutEffect } from '../helpers/timeoutEffect';
 import { animationDuration } from '../styling';
diff --git a/browser/data-browser/src/components/CommitDetail.tsx b/browser/data-browser/src/components/CommitDetail.tsx
index df982f4f7..5078d0874 100644
--- a/browser/data-browser/src/components/CommitDetail.tsx
+++ b/browser/data-browser/src/components/CommitDetail.tsx
@@ -4,6 +4,8 @@ import { Detail } from './Detail';
 import { DateTime } from './datatypes/DateTime';
 import { AtomicLink } from './AtomicLink';
 
+import type { JSX } from 'react';
+
 type Props = {
   commitSubject?: string;
 };
@@ -22,8 +24,8 @@ export function CommitDetail({ commitSubject }: Props): JSX.Element | null {
     return null;
   }
 
-  if (!commitSubject || !resource.isReady) {
-    return <Detail>loading...</Detail>;
+  if (!commitSubject || resource.loading) {
+    return <Detail>-</Detail>;
   }
 
   return (
diff --git a/browser/data-browser/src/components/ConfirmationDialog.tsx b/browser/data-browser/src/components/ConfirmationDialog.tsx
index b48a7b8f1..6e73be7ef 100644
--- a/browser/data-browser/src/components/ConfirmationDialog.tsx
+++ b/browser/data-browser/src/components/ConfirmationDialog.tsx
@@ -1,4 +1,4 @@
-import { useEffect } from 'react';
+import { useEffect, type JSX } from 'react';
 import {
   Dialog,
   DialogActions,
diff --git a/browser/data-browser/src/components/Detail.tsx b/browser/data-browser/src/components/Detail.tsx
index 492356326..4dab568b8 100644
--- a/browser/data-browser/src/components/Detail.tsx
+++ b/browser/data-browser/src/components/Detail.tsx
@@ -5,10 +5,12 @@ export const Detail = styled.div`
   display: inline-flex;
   align-items: center;
   gap: 0.5ch;
-  margin-right: 2rem;
 `;
 
 /** A wrapper for the Detail component . */
 export const Details = styled.div`
   font-style: italic;
+  display: flex;
+  justify-content: space-between;
+  flex-wrap: wrap;
 `;
diff --git a/browser/data-browser/src/components/Details.tsx b/browser/data-browser/src/components/Details.tsx
index dbebcd4c7..ebbdd01ab 100644
--- a/browser/data-browser/src/components/Details.tsx
+++ b/browser/data-browser/src/components/Details.tsx
@@ -1,4 +1,10 @@
-import { PropsWithChildren, useCallback, useEffect, useState } from 'react';
+import {
+  PropsWithChildren,
+  useCallback,
+  useEffect,
+  useState,
+  type JSX,
+} from 'react';
 import { styled } from 'styled-components';
 import { FaCaretRight } from 'react-icons/fa';
 import { Collapse } from './Collapse';
@@ -40,7 +46,7 @@ export function Details({
 
       return !p;
     });
-  }, []);
+  }, [onStateToggle]);
 
   return (
     <>
@@ -52,7 +58,7 @@ export function Details({
           hide={!!disabled}
           aria-label={isOpen ? 'collapse' : 'expand'}
         >
-          <Icon turn={!!isOpen} />
+          <Icon $turn={!!isOpen} />
         </StyledIconButton>
         <TitleWrapper>{title}</TitleWrapper>
       </SummaryWrapper>
@@ -78,7 +84,7 @@ const TitleWrapper = styled.div`
   }
 `;
 
-const Icon = styled(FaCaretRight)<{ turn: boolean }>`
+const Icon = styled(FaCaretRight)<{ $turn: boolean }>`
   color: ${({ theme }) => theme.colors.main};
   margin-top: auto;
   cursor: pointer;
@@ -89,7 +95,7 @@ const Icon = styled(FaCaretRight)<{ turn: boolean }>`
   transition:
     transform var(--speed) ease-in-out,
     background-color var(--speed) ease;
-  transform: rotate(${props => (props.turn ? '90deg' : '0deg')});
+  transform: rotate(${props => (props.$turn ? '90deg' : '0deg')});
   aspect-ratio: 1/1;
   display: flex;
   align-items: center;
diff --git a/browser/data-browser/src/components/Dialog/DialogGlobalContextProvider.tsx b/browser/data-browser/src/components/Dialog/DialogGlobalContextProvider.tsx
index 5f0a6ad58..56ae6dbd0 100644
--- a/browser/data-browser/src/components/Dialog/DialogGlobalContextProvider.tsx
+++ b/browser/data-browser/src/components/Dialog/DialogGlobalContextProvider.tsx
@@ -16,10 +16,14 @@ import { styled } from 'styled-components';
 interface DialogGlobalContext {
   openDialogs: string[];
   setDialogOpen: (id: string, open: boolean) => void;
-  portal: RefObject<HTMLDivElement>;
+  portal: RefObject<HTMLDivElement | null>;
 }
 
-export const DialogContext = createContext<DialogGlobalContext>(null!);
+export const DialogContext = createContext<DialogGlobalContext>({
+  openDialogs: [],
+  setDialogOpen: () => {},
+  portal: { current: null },
+});
 
 export const DialogGlobalContextProvider: FC<PropsWithChildren> = ({
   children,
diff --git a/browser/data-browser/src/components/Dialog/useDialog.tsx b/browser/data-browser/src/components/Dialog/useDialog.tsx
index 7ef7d5740..22de9ed1f 100644
--- a/browser/data-browser/src/components/Dialog/useDialog.tsx
+++ b/browser/data-browser/src/components/Dialog/useDialog.tsx
@@ -16,7 +16,7 @@ export type UseDialogOptions<E extends HTMLElement> = {
   bindShow?: React.Dispatch<boolean>;
   onCancel?: () => void;
   onSuccess?: () => void;
-  triggerRef?: React.RefObject<E>;
+  triggerRef?: React.RefObject<E | null>;
 };
 
 /** Sets up state, and functions to use with a {@link Dialog} */
diff --git a/browser/data-browser/src/components/Dropdown/DefaultTrigger.tsx b/browser/data-browser/src/components/Dropdown/DefaultTrigger.tsx
index 408f319ec..f560fa5ff 100644
--- a/browser/data-browser/src/components/Dropdown/DefaultTrigger.tsx
+++ b/browser/data-browser/src/components/Dropdown/DefaultTrigger.tsx
@@ -1,7 +1,6 @@
-import { useId } from 'react';
 import { IconButton } from '../IconButton/IconButton';
 import {
-  DropdownTriggerRenderFunction,
+  DropdownTriggerComponent,
   type DropdownTriggerProps,
 } from './DropdownTrigger';
 
@@ -12,13 +11,14 @@ export const buildDefaultTrigger = (
   icon: React.ReactNode,
   title = 'Open menu',
   ButtonComp: typeof IconButton = IconButton,
-): DropdownTriggerRenderFunction => {
-  const Comp = (
-    { onClick, menuId, isActive }: DropdownTriggerProps,
-    ref: React.Ref<HTMLButtonElement>,
-  ) => {
-    const id = useId();
-
+): DropdownTriggerComponent => {
+  const Comp = ({
+    onClick,
+    menuId,
+    isActive,
+    ref,
+    id,
+  }: DropdownTriggerProps) => {
     return (
       <ButtonComp
         id={id}
diff --git a/browser/data-browser/src/components/Dropdown/DropdownContainer.tsx b/browser/data-browser/src/components/Dropdown/DropdownContainer.tsx
index cc00156c2..7bd5da3ea 100644
--- a/browser/data-browser/src/components/Dropdown/DropdownContainer.tsx
+++ b/browser/data-browser/src/components/Dropdown/DropdownContainer.tsx
@@ -8,10 +8,10 @@ export const DropdownContainer: React.FC<React.PropsWithChildren<unknown>> = ({
   const portalRef = useRef<HTMLDivElement>(null);
 
   return (
-    <DropdownPortalContext.Provider value={portalRef}>
+    <DropdownPortalContext value={portalRef}>
       {children}
       <DropdownContainerDiv ref={portalRef}></DropdownContainerDiv>
-    </DropdownPortalContext.Provider>
+    </DropdownPortalContext>
   );
 };
 
diff --git a/browser/data-browser/src/components/Dropdown/DropdownTrigger.ts b/browser/data-browser/src/components/Dropdown/DropdownTrigger.ts
index da17763a4..aa52db8a3 100644
--- a/browser/data-browser/src/components/Dropdown/DropdownTrigger.ts
+++ b/browser/data-browser/src/components/Dropdown/DropdownTrigger.ts
@@ -2,9 +2,8 @@ export interface DropdownTriggerProps {
   onClick: (event: React.MouseEvent) => void;
   menuId: string;
   isActive: boolean;
+  ref: React.Ref<HTMLButtonElement | null>;
+  id: string;
 }
 
-export type DropdownTriggerRenderFunction = React.ForwardRefRenderFunction<
-  HTMLButtonElement,
-  DropdownTriggerProps
->;
+export type DropdownTriggerComponent = React.FC<DropdownTriggerProps>;
diff --git a/browser/data-browser/src/components/Dropdown/dropdownContext.ts b/browser/data-browser/src/components/Dropdown/dropdownContext.ts
index a35c6c132..9830d5424 100644
--- a/browser/data-browser/src/components/Dropdown/dropdownContext.ts
+++ b/browser/data-browser/src/components/Dropdown/dropdownContext.ts
@@ -1,5 +1,7 @@
 import { createContext } from 'react';
 
 export const DropdownPortalContext = createContext<
-  React.RefObject<HTMLDivElement>
->(null!);
+  React.RefObject<HTMLDivElement | null>
+>({
+  current: null,
+});
diff --git a/browser/data-browser/src/components/Dropdown/index.tsx b/browser/data-browser/src/components/Dropdown/index.tsx
index 005b19c24..6677c06f8 100644
--- a/browser/data-browser/src/components/Dropdown/index.tsx
+++ b/browser/data-browser/src/components/Dropdown/index.tsx
@@ -6,15 +6,15 @@ import {
   useState,
   useCallback,
   PropsWithChildren,
-  forwardRef,
   ReactNode,
   useEffect,
+  type JSX,
 } from 'react';
 import { useHotkeys } from 'react-hotkeys-hook';
 import { styled } from 'styled-components';
 import { useClickAwayListener } from '../../hooks/useClickAwayListener';
 import { Button } from '../Button';
-import { DropdownTriggerRenderFunction } from './DropdownTrigger';
+import { DropdownTriggerComponent as DropdownTriggerComponent } from './DropdownTrigger';
 import { shortcuts } from '../HotKeyWrapper';
 import { Shortcut } from '../Shortcut';
 import { transition } from '../../helpers/transition';
@@ -41,7 +41,7 @@ export type DropdownItem = typeof DIVIDER | MenuItemMinimial;
 interface DropdownMenuProps {
   /** The list of menu items */
   items: DropdownItem[];
-  trigger: DropdownTriggerRenderFunction;
+  Trigger: DropdownTriggerComponent;
   /** Enables the keyboard shortcut */
   isMainMenu?: boolean;
   bindActive?: (active: boolean) => void;
@@ -108,11 +108,12 @@ function normalizeItems(items: DropdownItem[]) {
  */
 export function DropdownMenu({
   items,
-  trigger,
+  Trigger,
   isMainMenu,
   bindActive = () => undefined,
 }: DropdownMenuProps): JSX.Element {
   const menuId = useId();
+  const triggerId = useId();
   const dropdownRef = useRef<HTMLDivElement>(null);
   const triggerRef = useRef<HTMLButtonElement>(null);
 
@@ -252,8 +253,6 @@ export function DropdownMenu({
     [getNewIndex],
   );
 
-  const Trigger = useMemo(() => forwardRef(trigger), []);
-
   const handleBlur = useCallback(() => {
     // Doesn't work without delay, maybe the browser sets document.activeElement after firering the blur event?
     requestAnimationFrame(() => {
@@ -268,6 +267,7 @@ export function DropdownMenu({
   return (
     <>
       <Trigger
+        id={triggerId}
         ref={triggerRef}
         onClick={handleTriggerActivate}
         isActive={isActive}
@@ -281,7 +281,7 @@ export function DropdownMenu({
             id={menuId}
             onMouseOver={handleMouseOverMenu}
             onBlur={handleBlur}
-            aria-labelledby={triggerRef.current?.id}
+            aria-labelledby={triggerId}
             role='menu'
           >
             {normalizedItems.map((props, i) => {
diff --git a/browser/data-browser/src/components/EditableTitle.tsx b/browser/data-browser/src/components/EditableTitle.tsx
index a48ffc26a..adc129d17 100644
--- a/browser/data-browser/src/components/EditableTitle.tsx
+++ b/browser/data-browser/src/components/EditableTitle.tsx
@@ -1,5 +1,5 @@
 import { Resource, useCanWrite, useTitle } from '@tomic/react';
-import { useEffect, useRef, useState } from 'react';
+import { useEffect, useRef, useState, type JSX } from 'react';
 import { useHotkeys } from 'react-hotkeys-hook';
 import { FaPencil } from 'react-icons/fa6';
 import { styled, css } from 'styled-components';
@@ -13,7 +13,7 @@ import { UnsavedIndicator } from './UnsavedIndicator';
 export interface EditableTitleProps {
   resource: Resource;
   /** Uses `name` by default */
-  parentRef?: React.RefObject<HTMLInputElement>;
+  parentRef?: React.RefObject<HTMLInputElement | null>;
   id?: string;
   className?: string;
 }
@@ -35,7 +35,7 @@ export function EditableTitle({
   const innerRef = useRef<HTMLInputElement>(null);
   const ref = parentRef || innerRef;
 
-  const [canEdit] = useCanWrite(resource);
+  const canEdit = useCanWrite(resource);
 
   useHotkeys(
     'enter',
diff --git a/browser/data-browser/src/components/ErrorLook.tsx b/browser/data-browser/src/components/ErrorLook.tsx
index 71c1469dd..cd0025e3f 100644
--- a/browser/data-browser/src/components/ErrorLook.tsx
+++ b/browser/data-browser/src/components/ErrorLook.tsx
@@ -3,6 +3,8 @@ import { styled, css } from 'styled-components';
 
 import { FaExclamationTriangle } from 'react-icons/fa';
 
+import type { JSX } from 'react';
+
 export const errorLookStyle = css`
   color: ${props => props.theme.colors.alert};
   font-family: monospace;
diff --git a/browser/data-browser/src/components/ExternalLink.tsx b/browser/data-browser/src/components/ExternalLink.tsx
index 68b790cf3..6ee83dfc5 100644
--- a/browser/data-browser/src/components/ExternalLink.tsx
+++ b/browser/data-browser/src/components/ExternalLink.tsx
@@ -1,6 +1,8 @@
 import { styled } from 'styled-components';
 import { FaExternalLinkAlt } from 'react-icons/fa';
 
+import type { JSX } from 'react';
+
 export enum ExternalLinkVariant {
   Plain,
   Button,
diff --git a/browser/data-browser/src/components/FilePill.tsx b/browser/data-browser/src/components/FilePill.tsx
index a3475eeb6..410f3d79c 100644
--- a/browser/data-browser/src/components/FilePill.tsx
+++ b/browser/data-browser/src/components/FilePill.tsx
@@ -3,6 +3,8 @@ import { useResource, useTitle } from '@tomic/react';
 import { AtomicLink } from './AtomicLink';
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 interface FilePillProps {
   subject: string;
 }
diff --git a/browser/data-browser/src/components/HotKeyWrapper.tsx b/browser/data-browser/src/components/HotKeyWrapper.tsx
index ab598b4b0..d61cd4e12 100644
--- a/browser/data-browser/src/components/HotKeyWrapper.tsx
+++ b/browser/data-browser/src/components/HotKeyWrapper.tsx
@@ -1,12 +1,14 @@
 import * as React from 'react';
 import { dataURL, editURL } from '../helpers/navigation';
 import { useHotkeys } from 'react-hotkeys-hook';
-import { useNavigate } from 'react-router-dom';
 import { useCurrentSubject } from '../helpers/useCurrentSubject';
 import { Client } from '@tomic/react';
 import { useSettings } from '../helpers/AppSettings';
 import { paths } from '../routes/paths';
 
+import type { JSX } from 'react';
+import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
+
 type Props = {
   children: React.ReactNode;
 };
@@ -63,7 +65,7 @@ export function displayShortcut(shortcut: string): string {
 
 /** App-wide keyboard events handler. */
 function HotKeysWrapper({ children }: Props): JSX.Element {
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
   const [subject] = useCurrentSubject();
   const { sideBarLocked, setSideBarLocked } = useSettings();
 
@@ -99,7 +101,7 @@ function HotKeysWrapper({ children }: Props): JSX.Element {
   });
   useHotkeys(shortcuts.themeSettings, e => {
     e.preventDefault();
-    navigate(paths.themeSettings);
+    navigate(paths.appSettings);
   });
   useHotkeys(shortcuts.keyboardShortcuts, e => {
     e.preventDefault();
diff --git a/browser/data-browser/src/components/IconButton/IconButton.tsx b/browser/data-browser/src/components/IconButton/IconButton.tsx
index 3446486cc..bd88be63f 100644
--- a/browser/data-browser/src/components/IconButton/IconButton.tsx
+++ b/browser/data-browser/src/components/IconButton/IconButton.tsx
@@ -1,8 +1,6 @@
 import {
   ComponentType,
   ButtonHTMLAttributes,
-  forwardRef,
-  PropsWithChildren,
   AnchorHTMLAttributes,
 } from 'react';
 import { styled, DefaultTheme } from 'styled-components';
@@ -30,52 +28,51 @@ type BaseProps = {
 };
 
 export type IconButtonProps = BaseProps &
-  ButtonHTMLAttributes<HTMLButtonElement>;
+  ButtonHTMLAttributes<HTMLButtonElement> & {
+    ref?: React.Ref<HTMLButtonElement | null>;
+  };
 
-export const IconButton = forwardRef<
-  HTMLButtonElement,
-  PropsWithChildren<IconButtonProps>
->(({ variant, children, color, ...props }, ref) => {
+export const IconButton: React.FC<React.PropsWithChildren<IconButtonProps>> = ({
+  variant = IconButtonVariant.Simple,
+  color = 'inherit',
+  size = '1em',
+  children,
+  ref,
+  ...props
+}) => {
   const Comp = ComponentMap.get(variant!) ?? SimpleIconButton;
 
   return (
-    <Comp ref={ref} color={color!} {...props}>
+    <Comp ref={ref} color={color} size={size} {...props}>
       {children}
     </Comp>
   );
-});
-
-IconButton.displayName = 'IconButton';
-
-const defaultProps = {
-  variant: IconButtonVariant.Simple,
-  color: 'inherit',
-  size: '1em',
-} as IconButtonProps;
-
-IconButton.defaultProps = defaultProps;
+};
 
 export type IconButtonLinkProps = BaseProps &
   AnchorHTMLAttributes<HTMLAnchorElement> & {
     href: string;
+    ref?: React.Ref<HTMLAnchorElement | null>;
   };
 
-export const IconButtonLink = forwardRef<
-  HTMLAnchorElement,
-  PropsWithChildren<IconButtonLinkProps>
->(({ variant, children, color, ...props }, ref) => {
+export const IconButtonLink: React.FC<
+  React.PropsWithChildren<IconButtonLinkProps>
+> = ({
+  variant = IconButtonVariant.Simple,
+  color = 'inherit',
+  size = '1em',
+  ref,
+  children,
+  ...props
+}) => {
   const Comp = ComponentMap.get(variant ?? IconButtonVariant.Simple)!;
 
   return (
-    <Comp ref={ref} color={color!} as='a' {...props}>
+    <Comp ref={ref} color={color!} size={size} as='a' {...props}>
       {children}
     </Comp>
   );
-});
-
-IconButtonLink.displayName = 'IconButtonLink';
-
-IconButtonLink.defaultProps = defaultProps as IconButtonLinkProps;
+};
 
 interface ButtonBaseProps {
   size?: string;
diff --git a/browser/data-browser/src/components/ImageViewer.tsx b/browser/data-browser/src/components/ImageViewer.tsx
index f86791bfd..b550c2b0d 100644
--- a/browser/data-browser/src/components/ImageViewer.tsx
+++ b/browser/data-browser/src/components/ImageViewer.tsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { createPortal } from 'react-dom';
 import { useHotkeys } from 'react-hotkeys-hook';
 
diff --git a/browser/data-browser/src/components/InlineFormattedResourceList.tsx b/browser/data-browser/src/components/InlineFormattedResourceList.tsx
index 635af1c53..4a5a6c5aa 100644
--- a/browser/data-browser/src/components/InlineFormattedResourceList.tsx
+++ b/browser/data-browser/src/components/InlineFormattedResourceList.tsx
@@ -1,5 +1,7 @@
 import { ResourceInline } from '../views/ResourceInline';
 
+import type { JSX } from 'react';
+
 interface InlineFormattedResourceListProps {
   subjects: string[];
   /** Optional component to render items instead of an inline resource */
diff --git a/browser/data-browser/src/components/Loader.tsx b/browser/data-browser/src/components/Loader.tsx
index 394610353..13cfecd03 100644
--- a/browser/data-browser/src/components/Loader.tsx
+++ b/browser/data-browser/src/components/Loader.tsx
@@ -1,4 +1,5 @@
 import { styled, keyframes } from 'styled-components';
+import { CurrentBackgroundColor } from '../globalCssVars';
 
 const loadingAnimation = keyframes`
   from {
@@ -11,13 +12,16 @@ const loadingAnimation = keyframes`
 
 export const LoaderInline = styled.span`
   --loader-bg-from: ${p => p.theme.colors.bg1};
-  --loader-bg-to: ${p => p.theme.colors.bg};
+  --loader-bg-to: ${CurrentBackgroundColor.var()};
   background-color: ${p => p.theme.colors.bg1};
   border-radius: ${p => p.theme.radius};
   animation: ${loadingAnimation} 0.8s infinite ease-in-out alternate;
-  width: 100%;
+  flex: 1;
   display: inline-block;
-  height: 1rem;
+  padding: 0;
+  padding-inline: 1ch;
+  margin: 0;
+  color: ${p => p.theme.colors.textLight};
 `;
 
 export const LoaderBlock = styled.div`
diff --git a/browser/data-browser/src/components/Logo.tsx b/browser/data-browser/src/components/Logo.tsx
index 8b079ed3b..7c738b1b6 100644
--- a/browser/data-browser/src/components/Logo.tsx
+++ b/browser/data-browser/src/components/Logo.tsx
@@ -1,5 +1,7 @@
 import { useSettings } from '../helpers/AppSettings';
 
+import type { JSX } from 'react';
+
 interface LogoProps {
   style: React.CSSProperties;
 }
diff --git a/browser/data-browser/src/components/Main.tsx b/browser/data-browser/src/components/Main.tsx
index 82ffac34d..8af90b1c6 100644
--- a/browser/data-browser/src/components/Main.tsx
+++ b/browser/data-browser/src/components/Main.tsx
@@ -1,4 +1,4 @@
-import { PropsWithChildren, memo } from 'react';
+import { PropsWithChildren, memo, type JSX } from 'react';
 import { VisuallyHidden } from './VisuallyHidden';
 import { styled } from 'styled-components';
 import {
diff --git a/browser/data-browser/src/components/MetaSetter.tsx b/browser/data-browser/src/components/MetaSetter.tsx
index 2418ee5dd..7055050a5 100644
--- a/browser/data-browser/src/components/MetaSetter.tsx
+++ b/browser/data-browser/src/components/MetaSetter.tsx
@@ -1,45 +1,44 @@
 import {
-  properties,
+  core,
   unknownSubject,
   useResource,
   useString,
   useTitle,
 } from '@tomic/react';
 
-import { Helmet } from 'react-helmet-async';
 import { useSettings } from '../helpers/AppSettings';
 import { useCurrentSubject } from '../helpers/useCurrentSubject';
 
+import type { JSX } from 'react';
+
 /** Sets various HTML meta tags, depending on the currently opened resource */
 export function MetaSetter(): JSX.Element {
   const { mainColor, darkMode } = useSettings();
   const [subject] = useCurrentSubject();
   const resource = useResource(subject);
-  let [title] = useTitle(resource);
-  let [description] = useString(resource, properties.description);
-  const hasResource =
-    resource.isReady() && resource.getSubject() !== unknownSubject;
+  const [title] = useTitle(resource);
+  const [description] = useString(resource, core.properties.description);
+  const hasResource = resource.isReady() && resource.subject !== unknownSubject;
 
-  title = hasResource && title ? title : 'Atomic Data';
-  description =
+  const displayTitle = hasResource && title ? title : 'Atomic Data';
+  const displayDescription =
     hasResource && description
       ? description
       : 'The easiest way to create and share linked data.';
 
   return (
-    <Helmet>
-      <title>{title}</title>
-      <meta name='theme-color' content={darkMode ? 'black' : 'white'} />
+    <>
+      <title>{displayTitle}</title>
       <meta name='theme-color' content={darkMode ? 'black' : 'white'} />
       <meta
         name='apple-mobile-web-app-status-bar-style'
         content={darkMode ? 'black' : 'default'}
       />
       <meta name='msapplication-TileColor' content={mainColor} />
-      <meta name='description' content={description} />
-      <meta property='og:title' content={title} />
-      <meta property='og:description' content={description} />
+      <meta name='description' content={displayDescription} />
+      <meta property='og:title' content={displayTitle} />
+      <meta property='og:description' content={displayDescription} />
       <meta property='og:url' content={subject} />
-    </Helmet>
+    </>
   );
 }
diff --git a/browser/data-browser/src/components/NavBarSpacer.tsx b/browser/data-browser/src/components/NavBarSpacer.tsx
index 9f9286166..38273a3ac 100644
--- a/browser/data-browser/src/components/NavBarSpacer.tsx
+++ b/browser/data-browser/src/components/NavBarSpacer.tsx
@@ -1,6 +1,8 @@
 import { styled } from 'styled-components';
 import { useSettings } from '../helpers/AppSettings';
 
+import type { JSX } from 'react';
+
 const NAVBAR_HEIGHT = '2rem';
 const NAVBAR_CALC_PART = ` + ${NAVBAR_HEIGHT}`;
 
diff --git a/browser/data-browser/src/components/NavState.tsx b/browser/data-browser/src/components/NavState.tsx
new file mode 100644
index 000000000..643f8225d
--- /dev/null
+++ b/browser/data-browser/src/components/NavState.tsx
@@ -0,0 +1,56 @@
+import { createContext, useContext, useEffect, useState } from 'react';
+
+export type NavState = 'PUSH' | 'POP' | 'NONE';
+
+const NavStateContext = createContext<NavState>('PUSH');
+
+/** Tracks navigation to keep a record of the last navigation type.
+ * Useful if you need to know if the last navigation was a pop or push.
+ */
+export const NavStateProvider: React.FC<React.PropsWithChildren> = ({
+  children,
+}) => {
+  const [navState, setNavState] = useState<NavState>('PUSH');
+
+  useEffect(() => {
+    const handlePopState = () => {
+      setNavState('POP');
+    };
+
+    const oldPushState = window.history.pushState;
+
+    const handlePageShow = (event: PageTransitionEvent) => {
+      if (!event.persisted) {
+        setNavState('NONE');
+      }
+    };
+
+    window.addEventListener('popstate', handlePopState);
+    window.addEventListener('pageshow', handlePageShow);
+
+    // Modify the pushState function so we can track when it is called.
+    window.history.pushState = function (...args) {
+      setNavState('PUSH');
+      oldPushState.apply(this, args);
+    };
+
+    return () => {
+      window.removeEventListener('popstate', handlePopState);
+      window.removeEventListener('pageshow', handlePageShow);
+      window.history.pushState = oldPushState;
+    };
+  }, []);
+
+  return (
+    <NavStateContext.Provider value={navState}>
+      {children}
+    </NavStateContext.Provider>
+  );
+};
+
+/**
+ * Returns the last navigation type.
+ */
+export const useNavState = (): NavState => {
+  return useContext(NavStateContext);
+};
diff --git a/browser/data-browser/src/components/NavStyleButton.tsx b/browser/data-browser/src/components/NavStyleButton.tsx
index 4f3a0d12f..a5f1bca61 100644
--- a/browser/data-browser/src/components/NavStyleButton.tsx
+++ b/browser/data-browser/src/components/NavStyleButton.tsx
@@ -1,6 +1,8 @@
 import { styled } from 'styled-components';
 import { useSettings } from '../helpers/AppSettings';
 
+import type { JSX } from 'react';
+
 interface NavBarButtonProps {
   top: boolean;
   floating: boolean;
diff --git a/browser/data-browser/src/components/Navigation.tsx b/browser/data-browser/src/components/Navigation.tsx
index 1f3830a8a..9be4d92bd 100644
--- a/browser/data-browser/src/components/Navigation.tsx
+++ b/browser/data-browser/src/components/Navigation.tsx
@@ -1,7 +1,6 @@
 import * as React from 'react';
-import { useEffect } from 'react';
+import { type JSX } from 'react';
 import { FaArrowLeft, FaArrowRight, FaBars } from 'react-icons/fa';
-import { useLocation } from 'react-router-dom';
 import { styled } from 'styled-components';
 
 import { ButtonBar } from './Button';
@@ -13,7 +12,7 @@ import { shortcuts } from './HotKeyWrapper';
 import { NavBarSpacer } from './NavBarSpacer';
 import { Searchbar } from './Searchbar';
 import { useMediaQuery } from '../hooks/useMediaQuery';
-import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
+import { useBackForward } from '../hooks/useNavigateWithTransition';
 import { NAVBAR_TRANSITION_TAG } from '../helpers/transitionName';
 
 interface NavWrapperProps {
@@ -24,11 +23,6 @@ interface NavWrapperProps {
 export function NavWrapper({ children }: NavWrapperProps): JSX.Element {
   const { navbarTop, navbarFloating } = useSettings();
   const contentRef = React.useRef<HTMLDivElement>(null);
-  const location = useLocation();
-
-  useEffect(() => {
-    contentRef?.current?.scrollTo(0, 0);
-  }, [location]);
 
   return (
     <>
@@ -62,8 +56,9 @@ const Content = styled.div<ContentProps>`
 
 /** Persistently shown navigation bar */
 function NavBar(): JSX.Element {
+  const { back, forward } = useBackForward();
+
   const [subject] = useCurrentSubject();
-  const navigate = useNavigateWithTransition();
   const { navbarTop, navbarFloating, sideBarLocked, setSideBarLocked } =
     useSettings();
   const [showButtons, setShowButtons] = React.useState<boolean>(true);
@@ -110,18 +105,10 @@ function NavBar(): JSX.Element {
           </ButtonBar>
           {isInStandaloneMode && (
             <>
-              <ButtonBar
-                type='button'
-                title='Go back'
-                onClick={() => navigate(-1)}
-              >
+              <ButtonBar type='button' title='Go back' onClick={back}>
                 <FaArrowLeft />
               </ButtonBar>{' '}
-              <ButtonBar
-                type='button'
-                title='Go forward'
-                onClick={() => navigate(1)}
-              >
+              <ButtonBar type='button' title='Go forward' onClick={forward}>
                 <FaArrowRight />
               </ButtonBar>
             </>
diff --git a/browser/data-browser/src/components/NewInstanceButton/Base.tsx b/browser/data-browser/src/components/NewInstanceButton/Base.tsx
index 50c317d5a..918236295 100644
--- a/browser/data-browser/src/components/NewInstanceButton/Base.tsx
+++ b/browser/data-browser/src/components/NewInstanceButton/Base.tsx
@@ -1,12 +1,12 @@
 import { useStore } from '@tomic/react';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import toast from 'react-hot-toast';
 import { IconType } from 'react-icons';
 import { FaPlus } from 'react-icons/fa';
-import { useNavigate } from 'react-router-dom';
 import { styled } from 'styled-components';
 import { paths } from '../../routes/paths';
 import { Button } from '../Button';
+import { useNavigateWithTransition } from '../../hooks/useNavigateWithTransition';
 
 export interface InstanceButtonBaseProps {
   onClick: () => void;
@@ -31,7 +31,7 @@ export function Base({
   const store = useStore();
   const agent = store.getAgent();
 
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
 
   const handleClick = useCallback(() => {
     if (!agent) {
diff --git a/browser/data-browser/src/components/NewInstanceButton/NewInstanceButton.tsx b/browser/data-browser/src/components/NewInstanceButton/NewInstanceButton.tsx
index 9f2249e31..ebb852118 100644
--- a/browser/data-browser/src/components/NewInstanceButton/NewInstanceButton.tsx
+++ b/browser/data-browser/src/components/NewInstanceButton/NewInstanceButton.tsx
@@ -5,6 +5,8 @@ import { useNewResourceUI } from '../forms/NewForm/useNewResourceUI';
 import { Base } from './Base';
 import { IconType } from 'react-icons';
 
+import type { JSX } from 'react';
+
 interface NewInstanceButtonProps {
   /** URL of the Class to be instantiated */
   klass: string;
diff --git a/browser/data-browser/src/components/OutlinedSection.tsx b/browser/data-browser/src/components/OutlinedSection.tsx
index 2ab5b4a01..f1b61936d 100644
--- a/browser/data-browser/src/components/OutlinedSection.tsx
+++ b/browser/data-browser/src/components/OutlinedSection.tsx
@@ -1,4 +1,4 @@
-import { PropsWithChildren } from 'react';
+import { PropsWithChildren, type JSX } from 'react';
 import { Row } from './Row';
 import { styled } from 'styled-components';
 import { CurrentBackgroundColor } from '../globalCssVars';
diff --git a/browser/data-browser/src/components/PalettePicker.tsx b/browser/data-browser/src/components/PalettePicker.tsx
index 5ac05a91b..1ab763b96 100644
--- a/browser/data-browser/src/components/PalettePicker.tsx
+++ b/browser/data-browser/src/components/PalettePicker.tsx
@@ -2,6 +2,8 @@ import { styled } from 'styled-components';
 import { transition } from '../helpers/transition';
 import { Row } from './Row';
 
+import type { JSX } from 'react';
+
 interface PalettePickerProps {
   palette: string[];
   onChange: (color: string) => void;
diff --git a/browser/data-browser/src/components/Parent.tsx b/browser/data-browser/src/components/Parent.tsx
index f30310742..023283062 100644
--- a/browser/data-browser/src/components/Parent.tsx
+++ b/browser/data-browser/src/components/Parent.tsx
@@ -13,9 +13,11 @@ import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
 import { useSettings } from '../helpers/AppSettings';
 import { Button } from './Button';
 import { BREADCRUMB_BAR_TRANSITION_TAG } from '../helpers/transitionName';
-import ResourceContextMenu from './ResourceContextMenu';
+import { ResourceContextMenu } from './ResourceContextMenu';
 import { MenuBarDropdownTrigger } from './ResourceContextMenu/MenuBarDropdownTrigger';
 
+import type { JSX } from 'react';
+
 type ParentProps = {
   resource: Resource;
 };
diff --git a/browser/data-browser/src/components/Popover.tsx b/browser/data-browser/src/components/Popover.tsx
index 57f85bfca..cef298447 100644
--- a/browser/data-browser/src/components/Popover.tsx
+++ b/browser/data-browser/src/components/Popover.tsx
@@ -9,6 +9,7 @@ import {
   useContext,
   useEffect,
   useRef,
+  type JSX,
 } from 'react';
 import * as RadixPopover from '@radix-ui/react-popover';
 import { styled, keyframes } from 'styled-components';
@@ -87,11 +88,11 @@ const fadeIn = keyframes`
 `;
 
 const Content = styled(RadixPopover.Content)`
-  --popover-close-offset: ${p => p.theme.margin}rem;
+  --popover-close-offset: ${p => p.theme.size()};
   --popover-close-size: 25px;
   --popover-close-safe-area: calc(
     var(--popover-close-size) + (var(--popover-close-offset) * 2) -
-      ${p => p.theme.margin}rem
+      ${p => p.theme.size()}
   );
   background-color: ${p => transparentize(0.2, p.theme.colors.bgBody)};
   backdrop-filter: blur(10px);
@@ -110,16 +111,16 @@ const Arrow = styled(RadixPopover.Arrow)`
 `;
 
 const PopoverContainerContext =
-  createContext<RefObject<HTMLDivElement>>(createRef());
+  createContext<RefObject<HTMLDivElement | null>>(createRef());
 
 export const PopoverContainer: FC<PropsWithChildren> = ({ children }) => {
   const popoverContainerRef = useRef<HTMLDivElement>(null);
 
   return (
     <ContainerDiv ref={popoverContainerRef}>
-      <PopoverContainerContext.Provider value={popoverContainerRef}>
+      <PopoverContainerContext value={popoverContainerRef}>
         {children}
-      </PopoverContainerContext.Provider>
+      </PopoverContainerContext>
     </ContainerDiv>
   );
 };
diff --git a/browser/data-browser/src/components/PropVal.tsx b/browser/data-browser/src/components/PropVal.tsx
index bb3108984..ca0f88c20 100644
--- a/browser/data-browser/src/components/PropVal.tsx
+++ b/browser/data-browser/src/components/PropVal.tsx
@@ -8,6 +8,8 @@ import ValueComp from './ValueComp';
 import { ALL_PROPS_CONTAINER } from '../helpers/containers';
 import { LoaderInline } from './Loader';
 
+import type { JSX } from 'react';
+
 type Props = {
   propertyURL: string;
   resource: Resource;
diff --git a/browser/data-browser/src/components/ResourceContextMenu/MenuBarDropdownTrigger.tsx b/browser/data-browser/src/components/ResourceContextMenu/MenuBarDropdownTrigger.tsx
index 4498699da..2d0fee966 100644
--- a/browser/data-browser/src/components/ResourceContextMenu/MenuBarDropdownTrigger.tsx
+++ b/browser/data-browser/src/components/ResourceContextMenu/MenuBarDropdownTrigger.tsx
@@ -1,12 +1,13 @@
 import { FaEllipsisV } from 'react-icons/fa';
-import { DropdownTriggerRenderFunction } from '../Dropdown/DropdownTrigger';
+import { DropdownTriggerComponent } from '../Dropdown/DropdownTrigger';
 import { shortcuts } from '../HotKeyWrapper';
 import { IconButton } from '../IconButton/IconButton';
 
-export const MenuBarDropdownTrigger: DropdownTriggerRenderFunction = (
-  { onClick, menuId },
+export const MenuBarDropdownTrigger: DropdownTriggerComponent = ({
+  onClick,
+  menuId,
   ref,
-) => (
+}) => (
   <IconButton
     aria-controls={menuId}
     ref={ref}
diff --git a/browser/data-browser/src/components/ResourceContextMenu/index.tsx b/browser/data-browser/src/components/ResourceContextMenu/index.tsx
index 720f85626..00e1f8ea6 100644
--- a/browser/data-browser/src/components/ResourceContextMenu/index.tsx
+++ b/browser/data-browser/src/components/ResourceContextMenu/index.tsx
@@ -1,5 +1,4 @@
 import { useCallback, useState } from 'react';
-import { useLocation, useNavigate } from 'react-router-dom';
 import { Client, core, useCanWrite, useResource } from '@tomic/react';
 import {
   editURL,
@@ -13,7 +12,7 @@ import { DIVIDER, DropdownMenu, isItem, DropdownItem } from '../Dropdown';
 import toast from 'react-hot-toast';
 import { paths } from '../../routes/paths';
 import { shortcuts } from '../HotKeyWrapper';
-import { DropdownTriggerRenderFunction } from '../Dropdown/DropdownTrigger';
+import { DropdownTriggerComponent } from '../Dropdown/DropdownTrigger';
 import { buildDefaultTrigger } from '../Dropdown/DefaultTrigger';
 import {
   FaClock,
@@ -38,27 +37,31 @@ import { useCurrentSubject } from '../../helpers/useCurrentSubject';
 import { ResourceCodeUsageDialog } from '../../views/CodeUsage/ResourceCodeUsageDialog';
 import { useNewRoute } from '../../helpers/useNewRoute';
 import { addIf } from '../../helpers/addIf';
+import { useNavigateWithTransition } from '../../hooks/useNavigateWithTransition';
 
-export enum ContextMenuOptions {
-  View = 'view',
-  Data = 'data',
-  Edit = 'edit',
-  Scope = 'scope',
-  Share = 'share',
-  Delete = 'delete',
-  History = 'history',
-  Import = 'import',
-  UseInCode = 'useInCode',
-  NewChild = 'newChild',
-  Export = 'export',
-  Open = 'open',
-}
+export const ContextMenuOptions = {
+  View: 'view',
+  Data: 'data',
+  Edit: 'edit',
+  Scope: 'scope',
+  Share: 'share',
+  Delete: 'delete',
+  History: 'history',
+  Import: 'import',
+  UseInCode: 'useInCode',
+  NewChild: 'newChild',
+  Export: 'export',
+  Open: 'open',
+} as const;
+
+export type ContextMenuOptionsUnion =
+  (typeof ContextMenuOptions)[keyof typeof ContextMenuOptions];
 
 export interface ResourceContextMenuProps {
   subject: string;
   // If given only these options will appear in the list.
-  showOnly?: ContextMenuOptions[];
-  trigger?: DropdownTriggerRenderFunction;
+  showOnly?: ContextMenuOptionsUnion[];
+  trigger?: DropdownTriggerComponent;
   simple?: boolean;
   /** If it's the primary menu in the navbar. Used for triggering keyboard shortcut */
   isMainMenu?: boolean;
@@ -70,7 +73,7 @@ export interface ResourceContextMenuProps {
 }
 
 /** Dropdown menu that opens a bunch of actions for some resource */
-function ResourceContextMenu({
+export function ResourceContextMenu({
   subject,
   showOnly,
   trigger,
@@ -81,14 +84,14 @@ function ResourceContextMenu({
   bindActive,
   onAfterDelete,
 }: ResourceContextMenuProps) {
-  const navigate = useNavigate();
-  const location = useLocation();
+  const navigate = useNavigateWithTransition();
+  const location = window.location;
   const resource = useResource(subject);
   const [showDeleteDialog, setShowDeleteDialog] = useState(false);
   const [showCodeUsageDialog, setShowCodeUsageDialog] = useState(false);
   const handleAddClick = useNewRoute(subject);
   const [currentSubject] = useCurrentSubject();
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
   const { enableScope } = useQueryScopeHandler(subject);
   // Try to not have a useResource hook in here, as that will lead to many costly fetches when the user enters a new subject
 
@@ -214,7 +217,8 @@ function ResourceContextMenu({
   const filteredItems = showOnly
     ? items.filter(
         item =>
-          !isItem(item) || showOnly.includes(item.id as ContextMenuOptions),
+          !isItem(item) ||
+          showOnly.includes(item.id as ContextMenuOptionsUnion),
       )
     : items;
 
@@ -229,7 +233,7 @@ function ResourceContextMenu({
     <>
       <DropdownMenu
         items={filteredItems}
-        trigger={triggerComp}
+        Trigger={triggerComp}
         isMainMenu={isMainMenu}
         bindActive={bindActive}
       />
@@ -258,5 +262,3 @@ function ResourceContextMenu({
     </>
   );
 }
-
-export default ResourceContextMenu;
diff --git a/browser/data-browser/src/components/ResourceUsage/ChildrenUsage.tsx b/browser/data-browser/src/components/ResourceUsage/ChildrenUsage.tsx
index 1a38a6697..1e71d651a 100644
--- a/browser/data-browser/src/components/ResourceUsage/ChildrenUsage.tsx
+++ b/browser/data-browser/src/components/ResourceUsage/ChildrenUsage.tsx
@@ -2,6 +2,8 @@ import { Resource, properties, useCollection } from '@tomic/react';
 
 import { UsageCard } from './UsageCard';
 
+import type { JSX } from 'react';
+
 interface ChildrenUsageProps {
   resource: Resource;
 }
diff --git a/browser/data-browser/src/components/ResourceUsage/ClassUsage.tsx b/browser/data-browser/src/components/ResourceUsage/ClassUsage.tsx
index 1438c3368..b89e3813e 100644
--- a/browser/data-browser/src/components/ResourceUsage/ClassUsage.tsx
+++ b/browser/data-browser/src/components/ResourceUsage/ClassUsage.tsx
@@ -4,6 +4,8 @@ import { UsageCard } from './UsageCard';
 import { Column } from '../Row';
 import { ChildrenUsage } from './ChildrenUsage';
 
+import type { JSX } from 'react';
+
 interface ClassUsageProps {
   resource: Resource;
 }
diff --git a/browser/data-browser/src/components/ResourceUsage/PropertyUsage.tsx b/browser/data-browser/src/components/ResourceUsage/PropertyUsage.tsx
index 47e4c783d..47bbfc341 100644
--- a/browser/data-browser/src/components/ResourceUsage/PropertyUsage.tsx
+++ b/browser/data-browser/src/components/ResourceUsage/PropertyUsage.tsx
@@ -4,6 +4,8 @@ import { UsageCard } from './UsageCard';
 import { Column } from '../Row';
 import { ChildrenUsage } from './ChildrenUsage';
 
+import type { JSX } from 'react';
+
 interface PropertyUsageProps {
   resource: Resource;
 }
diff --git a/browser/data-browser/src/components/ResourceUsage/ResourceUsage.tsx b/browser/data-browser/src/components/ResourceUsage/ResourceUsage.tsx
index b78d12afc..695fc4720 100644
--- a/browser/data-browser/src/components/ResourceUsage/ResourceUsage.tsx
+++ b/browser/data-browser/src/components/ResourceUsage/ResourceUsage.tsx
@@ -6,6 +6,8 @@ import { ChildrenUsage } from './ChildrenUsage';
 import { Column } from '../Row';
 import { ReferenceUsage } from './ReferenceUsage';
 
+import type { JSX } from 'react';
+
 interface ResourceUsageProps {
   resource: Resource;
 }
diff --git a/browser/data-browser/src/components/ResourceUsage/UsageCard.tsx b/browser/data-browser/src/components/ResourceUsage/UsageCard.tsx
index e0910eae4..1860df1e9 100644
--- a/browser/data-browser/src/components/ResourceUsage/UsageCard.tsx
+++ b/browser/data-browser/src/components/ResourceUsage/UsageCard.tsx
@@ -4,7 +4,7 @@ import { styled } from 'styled-components';
 import { Details } from '../Details';
 import { UsageRow } from './UsageRow';
 import { Column, Row } from '../Row';
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { FaChevronLeft, FaChevronRight } from 'react-icons/fa6';
 import { IconButton } from '../IconButton/IconButton';
 
diff --git a/browser/data-browser/src/components/ResourceUsage/UsageRow.tsx b/browser/data-browser/src/components/ResourceUsage/UsageRow.tsx
index abd56541c..552adba6a 100644
--- a/browser/data-browser/src/components/ResourceUsage/UsageRow.tsx
+++ b/browser/data-browser/src/components/ResourceUsage/UsageRow.tsx
@@ -4,6 +4,8 @@ import { ResourceInline } from '../../views/ResourceInline';
 import { styled } from 'styled-components';
 import { ErrorLook } from '../ErrorLook';
 
+import type { JSX } from 'react';
+
 interface UsageRowProps {
   subject: string;
 }
diff --git a/browser/data-browser/src/components/Row.tsx b/browser/data-browser/src/components/Row.tsx
index 26f04cd04..97c83e63a 100644
--- a/browser/data-browser/src/components/Row.tsx
+++ b/browser/data-browser/src/components/Row.tsx
@@ -2,7 +2,7 @@ import { styled } from 'styled-components';
 import * as CSS from 'csstype';
 
 import { ButtonDefault } from './Button';
-import { forwardRef } from 'react';
+import { forwardRef, type JSX } from 'react';
 
 export interface FlexProps extends React.HTMLAttributes<HTMLDivElement> {
   gap?: CSS.Property.Gap;
diff --git a/browser/data-browser/src/components/ScrollArea.tsx b/browser/data-browser/src/components/ScrollArea.tsx
index dbd3d0d50..c50f10376 100644
--- a/browser/data-browser/src/components/ScrollArea.tsx
+++ b/browser/data-browser/src/components/ScrollArea.tsx
@@ -1,7 +1,7 @@
 import * as RadixScrollArea from '@radix-ui/react-scroll-area';
 import { styled } from 'styled-components';
 import { transparentize } from 'polished';
-import { forwardRef } from 'react';
+import { forwardRef, type JSX } from 'react';
 
 const SIZE = '0.8rem';
 
diff --git a/browser/data-browser/src/components/Searchbar.tsx b/browser/data-browser/src/components/Searchbar.tsx
index f303d8e18..a26b3abc7 100644
--- a/browser/data-browser/src/components/Searchbar.tsx
+++ b/browser/data-browser/src/components/Searchbar.tsx
@@ -1,21 +1,18 @@
 import { Client, useResource, useTitle } from '@tomic/react';
 import { transparentize } from 'polished';
-import React, { useEffect, useRef, useState } from 'react';
+import React, { useEffect, useRef, useState, type JSX } from 'react';
 import { useHotkeys } from 'react-hotkeys-hook';
 import { FaTimes } from 'react-icons/fa';
-import { useNavigate } from 'react-router';
 import { styled } from 'styled-components';
-import {
-  constructOpenURL,
-  searchURL,
-  useSearchQuery,
-} from '../helpers/navigation';
-import { useFocus } from '../helpers/useFocus';
+import { constructOpenURL } from '../helpers/navigation';
 import { useQueryScopeHandler } from '../hooks/useQueryScope';
 import { shortcuts } from './HotKeyWrapper';
 import { IconButton, IconButtonVariant } from './IconButton/IconButton';
 import { FaMagnifyingGlass } from 'react-icons/fa6';
 import { isURL } from '../helpers/isURL';
+import { useNavigate, useSearch } from '@tanstack/react-router';
+import { paths } from '../routes/paths';
+import { useCurrentSubject } from '../helpers/useCurrentSubject';
 
 export interface SearchbarProps {
   onFocus?: React.FocusEventHandler<HTMLInputElement>;
@@ -28,13 +25,37 @@ export function Searchbar({
   onBlur,
   subject,
 }: SearchbarProps): JSX.Element {
-  const [input, setInput] = useState<string | undefined>('');
-  const [query] = useSearchQuery();
+  const [currentSubject] = useCurrentSubject();
+  const { query } = useSearch({ strict: false });
+  const [input, setInput] = useState<string>(currentSubject ?? query ?? '');
   const { scope, clearScope } = useQueryScopeHandler();
   const searchBarRef = useRef<HTMLFormElement>(null);
-  const [inputRef, setInputFocus] = useFocus();
+  const inputRef = useRef<HTMLInputElement>(null);
+
   const navigate = useNavigate();
 
+  const setQuery = useDebouncedCallback((q: string) => {
+    try {
+      Client.tryValidSubject(q);
+      // Replace instead of push to make the back-button behavior better.
+      navigate({ to: constructOpenURL(q), replace: true });
+    } catch (_err) {
+      navigate({
+        to: paths.search,
+        search: {
+          query: q,
+          ...(scope ? { queryscope: scope } : {}),
+        },
+        replace: true,
+      });
+    }
+  }, 20);
+
+  const handleInput = (q: string) => {
+    setInput(q);
+    setQuery(q);
+  };
+
   const handleSelect: React.MouseEventHandler<HTMLInputElement> = e => {
     if (isURL(input ?? '')) {
       // @ts-ignore
@@ -42,49 +63,36 @@ export function Searchbar({
     }
   };
 
-  const handleChange: React.ChangeEventHandler<HTMLInputElement> = e => {
-    setInput(e.target.value);
-
-    try {
-      Client.tryValidSubject(e.target.value);
-      // Replace instead of push to make the back-button behavior better.
-      navigate(constructOpenURL(e.target.value), { replace: true });
-    } catch (_err) {
-      navigate(searchURL(e.target.value, scope), { replace: true });
-    }
-  };
-
   const handleSubmit: React.FormEventHandler<HTMLFormElement> = event => {
     if (!subject) {
       return;
     }
 
     event.preventDefault();
-    //@ts-ignore this does seem callable
-    inputRef.current.blur();
-    //@ts-ignore this does seem callable
-    document.activeElement.blur();
-    navigate(constructOpenURL(subject));
+
+    inputRef.current?.blur();
+    //@ts-expect-error This should work
+    document.activeElement?.blur();
+    navigate({ to: constructOpenURL(subject), replace: true });
   };
 
   const onSearchButtonClick = () => {
-    navigate(searchURL('', scope), { replace: true });
-    setInputFocus();
+    navigate({ to: paths.search });
+    inputRef.current?.focus();
   };
 
   useHotkeys(shortcuts.search, e => {
     e.preventDefault();
-    //@ts-ignore this does seem callable
-    inputRef.current.select();
-    setInputFocus();
+
+    inputRef.current?.select();
+    inputRef.current?.focus();
   });
 
   useHotkeys(
     'esc',
     e => {
       e.preventDefault();
-      //@ts-ignore this does seem callable
-      inputRef.current.blur();
+      inputRef.current?.blur();
     },
     { enableOnTags: ['INPUT'] },
   );
@@ -102,16 +110,24 @@ export function Searchbar({
   );
 
   useEffect(() => {
-    if (query) {
-      setInput(query);
-    } else {
-      setInput(subject);
+    if (query !== undefined) {
+      return;
+    }
+
+    if (scope !== undefined) {
+      setInput('');
+
+      return;
     }
 
-    if (query || scope) {
-      setInputFocus();
+    if (currentSubject) {
+      setInput(currentSubject);
+
+      return;
     }
-  }, [query, scope, subject]);
+
+    setInput('');
+  }, [query, scope, currentSubject]);
 
   return (
     <Form onSubmit={handleSubmit} autoComplete='off' ref={searchBarRef}>
@@ -126,7 +142,6 @@ export function Searchbar({
       {scope && <ParentTag subject={scope} onClick={clearScope} />}
       <Input
         autoComplete='false'
-        // @ts-ignore this seems to work fine
         ref={inputRef}
         type='search'
         data-test='address-bar'
@@ -136,13 +151,32 @@ export function Searchbar({
         onFocus={onFocus}
         onBlur={onBlur}
         value={input || ''}
-        onChange={handleChange}
+        onChange={e => handleInput(e.target.value)}
         placeholder='Enter an Atomic URL or search   (press "/" )'
       />
     </Form>
   );
 }
 
+function useDebouncedCallback(
+  callback: (query: string) => void,
+  timeout: number,
+): (query: string) => void {
+  const timeoutId = useRef<ReturnType<typeof setTimeout>>(undefined);
+
+  const cb = (query: string) => {
+    if (timeoutId.current) {
+      clearTimeout(timeoutId.current);
+    }
+
+    timeoutId.current = setTimeout(async () => {
+      callback(query);
+    }, timeout);
+  };
+
+  return cb;
+}
+
 interface ParentTagProps {
   subject: string;
   onClick: () => void;
@@ -161,6 +195,7 @@ function ParentTag({ subject, onClick }: ParentTagProps): JSX.Element {
         variant={IconButtonVariant.Fill}
         color='textLight'
         size='0.8rem'
+        type='button'
       >
         <FaTimes />
       </IconButton>
diff --git a/browser/data-browser/src/components/Shortcut.tsx b/browser/data-browser/src/components/Shortcut.tsx
index c642c9923..71f5fdf1e 100644
--- a/browser/data-browser/src/components/Shortcut.tsx
+++ b/browser/data-browser/src/components/Shortcut.tsx
@@ -1,4 +1,4 @@
-import { Fragment } from 'react';
+import { Fragment, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { displayShortcut } from './HotKeyWrapper';
 
diff --git a/browser/data-browser/src/components/SideBar/About.tsx b/browser/data-browser/src/components/SideBar/About.tsx
index bfbe63414..bc0651671 100644
--- a/browser/data-browser/src/components/SideBar/About.tsx
+++ b/browser/data-browser/src/components/SideBar/About.tsx
@@ -4,6 +4,7 @@ import { FaGithub, FaDiscord, FaBook } from 'react-icons/fa';
 import { IconButtonLink, IconButtonVariant } from '../IconButton/IconButton';
 import { FaRadiation } from 'react-icons/fa6';
 import { isDev } from '../../config';
+import { paths } from '../../routes/paths';
 
 interface AboutItem {
   icon: React.ReactNode;
@@ -49,7 +50,7 @@ export function About() {
         ))}
         {isDev() && (
           <IconButtonLink
-            href='/sandbox'
+            href={paths.sandbox}
             title='Sandbox, test components in isolation'
             size='1.2em'
             color='textLight'
diff --git a/browser/data-browser/src/components/SideBar/AppMenu.tsx b/browser/data-browser/src/components/SideBar/AppMenu.tsx
index c108ee548..5c704e7f2 100644
--- a/browser/data-browser/src/components/SideBar/AppMenu.tsx
+++ b/browser/data-browser/src/components/SideBar/AppMenu.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useRef, useState, type JSX } from 'react';
 import {
   FaCog,
   FaInfo,
@@ -77,7 +77,7 @@ export function AppMenu({ onItemClick }: AppMenuProps): JSX.Element {
         icon={<FaCog />}
         label='Settings'
         helper='Change client settings (t)'
-        path={paths.themeSettings}
+        path={paths.appSettings}
         onClick={onItemClick}
       />
       <SideBarMenuItem
diff --git a/browser/data-browser/src/components/SideBar/DriveSwitcher.tsx b/browser/data-browser/src/components/SideBar/DriveSwitcher.tsx
index 6d4ba73c7..9c642d60e 100644
--- a/browser/data-browser/src/components/SideBar/DriveSwitcher.tsx
+++ b/browser/data-browser/src/components/SideBar/DriveSwitcher.tsx
@@ -7,7 +7,6 @@ import {
   FaRegCheckCircle,
   FaRegCircle,
 } from 'react-icons/fa';
-import { useNavigate } from 'react-router-dom';
 import { useSettings } from '../../helpers/AppSettings';
 import { constructOpenURL } from '../../helpers/navigation';
 import { useDriveHistory } from '../../hooks/useDriveHistory';
@@ -16,6 +15,7 @@ import { paths } from '../../routes/paths';
 import { DIVIDER, DropdownMenu } from '../Dropdown';
 import { buildDefaultTrigger } from '../Dropdown/DefaultTrigger';
 import { useNewResourceUI } from '../forms/NewForm/useNewResourceUI';
+import { useNavigateWithTransition } from '../../hooks/useNavigateWithTransition';
 
 const Trigger = buildDefaultTrigger(<FaHdd />, 'Open Drive Settings');
 
@@ -30,7 +30,7 @@ function dedupeAFromB<K, V>(a: Map<K, V>, b: Map<K, V>): Map<K, V> {
 }
 
 export function DriveSwitcher() {
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
   const { drive, setDrive, agent } = useSettings();
   const [savedDrives] = useSavedDrives();
   const [history, addToHistory] = useDriveHistory(savedDrives, 5);
@@ -94,5 +94,5 @@ export function DriveSwitcher() {
     [savedDrivesMap, drive, historyMap, agent],
   );
 
-  return <DropdownMenu trigger={Trigger} items={items} />;
+  return <DropdownMenu Trigger={Trigger} items={items} />;
 }
diff --git a/browser/data-browser/src/components/SideBar/OntologySideBar/OntologiesPanel.tsx b/browser/data-browser/src/components/SideBar/OntologySideBar/OntologiesPanel.tsx
index 006fa4748..b87f78332 100644
--- a/browser/data-browser/src/components/SideBar/OntologySideBar/OntologiesPanel.tsx
+++ b/browser/data-browser/src/components/SideBar/OntologySideBar/OntologiesPanel.tsx
@@ -12,7 +12,7 @@ import { AtomicLink } from '../../AtomicLink';
 import { getIconForClass } from '../../../helpers/iconMap';
 import { ScrollArea } from '../../ScrollArea';
 import { ErrorLook } from '../../ErrorLook';
-import { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState, type JSX } from 'react';
 import { useSettings } from '../../../helpers/AppSettings';
 
 export function OntologiesPanel(): JSX.Element | null {
diff --git a/browser/data-browser/src/components/SideBar/OverlapSpacer.tsx b/browser/data-browser/src/components/SideBar/OverlapSpacer.tsx
index 378ba9c12..61cd78c99 100644
--- a/browser/data-browser/src/components/SideBar/OverlapSpacer.tsx
+++ b/browser/data-browser/src/components/SideBar/OverlapSpacer.tsx
@@ -3,6 +3,8 @@ import { useSettings } from '../../helpers/AppSettings';
 import { styled } from 'styled-components';
 import { transition } from '../../helpers/transition';
 
+import type { JSX } from 'react';
+
 export function OverlapSpacer(): JSX.Element {
   const narrow = useMediaQuery('(max-width: 950px)');
   const { navbarFloating } = useSettings();
diff --git a/browser/data-browser/src/components/SideBar/ResourceSideBar/DropEdge.tsx b/browser/data-browser/src/components/SideBar/ResourceSideBar/DropEdge.tsx
index 8c860198b..6c095fd45 100644
--- a/browser/data-browser/src/components/SideBar/ResourceSideBar/DropEdge.tsx
+++ b/browser/data-browser/src/components/SideBar/ResourceSideBar/DropEdge.tsx
@@ -25,7 +25,7 @@ export function DropEdge({
 
   const parentResource = useResource(parent);
 
-  const [canWrite] = useCanWrite(parentResource);
+  const canWrite = useCanWrite(parentResource);
   useDndMonitor({
     onDragStart: event => setDraggingSubject(event.active.id as string),
     onDragEnd: () => setDraggingSubject(undefined),
diff --git a/browser/data-browser/src/components/SideBar/ResourceSideBar/FloatingActions.tsx b/browser/data-browser/src/components/SideBar/ResourceSideBar/FloatingActions.tsx
index 06b35ec3d..5f0077c76 100644
--- a/browser/data-browser/src/components/SideBar/ResourceSideBar/FloatingActions.tsx
+++ b/browser/data-browser/src/components/SideBar/ResourceSideBar/FloatingActions.tsx
@@ -1,8 +1,8 @@
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { FaEllipsisVertical } from 'react-icons/fa6';
 import { styled, css } from 'styled-components';
 import { buildDefaultTrigger } from '../../Dropdown/DefaultTrigger';
-import ResourceContextMenu from '../../ResourceContextMenu';
+import { ResourceContextMenu } from '../../ResourceContextMenu';
 
 export interface FloatingActionsProps {
   subject: string;
diff --git a/browser/data-browser/src/components/SideBar/ResourceSideBar/ResourceSideBar.tsx b/browser/data-browser/src/components/SideBar/ResourceSideBar/ResourceSideBar.tsx
index 9dda134f5..33cec0a1e 100644
--- a/browser/data-browser/src/components/SideBar/ResourceSideBar/ResourceSideBar.tsx
+++ b/browser/data-browser/src/components/SideBar/ResourceSideBar/ResourceSideBar.tsx
@@ -27,7 +27,7 @@ import { transition } from '../../../helpers/transition';
 
 interface ResourceSideBarProps {
   subject: string;
-  renderedHierargy: string[];
+  renderedHierarchy: string[];
   ancestry: string[];
   /** When a SideBar item is clicked, we should close the SideBar (on mobile devices) */
   onClick?: () => unknown;
@@ -36,19 +36,19 @@ interface ResourceSideBarProps {
 /** Renders a Resource as a nav item for in the sidebar. */
 export const ResourceSideBar: React.FC<ResourceSideBarProps> = ({
   subject,
-  renderedHierargy,
+  renderedHierarchy,
   ancestry,
   onClick,
 }) => {
-  if (renderedHierargy.length === 0) {
-    throw new Error('renderedHierargy should not be empty');
+  if (renderedHierarchy.length === 0) {
+    throw new Error('renderedHierarchy should not be empty');
   }
 
   const resource = useResource(subject, { allowIncomplete: true });
   const [currentUrl] = useCurrentSubject();
   const [title] = useTitle(resource);
   const [description] = useString(resource, core.properties.description);
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
   const active = currentUrl === subject;
   const [open, setOpen] = useState(active);
 
@@ -58,7 +58,7 @@ export const ResourceSideBar: React.FC<ResourceSideBarProps> = ({
   );
 
   const dragData: SideBarDragData = {
-    renderedUnder: renderedHierargy.at(-1)!,
+    renderedUnder: renderedHierarchy.at(-1)!,
   };
 
   const {
@@ -80,8 +80,8 @@ export const ResourceSideBar: React.FC<ResourceSideBarProps> = ({
         active={active}
         onClick={onClick}
         ref={setNodeRef}
-        listeners={listeners}
-        attributes={attributes}
+        listeners={canWrite ? listeners : undefined}
+        attributes={canWrite ? attributes : undefined}
       />
     ),
     [subject, active, onClick, description, title, listeners, attributes],
@@ -90,7 +90,7 @@ export const ResourceSideBar: React.FC<ResourceSideBarProps> = ({
   const hasSubResources = subResources.length > 0;
   const isDragging = draggingNode?.id === subject;
   const isHoveringOver = over?.data.current?.parent === subject;
-  const hierarchyWithItself = [...renderedHierargy, subject];
+  const hierarchyWithItself = [...renderedHierarchy, subject];
 
   useEffect(() => {
     if (isDragging) {
@@ -102,7 +102,7 @@ export const ResourceSideBar: React.FC<ResourceSideBarProps> = ({
     if (ancestry.includes(subject) && ancestry[0] !== subject) {
       setOpen(true);
     }
-  }, [ancestry]);
+  }, [ancestry, subject]);
 
   if (!subject || subject === unknownSubject) {
     return null;
@@ -150,7 +150,7 @@ export const ResourceSideBar: React.FC<ResourceSideBarProps> = ({
             <Fragment key={child}>
               <ResourceSideBar
                 subject={child}
-                renderedHierargy={hierarchyWithItself}
+                renderedHierarchy={hierarchyWithItself}
                 ancestry={ancestry}
                 onClick={onClick}
               />
diff --git a/browser/data-browser/src/components/SideBar/ResourceSideBar/SidebarItemTitle.tsx b/browser/data-browser/src/components/SideBar/ResourceSideBar/SidebarItemTitle.tsx
index 3c906d02e..aa484b2b3 100644
--- a/browser/data-browser/src/components/SideBar/ResourceSideBar/SidebarItemTitle.tsx
+++ b/browser/data-browser/src/components/SideBar/ResourceSideBar/SidebarItemTitle.tsx
@@ -66,6 +66,7 @@ export const SidebarItemTitle = forwardRef<
                   title={`Rearange ${resource.title}`}
                   {...(listeners ?? {})}
                   {...(attributes ?? {})}
+                  role='link'
                 >
                   <Icon />
                   <FaGripVertical />
diff --git a/browser/data-browser/src/components/SideBar/SideBarDrive.tsx b/browser/data-browser/src/components/SideBar/SideBarDrive.tsx
index d952731ce..56f5ec30f 100644
--- a/browser/data-browser/src/components/SideBar/SideBarDrive.tsx
+++ b/browser/data-browser/src/components/SideBar/SideBarDrive.tsx
@@ -6,9 +6,8 @@ import {
   useStore,
   useTitle,
 } from '@tomic/react';
-import { Fragment, useEffect, useState } from 'react';
+import { Fragment, useEffect, useState, type JSX } from 'react';
 import { FaPlus } from 'react-icons/fa6';
-import { useNavigate } from 'react-router-dom';
 import { styled } from 'styled-components';
 import { useSettings } from '../../helpers/AppSettings';
 import { constructOpenURL } from '../../helpers/navigation';
@@ -27,6 +26,7 @@ import { SidebarItemTitle } from './ResourceSideBar/SidebarItemTitle';
 import { DropEdge } from './ResourceSideBar/DropEdge';
 import { createPortal } from 'react-dom';
 import { transition } from '../../helpers/transition';
+import { useNavigateWithTransition } from '../../hooks/useNavigateWithTransition';
 
 interface SideBarDriveProps {
   onItemClick: () => unknown;
@@ -55,8 +55,8 @@ export function SideBarDrive({
     dataBrowser.properties.subResources,
   );
   const [title] = useTitle(driveResource);
-  const navigate = useNavigate();
-  const [agentCanWrite] = useCanWrite(driveResource);
+  const navigate = useNavigateWithTransition();
+  const agentCanWrite = useCanWrite(driveResource);
   const [currentSubject] = useCurrentSubject();
   const currentResource = useResource(currentSubject);
   const [ancestry, setAncestry] = useState<string[]>([]);
@@ -107,7 +107,7 @@ export function SideBarDrive({
                   <Fragment key={child}>
                     <ResourceSideBar
                       subject={child}
-                      renderedHierargy={[drive]}
+                      renderedHierarchy={[drive]}
                       ancestry={ancestry}
                       onClick={onItemClick}
                     />
diff --git a/browser/data-browser/src/components/SideBar/SideBarPanel.tsx b/browser/data-browser/src/components/SideBar/SideBarPanel.tsx
index ed7b279d2..2b0f21f70 100644
--- a/browser/data-browser/src/components/SideBar/SideBarPanel.tsx
+++ b/browser/data-browser/src/components/SideBar/SideBarPanel.tsx
@@ -2,7 +2,7 @@ import { styled } from 'styled-components';
 import { Collapse } from '../Collapse';
 import { FaCaretRight } from 'react-icons/fa';
 import { transition } from '../../helpers/transition';
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 
 interface SideBarPanelProps {
   title: string;
diff --git a/browser/data-browser/src/components/SideBar/index.tsx b/browser/data-browser/src/components/SideBar/index.tsx
index d6a5c054e..0c1c18236 100644
--- a/browser/data-browser/src/components/SideBar/index.tsx
+++ b/browser/data-browser/src/components/SideBar/index.tsx
@@ -15,6 +15,7 @@ import { OntologiesPanel } from './OntologySideBar/OntologiesPanel';
 import { SideBarPanel } from './SideBarPanel';
 import { Panel, usePanelList } from './usePanelList';
 import { SIDEBAR_WIDTH_PROP } from './SidebarCSSVars';
+import { useRef, type JSX } from 'react';
 
 /** Amount of pixels where the sidebar automatically shows */
 export const SIDEBAR_TOGGLE_WIDTH = 600;
@@ -22,6 +23,7 @@ export const SIDEBAR_TOGGLE_WIDTH = 600;
 const SideBarDriveMemo = React.memo(SideBarDrive);
 
 export function SideBar(): JSX.Element {
+  const targetRef = useRef<HTMLDivElement>(null);
   const [isRearanging, setIsRearanging] = React.useState(false);
 
   const { drive, sideBarLocked, setSideBarLocked } = useSettings();
@@ -32,12 +34,12 @@ export function SideBar(): JSX.Element {
     true,
   );
 
-  const { size, targetRef, dragAreaRef, isDragging, dragAreaListeners } =
-    useResizable({
-      initialSize: 300,
-      minSize: 200,
-      maxSize: 2000,
-    });
+  const { size, dragAreaRef, isDragging, dragAreaListeners } = useResizable({
+    initialSize: 300,
+    minSize: 200,
+    maxSize: 2000,
+    targetRef,
+  });
 
   const { enabledPanels } = usePanelList();
 
@@ -58,8 +60,7 @@ export function SideBar(): JSX.Element {
 
   return (
     <SideBarContainer>
-      {/* @ts-ignore */}
-      <SideBarStyled
+      <StyledNav
         ref={mountRefs}
         size={size}
         data-testid='sidebar'
@@ -98,7 +99,7 @@ export function SideBar(): JSX.Element {
             {...dragAreaListeners}
           />
         )}
-      </SideBarStyled>
+      </StyledNav>
       <SideBarOverlay
         onClick={() => setSideBarLocked(false)}
         visible={sideBarLocked && !isWideScreen}
@@ -107,7 +108,7 @@ export function SideBar(): JSX.Element {
   );
 }
 
-interface SideBarStyledProps {
+interface StyledNavProps {
   locked: boolean;
   exposed: boolean;
   size: string;
@@ -117,11 +118,10 @@ interface SideBarOverlayProps {
   visible: boolean;
 }
 
-//@ts-ignore
-const SideBarStyled = styled.nav.attrs<SideBarStyledProps>(p => ({
+const StyledNav = styled.nav.attrs<StyledNavProps>(p => ({
   style: {
     [SIDEBAR_WIDTH_PROP]: p.size,
-  },
+  } as Record<string, string>,
 }))`
   z-index: ${p => p.theme.zIndex.sidebar};
   box-sizing: border-box;
diff --git a/browser/data-browser/src/components/SignInButton.tsx b/browser/data-browser/src/components/SignInButton.tsx
index 5c1b55d04..d9bf18c6e 100644
--- a/browser/data-browser/src/components/SignInButton.tsx
+++ b/browser/data-browser/src/components/SignInButton.tsx
@@ -1,13 +1,13 @@
-import { useNavigate } from 'react-router-dom';
 import { paths } from '../routes/paths';
 import { Button } from './Button';
+import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
 
 /**
  * Button that currently links to the Agent Settings page. Should probably open
  * in a Modal.
  */
 export function SignInButton() {
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
 
   return (
     <Button
diff --git a/browser/data-browser/src/components/SkipNav.tsx b/browser/data-browser/src/components/SkipNav.tsx
index fd23718a5..285cea5a5 100644
--- a/browser/data-browser/src/components/SkipNav.tsx
+++ b/browser/data-browser/src/components/SkipNav.tsx
@@ -1,5 +1,7 @@
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 export function SkipNav(): JSX.Element {
   return <SkipLink href='#skip-to-content'>Skip Navigation?</SkipLink>;
 }
diff --git a/browser/data-browser/src/components/Table.tsx b/browser/data-browser/src/components/Table.tsx
index d97f850be..4e5d8d79a 100644
--- a/browser/data-browser/src/components/Table.tsx
+++ b/browser/data-browser/src/components/Table.tsx
@@ -11,7 +11,7 @@ import { useSubjectParam } from '../helpers/useCurrentSubject';
 import { FaSort, FaSortDown, FaSortUp } from 'react-icons/fa';
 import { Button } from './Button';
 import { ValueForm } from './forms/ValueForm';
-import { memo } from 'react';
+import { memo, type JSX } from 'react';
 
 type TableProps = {
   /** A Collection Resource with a filter-value set */
diff --git a/browser/data-browser/src/components/TableEditor/ActiveCellIndicator.tsx b/browser/data-browser/src/components/TableEditor/ActiveCellIndicator.tsx
index aa82e4e05..2d74d7db6 100644
--- a/browser/data-browser/src/components/TableEditor/ActiveCellIndicator.tsx
+++ b/browser/data-browser/src/components/TableEditor/ActiveCellIndicator.tsx
@@ -1,5 +1,5 @@
 import { transparentize } from 'polished';
-import { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState, type JSX } from 'react';
 import { styled } from 'styled-components';
 import {
   getHeight,
@@ -17,7 +17,7 @@ type OnScrollCallbackOptions = {
 
 export interface ActiveCellIndicatorProps {
   sizeStr: string;
-  scrollerRef: React.RefObject<HTMLDivElement>;
+  scrollerRef: React.RefObject<HTMLDivElement | null>;
   setOnScroll: (
     onScroll: ({ scrollUpdateWasRequested }: OnScrollCallbackOptions) => void,
   ) => void;
@@ -29,7 +29,7 @@ const cursorGoesOffscreen = (parentRect: DOMRect, childRect: DOMRect) => {
 
 const getCornerIfMultiSelect = (
   cursorMode: CursorMode,
-  ref: React.MutableRefObject<HTMLDivElement | null>,
+  ref: React.RefObject<HTMLDivElement | null>,
 ) => {
   if (cursorMode === CursorMode.MultiSelect && ref.current) {
     return ref.current.getBoundingClientRect();
@@ -68,7 +68,7 @@ export function ActiveCellIndicator({
 
   /** Measure the size and position of the current active cell and morph the indicator to the same values. */
   const updatePosition = useCallback(
-    (followHorizontaly = true) => {
+    (followHorizontally = true) => {
       if (!activeCellRef.current || !scrollerRef.current) {
         setVisible(false);
 
@@ -83,7 +83,7 @@ export function ActiveCellIndicator({
         multiSelectCornerCellRef,
       );
 
-      if (followHorizontaly && cursorGoesOffscreen(scrollerRect, cellRect)) {
+      if (followHorizontally && cursorGoesOffscreen(scrollerRect, cellRect)) {
         setTransitioningOffscreen(true);
 
         scrollIntoView(scrollerRef.current, scrollerRect, cellRect);
diff --git a/browser/data-browser/src/components/TableEditor/Cell.tsx b/browser/data-browser/src/components/TableEditor/Cell.tsx
index 3f1568470..984235cb0 100644
--- a/browser/data-browser/src/components/TableEditor/Cell.tsx
+++ b/browser/data-browser/src/components/TableEditor/Cell.tsx
@@ -4,6 +4,7 @@ import {
   useLayoutEffect,
   useRef,
   useState,
+  type JSX,
 } from 'react';
 import { styled } from 'styled-components';
 import {
@@ -61,8 +62,8 @@ export function Cell({
     cursorMode,
     setActiveCell,
     setMultiSelectCorner,
-    activeCellRef,
-    multiSelectCornerCellRef,
+    updateActiveCellRef,
+    updateMultiSelectCornerCellRef,
     setCursorMode,
     registerEventListener,
     disabledKeyboardInteractions,
@@ -162,7 +163,7 @@ export function Cell({
     }
 
     if (isActiveCorner) {
-      multiSelectCornerCellRef.current = ref.current;
+      updateMultiSelectCornerCellRef(ref.current);
     }
   }, [isActiveCorner]);
 
@@ -176,7 +177,7 @@ export function Cell({
         ref.current.focus({ preventScroll: true });
       }
 
-      activeCellRef.current = ref.current;
+      updateActiveCellRef(ref.current);
 
       const unregisters = [
         registerEventListener(
@@ -199,7 +200,12 @@ export function Cell({
         }
       };
     }
-  }, [isActive, onEnterEditModeWithCharacter, onEditNextRow]);
+  }, [
+    isActive,
+    onEnterEditModeWithCharacter,
+    onEditNextRow,
+    updateActiveCellRef,
+  ]);
 
   return (
     <CellWrapper
diff --git a/browser/data-browser/src/components/TableEditor/TableEditor.tsx b/browser/data-browser/src/components/TableEditor/TableEditor.tsx
index ca71b14bd..3f8bf0806 100644
--- a/browser/data-browser/src/components/TableEditor/TableEditor.tsx
+++ b/browser/data-browser/src/components/TableEditor/TableEditor.tsx
@@ -5,6 +5,7 @@ import {
   useMemo,
   useRef,
   useState,
+  type JSX,
 } from 'react';
 import { styled } from 'styled-components';
 import { FixedSizeList, ListOnScrollProps } from 'react-window';
diff --git a/browser/data-browser/src/components/TableEditor/TableEditorContext.tsx b/browser/data-browser/src/components/TableEditor/TableEditorContext.tsx
index 7bae3e82f..23944fbd6 100644
--- a/browser/data-browser/src/components/TableEditor/TableEditorContext.tsx
+++ b/browser/data-browser/src/components/TableEditor/TableEditorContext.tsx
@@ -6,6 +6,7 @@ import {
   createContext,
   useContext,
   ReactElement,
+  type JSX,
 } from 'react';
 import { FixedSizeList } from 'react-window';
 import { EventManager } from '../../helpers/EventManager';
@@ -38,7 +39,7 @@ function emptySetState<T>(_: T | ((__: T) => T)): undefined {
 export interface TableEditorContext {
   mouseDown: boolean;
   setMouseDown: React.Dispatch<React.SetStateAction<boolean>>;
-  tableRef: React.MutableRefObject<HTMLDivElement | null>;
+  tableRef: React.RefObject<HTMLDivElement | null>;
   disabledKeyboardInteractions: Set<KeyboardInteraction>;
   setDisabledKeyboardInteractions: React.Dispatch<
     React.SetStateAction<Set<KeyboardInteraction>>
@@ -54,11 +55,13 @@ export interface TableEditorContext {
     row: number | undefined,
     column: number | undefined,
   ) => void;
-  activeCellRef: React.MutableRefObject<HTMLDivElement | null>;
-  multiSelectCornerCellRef: React.MutableRefObject<HTMLDivElement | null>;
+  activeCellRef: React.RefObject<HTMLDivElement | null>;
+  updateActiveCellRef: (newValue: HTMLDivElement | null) => void;
+  multiSelectCornerCellRef: React.RefObject<HTMLDivElement | null>;
+  updateMultiSelectCornerCellRef: (newValue: HTMLDivElement | null) => void;
   isDragging: boolean;
   setIsDragging: React.Dispatch<React.SetStateAction<boolean>>;
-  listRef: React.MutableRefObject<FixedSizeList | null>;
+  listRef: React.RefObject<FixedSizeList | null>;
   cursorMode: CursorMode;
   setCursorMode: React.Dispatch<React.SetStateAction<CursorMode>>;
   clearCell: () => void;
@@ -88,7 +91,9 @@ const initial: TableEditorContext = {
   setIndicatorHidden: emptySetState,
   setMultiSelectCorner: () => undefined,
   activeCellRef: { current: null },
+  updateActiveCellRef: () => undefined,
   multiSelectCornerCellRef: { current: null },
+  updateMultiSelectCornerCellRef: () => undefined,
   isDragging: false,
   setIsDragging: emptySetState,
   listRef: { current: null },
@@ -135,8 +140,20 @@ export function TableEditorContextProvider({
   );
 
   const activeCellRef = useRef<HTMLDivElement | null>(null);
+
+  const updateActiveCellRef = useCallback((newValue: HTMLDivElement | null) => {
+    activeCellRef.current = newValue;
+  }, []);
+
   const multiSelectCornerCellRef = useRef<HTMLDivElement | null>(null);
 
+  const updateMultiSelectCornerCellRef = useCallback(
+    (newValue: HTMLDivElement | null) => {
+      multiSelectCornerCellRef.current = newValue;
+    },
+    [],
+  );
+
   const setActiveCell = useCallback(
     (row: number | undefined, column: number | undefined) => {
       setSelectedRow(row);
@@ -194,7 +211,9 @@ export function TableEditorContextProvider({
       setActiveCell,
       setMultiSelectCorner,
       activeCellRef,
+      updateActiveCellRef,
       multiSelectCornerCellRef,
+      updateMultiSelectCornerCellRef,
       isDragging,
       setIsDragging,
       listRef,
@@ -217,6 +236,8 @@ export function TableEditorContextProvider({
       indicatorHidden,
       setActiveCell,
       setMultiSelectCorner,
+      updateActiveCellRef,
+      updateMultiSelectCornerCellRef,
       isDragging,
       cursorMode,
       emitInteractionsFired,
diff --git a/browser/data-browser/src/components/TableEditor/TableHeader.tsx b/browser/data-browser/src/components/TableEditor/TableHeader.tsx
index 081202cf1..404fcb3b2 100644
--- a/browser/data-browser/src/components/TableEditor/TableHeader.tsx
+++ b/browser/data-browser/src/components/TableEditor/TableHeader.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useState } from 'react';
+import { useCallback, useState, type JSX } from 'react';
 import { styled } from 'styled-components';
 import {
   TableHeading,
@@ -55,6 +55,8 @@ export function TableHeader<T>({
       const key = columns.map(columnToKey).indexOf(event.active.id as string);
       setActiveIndex(key);
 
+      // Bug in react-compiler linter
+      // eslint-disable-next-line react-compiler/react-compiler
       document.body.style.cursor = 'grabbing';
     },
     [columns, columnToKey],
diff --git a/browser/data-browser/src/components/TableEditor/TableHeading.tsx b/browser/data-browser/src/components/TableEditor/TableHeading.tsx
index 38acfc1e1..c625cdf85 100644
--- a/browser/data-browser/src/components/TableEditor/TableHeading.tsx
+++ b/browser/data-browser/src/components/TableEditor/TableHeading.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect } from 'react';
+import { useCallback, useEffect, useRef, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { DragAreaBase, useResizable } from '../../hooks/useResizable';
 import { useTableEditorContext } from './TableEditorContext';
@@ -26,6 +26,7 @@ export function TableHeading<T>({
   onResize,
   HeadingComponent,
 }: TableHeadingProps<T>): JSX.Element {
+  const targetRef = useRef<HTMLDivElement>(null);
   const {
     attributes,
     listeners,
@@ -36,11 +37,12 @@ export function TableHeading<T>({
     data: { index },
   });
 
-  const { targetRef, dragAreaRef, isDragging, dragAreaListeners } =
+  const { dragAreaRef, isDragging, dragAreaListeners } =
     useResizable<HTMLDivElement>({
       initialSize: DEFAULT_SIZE_PX,
       minSize: 100,
       onResize: size => onResize(index, `${size}px`),
+      targetRef,
     });
 
   const { setIsDragging } = useTableEditorContext();
diff --git a/browser/data-browser/src/components/TableEditor/helpers/keyboardHandlers.ts b/browser/data-browser/src/components/TableEditor/helpers/keyboardHandlers.ts
index 9c939e0d1..836c9b791 100644
--- a/browser/data-browser/src/components/TableEditor/helpers/keyboardHandlers.ts
+++ b/browser/data-browser/src/components/TableEditor/helpers/keyboardHandlers.ts
@@ -34,7 +34,7 @@ export type TableCommands = {
 export type HandlerContext = {
   tableContext: TableEditorContext;
   event: React.KeyboardEvent;
-  tableRef: React.RefObject<HTMLDivElement>;
+  tableRef: React.RefObject<HTMLDivElement | null>;
   translateCursor: (row: number, column: number) => void;
   columnCount: number;
 } & TableCommands;
diff --git a/browser/data-browser/src/components/TableEditor/hooks/useIsScrolling.ts b/browser/data-browser/src/components/TableEditor/hooks/useIsScrolling.ts
deleted file mode 100644
index ca102c900..000000000
--- a/browser/data-browser/src/components/TableEditor/hooks/useIsScrolling.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import { useCallback, useEffect, useRef } from 'react';
-
-/**
- * Sets a ref to true when the user is scrolling the given element.
- * @param ref The element to attach the scroll listener to.
- * @param isScrollingRef The ref that is modified to reflect if the user is scrolling.
- * @param pollingRate After how many milliseconds the hook should check if the user is still scrolling.
- */
-export function useIsScrolling<T extends HTMLElement>(
-  ref: React.RefObject<T | null>,
-  isScrollingRef: React.MutableRefObject<boolean>,
-  pollingRate = 100,
-): void {
-  const scrollLeft = useRef(0);
-  const scrollTop = useRef(0);
-  const timeoutID = useRef<number | undefined>();
-
-  const scrollPositionChanged = (): boolean => {
-    const node = ref.current;
-
-    return (
-      !!node &&
-      node.scrollLeft !== scrollLeft.current &&
-      node.scrollTop !== scrollTop.current
-    );
-  };
-
-  const checkIfScrollEnded = useCallback(() => {
-    if (ref.current === null) {
-      return;
-    }
-
-    if (scrollPositionChanged()) {
-      // The user is still scrolling.
-      scrollLeft.current = ref.current.scrollLeft;
-      scrollTop.current = ref.current.scrollTop;
-
-      timeoutID.current = setTimeout(
-        checkIfScrollEnded,
-        pollingRate,
-      ) as unknown as number;
-    } else {
-      // The user has stopped scrolling.
-      isScrollingRef.current = false;
-      timeoutID.current = undefined;
-    }
-  }, [ref, pollingRate]);
-
-  const handleScroll = useCallback(() => {
-    if (ref.current === null) {
-      return;
-    }
-
-    if (!isScrollingRef.current) {
-      isScrollingRef.current = true;
-      scrollLeft.current = ref.current.scrollLeft;
-      scrollTop.current = ref.current.scrollTop;
-    }
-
-    if (timeoutID.current !== undefined) {
-      clearTimeout(timeoutID.current);
-    }
-
-    timeoutID.current = setTimeout(
-      checkIfScrollEnded,
-      pollingRate,
-    ) as unknown as number;
-  }, [ref, pollingRate, checkIfScrollEnded]);
-
-  useEffect(() => {
-    if (ref.current === null) {
-      return;
-    }
-
-    const listener = () => {
-      requestAnimationFrame(() => {
-        handleScroll();
-      });
-    };
-
-    ref.current.addEventListener('scroll', listener);
-
-    return () => ref.current?.removeEventListener('scroll', listener);
-  }, [ref]);
-}
diff --git a/browser/data-browser/src/components/TableEditor/hooks/useTableEditorKeyboardNavigation.tsx b/browser/data-browser/src/components/TableEditor/hooks/useTableEditorKeyboardNavigation.tsx
index 0395790e9..4a5a9daef 100644
--- a/browser/data-browser/src/components/TableEditor/hooks/useTableEditorKeyboardNavigation.tsx
+++ b/browser/data-browser/src/components/TableEditor/hooks/useTableEditorKeyboardNavigation.tsx
@@ -24,14 +24,15 @@ const matchModifier = (
 const matchCondition = (handler: KeyboardHandler, context: HandlerContext) =>
   handler.condition === undefined || handler.condition(context);
 
-const tableHeaderHasFocus = (headerRef: React.RefObject<HTMLDivElement>) =>
-  headerRef.current?.contains(document.activeElement);
+const tableHeaderHasFocus = (
+  headerRef: React.RefObject<HTMLDivElement | null>,
+) => headerRef.current?.contains(document.activeElement);
 
 export function useTableEditorKeyboardNavigation(
   columnCount: number,
   rowCount: number,
-  tableRef: React.RefObject<HTMLDivElement>,
-  headerRef: React.RefObject<HTMLDivElement>,
+  tableRef: React.RefObject<HTMLDivElement | null>,
+  headerRef: React.RefObject<HTMLDivElement | null>,
   commands: TableCommands,
 ) {
   const tableContext = useTableEditorContext();
diff --git a/browser/data-browser/src/components/Tag/Tag.tsx b/browser/data-browser/src/components/Tag/Tag.tsx
index f7ed87be7..3533751de 100644
--- a/browser/data-browser/src/components/Tag/Tag.tsx
+++ b/browser/data-browser/src/components/Tag/Tag.tsx
@@ -1,7 +1,7 @@
 import { urls, useResource, useString, useTitle } from '@tomic/react';
 import { lighten, setLightness, setSaturation } from 'polished';
 import * as RadixPopover from '@radix-ui/react-popover';
-import { useCallback, useMemo, useState } from 'react';
+import { useCallback, useMemo, useState, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { transition } from '../../helpers/transition';
 import { Popover } from '../Popover';
diff --git a/browser/data-browser/src/components/Thumbnail.tsx b/browser/data-browser/src/components/Thumbnail.tsx
index 40f5e37f9..6bff2c917 100644
--- a/browser/data-browser/src/components/Thumbnail.tsx
+++ b/browser/data-browser/src/components/Thumbnail.tsx
@@ -2,6 +2,8 @@ import { styled } from 'styled-components';
 import { Image } from '@tomic/react';
 import { InnerWrapper } from '../views/FolderPage/GridItem/components';
 
+import type { JSX } from 'react';
+
 interface ThumbnailProps {
   subject: string;
   style?: React.CSSProperties | undefined;
diff --git a/browser/data-browser/src/components/Title.tsx b/browser/data-browser/src/components/Title.tsx
index 53a94ece5..10fe15021 100644
--- a/browser/data-browser/src/components/Title.tsx
+++ b/browser/data-browser/src/components/Title.tsx
@@ -3,6 +3,8 @@ import { Resource, useTitle } from '@tomic/react';
 import { AtomicLink } from './AtomicLink';
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 interface PageTitleProps {
   /** Put in front of the subject's name */
   prefix?: string;
diff --git a/browser/data-browser/src/components/Toaster.tsx b/browser/data-browser/src/components/Toaster.tsx
index 1c147cbbf..c567d5776 100644
--- a/browser/data-browser/src/components/Toaster.tsx
+++ b/browser/data-browser/src/components/Toaster.tsx
@@ -10,6 +10,8 @@ import { zIndex } from '../styling';
 import { Row } from './Row';
 import { IconButton } from './IconButton/IconButton';
 
+import type { JSX } from 'react';
+
 /**
  * Makes themed toast notifications available in the Context. Render this
  * somewhere high up in the app
diff --git a/browser/data-browser/src/components/ValueComp.tsx b/browser/data-browser/src/components/ValueComp.tsx
index 08662dfc9..0f1a57fb8 100644
--- a/browser/data-browser/src/components/ValueComp.tsx
+++ b/browser/data-browser/src/components/ValueComp.tsx
@@ -13,6 +13,8 @@ import Nestedresource from './datatypes/NestedResource';
 import ResourceArray from './datatypes/ResourceArray';
 import { ErrMessage } from './forms/InputStyles';
 
+import type { JSX } from 'react';
+
 type Props = {
   value: JSONValue;
   datatype: Datatype;
diff --git a/browser/data-browser/src/components/datatypes/DateTime.tsx b/browser/data-browser/src/components/datatypes/DateTime.tsx
index 9a1c5dd6a..3cf44f881 100644
--- a/browser/data-browser/src/components/datatypes/DateTime.tsx
+++ b/browser/data-browser/src/components/datatypes/DateTime.tsx
@@ -1,3 +1,4 @@
+import type { JSX } from 'react';
 type Props = {
   date: Date;
 };
diff --git a/browser/data-browser/src/components/datatypes/NestedResource.tsx b/browser/data-browser/src/components/datatypes/NestedResource.tsx
index d043f80b3..a0a97a8d8 100644
--- a/browser/data-browser/src/components/datatypes/NestedResource.tsx
+++ b/browser/data-browser/src/components/datatypes/NestedResource.tsx
@@ -2,6 +2,8 @@ import { Resource } from '@tomic/react';
 import AllProps from '../AllProps';
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 type Props = {
   resource: Resource;
 };
diff --git a/browser/data-browser/src/components/datatypes/ResourceArray.tsx b/browser/data-browser/src/components/datatypes/ResourceArray.tsx
index 21f4547c2..15bace704 100644
--- a/browser/data-browser/src/components/datatypes/ResourceArray.tsx
+++ b/browser/data-browser/src/components/datatypes/ResourceArray.tsx
@@ -1,4 +1,4 @@
-import { useState, Fragment } from 'react';
+import { useState, Fragment, type JSX } from 'react';
 import { JSONValue } from '@tomic/react';
 import { styled } from 'styled-components';
 import { ResourceInline } from '../../views/ResourceInline';
diff --git a/browser/data-browser/src/components/forms/AtomicSelectInput.tsx b/browser/data-browser/src/components/forms/AtomicSelectInput.tsx
index b3c00dcea..fe96189b7 100644
--- a/browser/data-browser/src/components/forms/AtomicSelectInput.tsx
+++ b/browser/data-browser/src/components/forms/AtomicSelectInput.tsx
@@ -2,6 +2,8 @@ import { Resource, useValue } from '@tomic/react';
 
 import { BasicSelect } from './BasicSelect';
 
+import type { JSX } from 'react';
+
 interface AtomicSelectInputProps {
   resource: Resource;
   property: string;
diff --git a/browser/data-browser/src/components/forms/Checkbox.tsx b/browser/data-browser/src/components/forms/Checkbox.tsx
index 35b8d9df9..565a267d8 100644
--- a/browser/data-browser/src/components/forms/Checkbox.tsx
+++ b/browser/data-browser/src/components/forms/Checkbox.tsx
@@ -1,5 +1,7 @@
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 interface CheckboxProps
   extends Omit<
     React.InputHTMLAttributes<HTMLInputElement>,
diff --git a/browser/data-browser/src/components/forms/Field.tsx b/browser/data-browser/src/components/forms/Field.tsx
index 828953a51..7d81774ec 100644
--- a/browser/data-browser/src/components/forms/Field.tsx
+++ b/browser/data-browser/src/components/forms/Field.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React, { useState, type JSX } from 'react';
 import { FaAsterisk, FaInfo, FaTrash } from 'react-icons/fa';
 import { styled } from 'styled-components';
 import { Collapse } from '../Collapse';
diff --git a/browser/data-browser/src/components/forms/FileDropzone/FileDropzone.tsx b/browser/data-browser/src/components/forms/FileDropzone/FileDropzone.tsx
index 2662aaa04..95c078282 100644
--- a/browser/data-browser/src/components/forms/FileDropzone/FileDropzone.tsx
+++ b/browser/data-browser/src/components/forms/FileDropzone/FileDropzone.tsx
@@ -1,5 +1,11 @@
 import { Resource } from '@tomic/react';
-import { PropsWithChildren, useCallback, useEffect, useRef } from 'react';
+import {
+  PropsWithChildren,
+  useCallback,
+  useEffect,
+  useRef,
+  type JSX,
+} from 'react';
 import { useDropzone } from 'react-dropzone';
 import { FaUpload } from 'react-icons/fa';
 import { styled, keyframes } from 'styled-components';
diff --git a/browser/data-browser/src/components/forms/FileDropzone/FileDropzoneInput.tsx b/browser/data-browser/src/components/forms/FileDropzone/FileDropzoneInput.tsx
index 25e5a2f48..7b4241cd2 100644
--- a/browser/data-browser/src/components/forms/FileDropzone/FileDropzoneInput.tsx
+++ b/browser/data-browser/src/components/forms/FileDropzone/FileDropzoneInput.tsx
@@ -1,5 +1,5 @@
 import { Resource } from '@tomic/react';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { useDropzone } from 'react-dropzone';
 import { FaUpload } from 'react-icons/fa';
 import { styled } from 'styled-components';
diff --git a/browser/data-browser/src/components/forms/InputBoolean.tsx b/browser/data-browser/src/components/forms/InputBoolean.tsx
index 589dd5771..23b1786ae 100644
--- a/browser/data-browser/src/components/forms/InputBoolean.tsx
+++ b/browser/data-browser/src/components/forms/InputBoolean.tsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { useBoolean } from '@tomic/react';
 import { InputProps } from './ResourceField';
 import { ErrMessage } from './InputStyles';
diff --git a/browser/data-browser/src/components/forms/InputMarkdown.tsx b/browser/data-browser/src/components/forms/InputMarkdown.tsx
index 55e49a028..33df88550 100644
--- a/browser/data-browser/src/components/forms/InputMarkdown.tsx
+++ b/browser/data-browser/src/components/forms/InputMarkdown.tsx
@@ -1,4 +1,4 @@
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { useString, validateDatatype } from '@tomic/react';
 import { InputProps } from './ResourceField';
 import { ErrMessage } from './InputStyles';
diff --git a/browser/data-browser/src/components/forms/InputNumber.tsx b/browser/data-browser/src/components/forms/InputNumber.tsx
index 077f0f007..ba12932f4 100644
--- a/browser/data-browser/src/components/forms/InputNumber.tsx
+++ b/browser/data-browser/src/components/forms/InputNumber.tsx
@@ -8,6 +8,8 @@ import {
 import { ErrorChipInput } from './ErrorChip';
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 export default function InputNumber({
   resource,
   property,
diff --git a/browser/data-browser/src/components/forms/InputResource.tsx b/browser/data-browser/src/components/forms/InputResource.tsx
index 9e7c472ff..cca246d34 100644
--- a/browser/data-browser/src/components/forms/InputResource.tsx
+++ b/browser/data-browser/src/components/forms/InputResource.tsx
@@ -3,6 +3,8 @@ import { noNestedSupport, useSubject } from '@tomic/react';
 import { ResourceSelector } from './ResourceSelector';
 import { ErrorLook } from '../ErrorLook';
 
+import type { JSX } from 'react';
+
 /** Input field for a single Resource. Renders a dropdown select menu. */
 export function InputResource({
   resource,
diff --git a/browser/data-browser/src/components/forms/InputResourceArray.tsx b/browser/data-browser/src/components/forms/InputResourceArray.tsx
index 713771cdf..091f078dd 100644
--- a/browser/data-browser/src/components/forms/InputResourceArray.tsx
+++ b/browser/data-browser/src/components/forms/InputResourceArray.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useMemo, useState } from 'react';
+import React, { useCallback, useMemo, useState, type JSX } from 'react';
 import { useArray, validateDatatype } from '@tomic/react';
 import { Button } from '../Button';
 import { InputProps } from './ResourceField';
diff --git a/browser/data-browser/src/components/forms/InputSlug.tsx b/browser/data-browser/src/components/forms/InputSlug.tsx
index 25c0bfb0c..e6d566046 100644
--- a/browser/data-browser/src/components/forms/InputSlug.tsx
+++ b/browser/data-browser/src/components/forms/InputSlug.tsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { useString, validateDatatype } from '@tomic/react';
 import { InputProps } from './ResourceField';
 import { InputStyled, InputWrapper } from './InputStyles';
@@ -55,9 +55,11 @@ export default function InputSlug({
     <Wrapper>
       <InputWrapper $invalid={!!error}>
         <InputStyled
+          type='text'
           value={inputValue ?? ''}
           onChange={handleUpdate}
           onBlur={setTouched}
+          autoComplete='none'
           {...props}
         />
       </InputWrapper>
diff --git a/browser/data-browser/src/components/forms/InputString.tsx b/browser/data-browser/src/components/forms/InputString.tsx
index 9d0165331..17f09df0e 100644
--- a/browser/data-browser/src/components/forms/InputString.tsx
+++ b/browser/data-browser/src/components/forms/InputString.tsx
@@ -8,6 +8,8 @@ import {
   useValidation,
 } from './formValidation/useValidation';
 
+import type { JSX } from 'react';
+
 export default function InputString({
   resource,
   property,
diff --git a/browser/data-browser/src/components/forms/InputSwitcher.tsx b/browser/data-browser/src/components/forms/InputSwitcher.tsx
index 0ab600f55..9e58b45df 100644
--- a/browser/data-browser/src/components/forms/InputSwitcher.tsx
+++ b/browser/data-browser/src/components/forms/InputSwitcher.tsx
@@ -12,6 +12,8 @@ import { InputTimestamp } from './InputTimestamp';
 import { InputDate } from './InputDate';
 import { FilePicker } from './FilePicker/FilePicker';
 
+import type { JSX } from 'react';
+
 /** Renders a fitting HTML input depending on the Datatype */
 export default function InputSwitcher(props: InputProps): JSX.Element {
   switch (props.property.datatype) {
diff --git a/browser/data-browser/src/components/forms/NewForm/NewFormDialog.tsx b/browser/data-browser/src/components/forms/NewForm/NewFormDialog.tsx
index 891994f61..224d2b9e9 100644
--- a/browser/data-browser/src/components/forms/NewForm/NewFormDialog.tsx
+++ b/browser/data-browser/src/components/forms/NewForm/NewFormDialog.tsx
@@ -1,5 +1,5 @@
 import { Core, JSONValue, useResource } from '@tomic/react';
-import { useState, useCallback } from 'react';
+import { useState, useCallback, type JSX } from 'react';
 import { useEffectOnce } from '../../../hooks/useEffectOnce';
 import { Button } from '../../Button';
 import { DialogTitle, DialogContent, DialogActions } from '../../Dialog';
diff --git a/browser/data-browser/src/components/forms/NewForm/NewFormPage.tsx b/browser/data-browser/src/components/forms/NewForm/NewFormPage.tsx
index 15db7fc0f..cfe36ec48 100644
--- a/browser/data-browser/src/components/forms/NewForm/NewFormPage.tsx
+++ b/browser/data-browser/src/components/forms/NewForm/NewFormPage.tsx
@@ -1,11 +1,15 @@
 import { useResource } from '@tomic/react';
-import { useQueryString } from '../../../helpers/navigation';
 import { ResourceForm } from '../ResourceForm';
 import { NewFormTitle } from './NewFormTitle';
 import { SubjectField } from './SubjectField';
 import { useNewForm } from './useNewForm';
 import { Column } from '../../Row';
 
+import type { JSX } from 'react';
+import { useSearch } from '@tanstack/react-router';
+import { paths } from '../../../routes/paths';
+import { NewRoute } from '../../../routes/NewResource/NewRoute';
+
 export interface NewFormProps {
   classSubject: string;
 }
@@ -15,15 +19,24 @@ export const NewFormFullPage = ({
   classSubject,
 }: NewFormProps): JSX.Element => {
   const klass = useResource(classSubject);
-  const [subject, setSubject] = useQueryString('newSubject');
-  const [parentSubject] = useQueryString('parent');
+  const { parent, newSubject: subject } = useSearch({ strict: false });
+
+  const navigate = NewRoute.useNavigate();
+
+  const setSubject = (x: string) => {
+    navigate({
+      to: paths.new,
+      search: prev => ({ ...prev, newSubject: x }),
+      replace: true,
+    });
+  };
 
   const { initialized, subjectErr, subjectValue, setSubjectValue, resource } =
     useNewForm({
       klass,
       setSubject,
       initialSubject: subject,
-      parent: parentSubject,
+      parent,
     });
 
   if (!initialized) return <>Initializing Resource</>;
diff --git a/browser/data-browser/src/components/forms/NewForm/NewFormTitle.tsx b/browser/data-browser/src/components/forms/NewForm/NewFormTitle.tsx
index 4be0c88f6..f56b7d1bd 100644
--- a/browser/data-browser/src/components/forms/NewForm/NewFormTitle.tsx
+++ b/browser/data-browser/src/components/forms/NewForm/NewFormTitle.tsx
@@ -1,5 +1,5 @@
 import { core, useResource, useString, useTitle } from '@tomic/react';
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { FaInfo } from 'react-icons/fa';
 import Markdown from '../../datatypes/Markdown';
 import { Column, Row } from '../../Row';
diff --git a/browser/data-browser/src/components/forms/NewForm/useNewResourceUI.tsx b/browser/data-browser/src/components/forms/NewForm/useNewResourceUI.tsx
index bdc34697f..689f73f62 100644
--- a/browser/data-browser/src/components/forms/NewForm/useNewResourceUI.tsx
+++ b/browser/data-browser/src/components/forms/NewForm/useNewResourceUI.tsx
@@ -7,6 +7,7 @@ import {
   useContext,
   useMemo,
   useState,
+  type JSX,
 } from 'react';
 import {
   useCreateAndNavigate,
diff --git a/browser/data-browser/src/components/forms/RadioInput.tsx b/browser/data-browser/src/components/forms/RadioInput.tsx
index 5ac754888..e257037c2 100644
--- a/browser/data-browser/src/components/forms/RadioInput.tsx
+++ b/browser/data-browser/src/components/forms/RadioInput.tsx
@@ -1,6 +1,8 @@
 import { styled } from 'styled-components';
 import { transition } from '../../helpers/transition';
 
+import type { JSX } from 'react';
+
 interface RadioInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
   disabled?: boolean;
 }
diff --git a/browser/data-browser/src/components/forms/RangeInput.tsx b/browser/data-browser/src/components/forms/RangeInput.tsx
index f7d1fc4c6..a4e4fe819 100644
--- a/browser/data-browser/src/components/forms/RangeInput.tsx
+++ b/browser/data-browser/src/components/forms/RangeInput.tsx
@@ -1,4 +1,4 @@
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { InputStyled, InputWrapper } from './InputStyles';
 import { Row } from '../Row';
 
diff --git a/browser/data-browser/src/components/forms/ResourceField.tsx b/browser/data-browser/src/components/forms/ResourceField.tsx
index 0b1cae45b..4bc879279 100644
--- a/browser/data-browser/src/components/forms/ResourceField.tsx
+++ b/browser/data-browser/src/components/forms/ResourceField.tsx
@@ -5,7 +5,7 @@ import Markdown from '../datatypes/Markdown';
 import { InputWrapper, InputStyled } from './InputStyles';
 import InputSwitcher from './InputSwitcher';
 import { AtomicLink } from '../AtomicLink';
-import { useId } from 'react';
+import { useId, type JSX } from 'react';
 import { Row } from '../Row';
 import { FaServer } from 'react-icons/fa6';
 
diff --git a/browser/data-browser/src/components/forms/ResourceForm.tsx b/browser/data-browser/src/components/forms/ResourceForm.tsx
index ebeb47dcd..a9745f30b 100644
--- a/browser/data-browser/src/components/forms/ResourceForm.tsx
+++ b/browser/data-browser/src/components/forms/ResourceForm.tsx
@@ -1,5 +1,4 @@
-import { useCallback, useMemo, useState } from 'react';
-import { useNavigate } from 'react-router-dom';
+import { useCallback, useMemo, useState, type JSX } from 'react';
 import {
   useArray,
   useResource,
@@ -31,6 +30,7 @@ import {
   RESOURCE_FORM_CONTEXT_VALUE,
   ResourceFormContext,
 } from './ResourceFormContext';
+import { useNavigateWithTransition } from '../../hooks/useNavigateWithTransition';
 
 export enum ResourceFormVariant {
   Default,
@@ -71,7 +71,7 @@ export function ResourceForm({
   onValidationChange,
 }: ResourceFormProps): JSX.Element {
   const isOnline = useOnline();
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
   const [isAArray] = useArray(resource, core.properties.isA);
 
   if (classSubject === undefined && isAArray?.length > 0) {
@@ -102,7 +102,7 @@ export function ResourceForm({
 
   const [save, saving, err] = useSaveResource(resource, onSaveSuccess);
 
-  const [canWrite, canWriteErr] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
 
   const otherProps = useMemo(() => {
     const allProps = Array.from(resource.getPropVals().keys());
@@ -203,8 +203,10 @@ export function ResourceForm({
                 {klass.error.message}`
               </ErrMessage>
             )}
-            {canWriteErr && (
-              <ErrMessage>Cannot save edits: {canWriteErr}</ErrMessage>
+            {!canWrite && (
+              <ErrMessage>
+                Cannot save edits: Agent does not have edit rights
+              </ErrMessage>
             )}
             {requires.map(property => {
               return (
diff --git a/browser/data-browser/src/components/forms/ResourceSelector/DropdownInput.tsx b/browser/data-browser/src/components/forms/ResourceSelector/DropdownInput.tsx
index 7622fceab..f049017af 100644
--- a/browser/data-browser/src/components/forms/ResourceSelector/DropdownInput.tsx
+++ b/browser/data-browser/src/components/forms/ResourceSelector/DropdownInput.tsx
@@ -1,4 +1,11 @@
-import { useEffect, useRef, useState, useCallback, useContext } from 'react';
+import {
+  useEffect,
+  useRef,
+  useState,
+  useCallback,
+  useContext,
+  type JSX,
+} from 'react';
 import { useHotkeys } from 'react-hotkeys-hook';
 import * as RadixPopover from '@radix-ui/react-popover';
 import { useResource, useTitle } from '@tomic/react';
diff --git a/browser/data-browser/src/components/forms/ResourceSelector/InlineOverlay.tsx b/browser/data-browser/src/components/forms/ResourceSelector/InlineOverlay.tsx
index 7a2f16db4..7900da05f 100644
--- a/browser/data-browser/src/components/forms/ResourceSelector/InlineOverlay.tsx
+++ b/browser/data-browser/src/components/forms/ResourceSelector/InlineOverlay.tsx
@@ -2,6 +2,8 @@ import { useResource } from '@tomic/react';
 
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 interface InlineOverlayProps {
   subject: string;
 }
diff --git a/browser/data-browser/src/components/forms/ResourceSelector/ResourceSelector.tsx b/browser/data-browser/src/components/forms/ResourceSelector/ResourceSelector.tsx
index b0eb7b0df..7076a3be5 100644
--- a/browser/data-browser/src/components/forms/ResourceSelector/ResourceSelector.tsx
+++ b/browser/data-browser/src/components/forms/ResourceSelector/ResourceSelector.tsx
@@ -1,4 +1,4 @@
-import { useState, useMemo, memo, useContext } from 'react';
+import { useState, useMemo, memo, useContext, type JSX } from 'react';
 import { Dialog, useDialog } from '../../Dialog';
 import { useSettings } from '../../../helpers/AppSettings';
 import { css, styled } from 'styled-components';
@@ -118,7 +118,7 @@ export const ResourceSelector = memo(function ResourceSelector({
   const { drive } = useSettings();
 
   const resource = useResource(value ?? unknownSubject);
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
 
   const shouldShowEditForm = canWrite && isURL(value ?? '');
 
diff --git a/browser/data-browser/src/components/forms/SearchBox/ResultLine.tsx b/browser/data-browser/src/components/forms/SearchBox/ResultLine.tsx
index 794845030..525dcac3f 100644
--- a/browser/data-browser/src/components/forms/SearchBox/ResultLine.tsx
+++ b/browser/data-browser/src/components/forms/SearchBox/ResultLine.tsx
@@ -5,7 +5,7 @@ import {
   useString,
   type Resource,
 } from '@tomic/react';
-import React, { useEffect, useRef } from 'react';
+import React, { useEffect, useRef, type JSX } from 'react';
 import { styled, css } from 'styled-components';
 import { dataTypeIconMap, getIconForClass } from '../../../helpers/iconMap';
 import { FaAtom } from 'react-icons/fa6';
diff --git a/browser/data-browser/src/components/forms/SearchBox/SearchBox.tsx b/browser/data-browser/src/components/forms/SearchBox/SearchBox.tsx
index cddd33106..442544520 100644
--- a/browser/data-browser/src/components/forms/SearchBox/SearchBox.tsx
+++ b/browser/data-browser/src/components/forms/SearchBox/SearchBox.tsx
@@ -5,6 +5,7 @@ import {
   useEffect,
   useRef,
   useState,
+  type JSX,
 } from 'react';
 import { css, styled } from 'styled-components';
 import { removeCachedSearchResults, useResource, useStore } from '@tomic/react';
diff --git a/browser/data-browser/src/components/forms/SearchBox/SearchBoxWindow.tsx b/browser/data-browser/src/components/forms/SearchBox/SearchBoxWindow.tsx
index d12152bc3..c5f5f8480 100644
--- a/browser/data-browser/src/components/forms/SearchBox/SearchBoxWindow.tsx
+++ b/browser/data-browser/src/components/forms/SearchBox/SearchBoxWindow.tsx
@@ -8,6 +8,7 @@ import {
   useMemo,
   useRef,
   useState,
+  type JSX,
 } from 'react';
 import { FaSearch } from 'react-icons/fa';
 import { styled, css } from 'styled-components';
@@ -25,6 +26,7 @@ import { useTitlePropOfClass } from '../ResourceSelector/useTitlePropOfClass';
 import { stringToSlug } from '../../../helpers/stringToSlug';
 import { addIf } from '../../../helpers/addIf';
 import { Row } from '../../Row';
+import React from 'react';
 
 /**
  * Options shown at the top of the results when the `isA` prop matches a key in this object.
@@ -57,7 +59,7 @@ interface SearchBoxWindowProps {
   scopes?: string[];
   placeholder?: string;
   allowsOnly?: string[];
-  triggerRef: RefObject<HTMLButtonElement>;
+  triggerRef: RefObject<HTMLButtonElement | null>;
   onExit: (lostFocus: boolean) => void;
   onChange: (value: string) => void;
   onSelect: (value: string) => void;
@@ -94,7 +96,7 @@ export function SearchBoxWindow({
   const isAboveTrigger = below < remToPixels(BOX_HEIGHT_REM);
 
   const showCreateOption =
-    onCreateItem && searchValue && !valueIsURL && !allowsOnly;
+    !!onCreateItem && !!searchValue && !valueIsURL && !allowsOnly;
 
   const standardOptions = useMemo(() => {
     if (!searchValue && isA && isA in STANDARD_OPTIONS) {
@@ -106,7 +108,7 @@ export function SearchBoxWindow({
 
   const options: Option[] = useMemo(
     () => [
-      ...addIf(!!showCreateOption, {
+      ...addIf(showCreateOption, {
         type: OptionType.CreateOption,
         data: '',
       }),
@@ -276,7 +278,7 @@ export function SearchBoxWindow({
         />
       </SearchInputWrapper>
       <ResultBox data-testid='searchbox-results'>
-        {!searchValue && results.length === 0 && (
+        {!searchValue && options.length === 0 && (
           <CenteredMessage>Start Searching</CenteredMessage>
         )}
         <StyledScrollArea>
@@ -287,7 +289,6 @@ export function SearchBoxWindow({
               if (option.type === OptionType.CreateOption) {
                 line = (
                   <ResultLine
-                    key={'create option'}
                     selected={selectedIndex === 0}
                     onMouseOver={() => handleMouseMove(0)}
                     onClick={() => createItem(searchValue)}
@@ -305,7 +306,6 @@ export function SearchBoxWindow({
               } else {
                 line = (
                   <ResourceResultLine
-                    key={option.data}
                     subject={option.data}
                     selected={i === selectedIndex}
                     onMouseOver={() => handleMouseMove(i)}
@@ -317,15 +317,22 @@ export function SearchBoxWindow({
                 );
               }
 
+              // Show a divider if the next option is of a different type. But not on the last option.
               const showDivider =
                 options[i + 1] !== undefined &&
                 option.type !== options[i + 1].type;
 
               return (
-                <>
+                <React.Fragment
+                  key={
+                    option.type === OptionType.CreateOption
+                      ? 'create option'
+                      : option.data
+                  }
+                >
                   {line}
                   {showDivider && <Divider />}
-                </>
+                </React.Fragment>
               );
             })}
           </List>
diff --git a/browser/data-browser/src/components/forms/UploadForm.tsx b/browser/data-browser/src/components/forms/UploadForm.tsx
index 3d618c735..188a869fa 100644
--- a/browser/data-browser/src/components/forms/UploadForm.tsx
+++ b/browser/data-browser/src/components/forms/UploadForm.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useState } from 'react';
+import { useCallback, useState, type JSX } from 'react';
 import { Resource } from '@tomic/react';
 import { useDropzone } from 'react-dropzone';
 import { Button } from '../Button';
diff --git a/browser/data-browser/src/components/forms/ValueForm/ValueForm.tsx b/browser/data-browser/src/components/forms/ValueForm/ValueForm.tsx
index 1fc957153..7e56ddf66 100644
--- a/browser/data-browser/src/components/forms/ValueForm/ValueForm.tsx
+++ b/browser/data-browser/src/components/forms/ValueForm/ValueForm.tsx
@@ -33,7 +33,7 @@ export function ValueForm({ resource, propertyURL, datatype }: ValueFormProps) {
   const property = useProperty(propertyURL);
   const [value] = useValue(resource, propertyURL);
   const { agent } = useSettings();
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
 
   useHotkeys(
     'esc',
diff --git a/browser/data-browser/src/components/forms/formValidation/useLifecycleWithDependencies.ts b/browser/data-browser/src/components/forms/formValidation/useLifecycleWithDependencies.ts
index 70ce2c5bd..2b8ec9332 100644
--- a/browser/data-browser/src/components/forms/formValidation/useLifecycleWithDependencies.ts
+++ b/browser/data-browser/src/components/forms/formValidation/useLifecycleWithDependencies.ts
@@ -7,8 +7,10 @@ export function useLifecycleWithDependencies(
   const mountRef = useRef(onMount);
   const cleanupRef = useRef(onCleanup);
 
-  mountRef.current = onMount;
-  cleanupRef.current = onCleanup;
+  useEffect(() => {
+    mountRef.current = onMount;
+    cleanupRef.current = onCleanup;
+  }, [onMount, onCleanup]);
 
   useEffect(() => {
     mountRef.current();
diff --git a/browser/data-browser/src/components/forms/hooks/useAvailableSpace.ts b/browser/data-browser/src/components/forms/hooks/useAvailableSpace.ts
index fb0cf9c91..3a857dc8f 100644
--- a/browser/data-browser/src/components/forms/hooks/useAvailableSpace.ts
+++ b/browser/data-browser/src/components/forms/hooks/useAvailableSpace.ts
@@ -2,7 +2,7 @@ import { useDeferredValue, useLayoutEffect, useState } from 'react';
 
 export function useAvailableSpace<T extends HTMLElement>(
   trigger: boolean,
-  ref: React.RefObject<T>,
+  ref: React.RefObject<T | null>,
 ) {
   const [space, setSpace] = useState({ above: 0, below: 0, width: 0 });
 
diff --git a/browser/data-browser/src/config.ts b/browser/data-browser/src/config.ts
index 659a4cc1b..56c5b9ab7 100644
--- a/browser/data-browser/src/config.ts
+++ b/browser/data-browser/src/config.ts
@@ -1,4 +1,6 @@
+/// <reference types="vite/client" />
+
 /** Returns true if this is run in locally, in Development mode */
 export function isDev(): boolean {
-  return import.meta.env['MODE'] === 'development';
+  return import.meta.env.MODE === 'development';
 }
diff --git a/browser/data-browser/src/helpers/AppSettings.tsx b/browser/data-browser/src/helpers/AppSettings.tsx
index fb52ca4eb..99a615436 100644
--- a/browser/data-browser/src/helpers/AppSettings.tsx
+++ b/browser/data-browser/src/helpers/AppSettings.tsx
@@ -4,6 +4,7 @@ import {
   useCallback,
   useContext,
   useMemo,
+  type JSX,
 } from 'react';
 import { DarkModeOption, useDarkMode } from './useDarkMode';
 import { useCurrentAgent, useServerURL, Agent } from '@tomic/react';
diff --git a/browser/data-browser/src/helpers/buildComponentFactory.ts b/browser/data-browser/src/helpers/buildComponentFactory.ts
index 97acd4523..3be160c6e 100644
--- a/browser/data-browser/src/helpers/buildComponentFactory.ts
+++ b/browser/data-browser/src/helpers/buildComponentFactory.ts
@@ -1,3 +1,5 @@
+import type { JSX } from 'react';
+
 export function buildComponentFactory<K, P>(
   options: Map<K, (props: P) => JSX.Element>,
   fallback: () => JSX.Element,
diff --git a/browser/data-browser/src/helpers/navigation.tsx b/browser/data-browser/src/helpers/navigation.tsx
index 66f42793a..ba7e6ecea 100644
--- a/browser/data-browser/src/helpers/navigation.tsx
+++ b/browser/data-browser/src/helpers/navigation.tsx
@@ -1,4 +1,3 @@
-import { useSearchParams } from 'react-router-dom';
 import { paths } from '../routes/paths';
 import { unknownSubject } from '@tomic/react';
 
@@ -13,6 +12,9 @@ function constructURL(
   return `${path}?${params}`;
 }
 
+const isRemoteResource = (subject: URL) =>
+  window.location.origin !== subject.origin;
+
 /** Constructs a URL for opening / showing a Resource. */
 export function constructOpenURL(
   subject: string,
@@ -24,13 +26,13 @@ export function constructOpenURL(
 
   const url = new URL(subject);
 
-  if (window.location.origin === url.origin) {
-    const path = url.pathname + url.search;
-
-    return path;
-  } else {
+  if (isRemoteResource(url)) {
     return constructURL(paths.show, { subject, ...extraParams });
   }
+
+  const path = url.pathname + url.search;
+
+  return path;
 }
 
 export function searchURL(query: string, scope?: string): string {
@@ -40,37 +42,6 @@ export function searchURL(query: string, scope?: string): string {
   });
 }
 
-type setFunc = (latestValue: string | undefined) => void;
-
-/** Returns a getter and a setter for query parameters */
-export function useQueryString(key: string): [string | undefined, setFunc] {
-  const [params, set] = useSearchParams();
-
-  const customSet = (subject: string | undefined) => {
-    if (subject === undefined) {
-      params.delete(key);
-    } else {
-      params.set(key, subject);
-    }
-
-    set(params);
-  };
-
-  const found = params.get(key);
-
-  if (found === null) {
-    return [undefined, customSet];
-  }
-
-  return [found, customSet];
-}
-
-/** A hook containing a getter and a setter for the current 'query' search param */
-// eslint-disable-next-line
-export function useSearchQuery() {
-  return useQueryString('query');
-}
-
 /** Query parameters used by the `/new` route */
 export const newURLParams = {
   classSubject: 'classSubject',
diff --git a/browser/data-browser/src/helpers/useCurrentSubject.tsx b/browser/data-browser/src/helpers/useCurrentSubject.tsx
index a5b5365ad..ad16111f3 100644
--- a/browser/data-browser/src/helpers/useCurrentSubject.tsx
+++ b/browser/data-browser/src/helpers/useCurrentSubject.tsx
@@ -1,6 +1,8 @@
 import { useEffect, useState } from 'react';
-import { useNavigate, useLocation } from 'react-router-dom';
-import { useQueryString } from './navigation';
+import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
+import { useLocation, useSearch } from '@tanstack/react-router';
+import { paths } from '../routes/paths';
+import { ShowRoute } from '../routes/ShowRoute';
 
 type setFunc = (latestValue: string) => void;
 
@@ -12,22 +14,20 @@ export function useCurrentSubject(
   /** Replace URL instead of push it, so it does not get added to history */
   replace?: boolean,
 ): [string | undefined, setFunc] {
-  const [subjectQ, setSubjectQ] = useQueryString('subject');
-  const navigate = useNavigate();
-  const { pathname, search } = useLocation();
+  const { subject: subjectQ } = useSearch({ strict: false });
+  const navigate = useNavigateWithTransition();
+  const navigateShow = ShowRoute.useNavigate();
+  const { pathname } = useLocation();
 
   function handleSetSubject(subject: string) {
     const url = new URL(subject);
 
     if (window.location.origin === url.origin) {
-      if (replace) {
-        navigate(url.pathname + url.search, { replace: true });
-      } else {
-        navigate(url.pathname + url.search);
-      }
+      // Navigate to the new subject.
+      navigate({ to: url.pathname + url.search, replace });
     } else {
-      // TODO: Handle replace?
-      setSubjectQ(subject);
+      // Add the new subject to the search params.
+      navigateShow({ to: paths.show, search: { subject }, replace });
     }
   }
 
@@ -37,12 +37,11 @@ export function useCurrentSubject(
     }
 
     // The pathname defaults to a trailing slash, which leads to issues
-    const correctedPathNamer = pathname === '/' ? '' : pathname;
+    const correctedPathName = pathname === '/' ? '' : '/' + pathname;
+    const subject =
+      window.location.origin + correctedPathName + window.location.search;
 
-    return [
-      window.location.origin + correctedPathNamer + search,
-      handleSetSubject,
-    ];
+    return [subject, handleSetSubject];
   }
 
   return [subjectQ, handleSetSubject];
diff --git a/browser/data-browser/src/helpers/useDebounce.ts b/browser/data-browser/src/helpers/useDebounce.ts
new file mode 100644
index 000000000..7e5efa0fb
--- /dev/null
+++ b/browser/data-browser/src/helpers/useDebounce.ts
@@ -0,0 +1,25 @@
+import { useState, useEffect } from 'react';
+
+export function useDebounce<T>(value: T, delay: number): T {
+  // State and setters for debounced value
+  const [debouncedValue, setDebouncedValue] = useState<T>(value);
+
+  useEffect(
+    () => {
+      // Update debounced value after delay
+      const handler = setTimeout(() => {
+        setDebouncedValue(value);
+      }, delay);
+
+      // Cancel the timeout if value changes (also on delay change or unmount)
+      // This is how we prevent debounced value from updating if value is changed ...
+      // .. within the delay period. Timeout gets cleared and restarted.
+      return () => {
+        clearTimeout(handler);
+      };
+    },
+    [value, delay], // Only re-call effect if value or delay changes
+  );
+
+  return debouncedValue;
+}
diff --git a/browser/data-browser/src/helpers/useFocus.tsx b/browser/data-browser/src/helpers/useFocus.tsx
deleted file mode 100644
index 8d5b31d4b..000000000
--- a/browser/data-browser/src/helpers/useFocus.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import { useRef } from 'react';
-
-/** Hook for programmaticall setting focus */
-export const useFocus = (): [React.RefObject<unknown>, () => void] => {
-  const htmlElRef = useRef<HTMLElement>(null);
-
-  const setFocus = () => {
-    htmlElRef.current?.focus();
-  };
-
-  return [htmlElRef, setFocus];
-};
diff --git a/browser/data-browser/src/helpers/useHTMLFormFieldValidation.ts b/browser/data-browser/src/helpers/useHTMLFormFieldValidation.ts
index a70403fb6..9261a1116 100644
--- a/browser/data-browser/src/helpers/useHTMLFormFieldValidation.ts
+++ b/browser/data-browser/src/helpers/useHTMLFormFieldValidation.ts
@@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from 'react';
 
 export function useHTMLFormFieldValidation(): [
   valid: boolean,
-  ref: React.RefObject<HTMLInputElement>,
+  ref: React.RefObject<HTMLInputElement | null>,
 ] {
   const [valid, setValid] = useState(false);
 
diff --git a/browser/data-browser/src/helpers/useHover.tsx b/browser/data-browser/src/helpers/useHover.tsx
index 0f4986bb3..3991d620f 100644
--- a/browser/data-browser/src/helpers/useHover.tsx
+++ b/browser/data-browser/src/helpers/useHover.tsx
@@ -8,7 +8,7 @@ type Listeners = {
 };
 
 export function useHover<T extends HTMLElement>(): [
-  ref: RefObject<T>,
+  ref: RefObject<T | null>,
   isHovering: boolean,
   listeners: Listeners,
 ] {
diff --git a/browser/data-browser/src/helpers/useLocalSearch.tsx b/browser/data-browser/src/helpers/useLocalSearch.tsx
index fd71aacde..7ac956f09 100644
--- a/browser/data-browser/src/helpers/useLocalSearch.tsx
+++ b/browser/data-browser/src/helpers/useLocalSearch.tsx
@@ -1,13 +1,13 @@
 import { useState, useEffect } from 'react';
 import {
   Client,
+  commits,
   Resource,
-  urls,
   useResources,
   useStore,
-  useDebounce,
 } from '@tomic/react';
 import { QuickScore } from 'quick-score';
+import { useDebounce } from './useDebounce';
 
 /**
  * Pass a query and an set of pre-defined subjects. If you don't pass these
@@ -75,12 +75,12 @@ function constructIndex(resourceMap?: Map<string, Resource>): SearchIndex {
     if (!resource.isReady()) return array;
 
     // ... or have no subject
-    if (resource.getSubject() === undefined) {
+    if (resource.subject === undefined) {
       return array;
     }
 
     // Don't index commits
-    if (resource.getClasses().includes(urls.classes.commit)) {
+    if (resource.hasClasses(commits.classes.commit)) {
       return array;
     }
 
@@ -89,7 +89,7 @@ function constructIndex(resourceMap?: Map<string, Resource>): SearchIndex {
       Array.from(resource.getPropVals().values()).sort().join(' \n '),
     );
     const searchResource: FoundResource = {
-      subject: resource.getSubject(),
+      subject: resource.subject,
       valuesArray: propvalsString,
     };
     array.push(searchResource);
diff --git a/browser/data-browser/src/helpers/useNewRoute.ts b/browser/data-browser/src/helpers/useNewRoute.ts
index 39ab91f33..e2751ad12 100644
--- a/browser/data-browser/src/helpers/useNewRoute.ts
+++ b/browser/data-browser/src/helpers/useNewRoute.ts
@@ -1,6 +1,6 @@
 import { useCallback } from 'react';
-import { useNavigate } from 'react-router';
 import { paths } from '../routes/paths';
+import { useNavigate } from '@tanstack/react-router';
 
 function buildURL(parent?: string) {
   const params = new URLSearchParams({
@@ -15,7 +15,7 @@ export function useNewRoute(parent?: string) {
 
   const navigateToNewRoute = useCallback(() => {
     const url = buildURL(parent);
-    navigate(url);
+    navigate({ to: url });
   }, [parent]);
 
   return navigateToNewRoute;
diff --git a/browser/data-browser/src/hooks/useCombineRefs.ts b/browser/data-browser/src/hooks/useCombineRefs.ts
index cceb2bcf1..9a62e70f4 100644
--- a/browser/data-browser/src/hooks/useCombineRefs.ts
+++ b/browser/data-browser/src/hooks/useCombineRefs.ts
@@ -1,16 +1,13 @@
-import { useCallback } from 'react';
-
 /**
  * Returns a callback ref that sets all given refs to the same passed in node.
  * Usefull if you want multiple refs to reference the same dom element.
  */
 export function useCombineRefs<T>(
-  refs: React.MutableRefObject<T>[],
-  deps: unknown[] = [],
+  refs: React.RefObject<T>[],
 ): (node: T) => void {
-  return useCallback((node: T) => {
+  return (node: T) => {
     for (const ref of refs) {
       ref.current = node;
     }
-  }, deps);
+  };
 }
diff --git a/browser/data-browser/src/hooks/useCreateAndNavigate.ts b/browser/data-browser/src/hooks/useCreateAndNavigate.ts
index 5bc63ae14..3f7049d47 100644
--- a/browser/data-browser/src/hooks/useCreateAndNavigate.ts
+++ b/browser/data-browser/src/hooks/useCreateAndNavigate.ts
@@ -1,8 +1,8 @@
 import { Core, JSONValue, Resource, useStore } from '@tomic/react';
 import { useCallback } from 'react';
 import toast from 'react-hot-toast';
-import { useNavigate } from 'react-router-dom';
 import { constructOpenURL } from '../helpers/navigation';
+import { useNavigate } from '@tanstack/react-router';
 
 export type CreateAndNavigate = (
   isA: string,
@@ -51,7 +51,7 @@ export function useCreateAndNavigate(): CreateAndNavigate {
           await onCreated(resource);
         }
 
-        navigate(constructOpenURL(resource.subject, extraParams));
+        await navigate({ to: constructOpenURL(resource.subject, extraParams) });
         toast.success(`${classResource.title} created`);
         store.notifyResourceManuallyCreated(resource);
       } catch (e) {
diff --git a/browser/data-browser/src/hooks/useIndexDependantCallback.ts b/browser/data-browser/src/hooks/useIndexDependantCallback.ts
index 1386c30e0..77e91ca50 100644
--- a/browser/data-browser/src/hooks/useIndexDependantCallback.ts
+++ b/browser/data-browser/src/hooks/useIndexDependantCallback.ts
@@ -2,18 +2,20 @@ import { useMemo } from 'react';
 import { GenericFunction } from '../helpers/genericTypes';
 
 /**
- * A hook that builds a list of callbacks that recieve the index of the item in the dependant array.
- * Usefull for buttons in a list that need to know which item they are acting on but should also be memoized.
+ * A hook that builds a list of callbacks that receive the index of the item in the dependant array.
+ * Useful for buttons in a list that need to know which item they are acting on but should also be memoized.
  * @param callbackFactory A function that takes an index and returns the actual callback.
  * @param dependantArray This array determines the amount of callbacks that will be created.
- * @param dependancies Any values the callback depends on (same as a useCallback dependancy array).
+ * @param dependencies Any values the callback depends on (same as a useCallback dependency array).
  */
 export function useIndexDependantCallback<CB extends GenericFunction>(
   callbackFactory: (index: number) => CB,
   dependantArray: unknown[],
-  dependancies: unknown[],
+  dependencies: unknown[],
 ): CB[] {
+  const memoizedDependencies = useMemo(() => dependencies, [dependencies]);
+
   return useMemo(() => {
     return dependantArray.map((_, i) => callbackFactory(i));
-  }, [dependantArray, ...dependancies]);
+  }, [dependantArray, memoizedDependencies]);
 }
diff --git a/browser/data-browser/src/hooks/useNavigateWithTransition.ts b/browser/data-browser/src/hooks/useNavigateWithTransition.ts
index 94c24ab3a..e4b1a403f 100644
--- a/browser/data-browser/src/hooks/useNavigateWithTransition.ts
+++ b/browser/data-browser/src/hooks/useNavigateWithTransition.ts
@@ -1,42 +1,71 @@
-import { useCallback } from 'react';
 import { flushSync } from 'react-dom';
-import { useNavigate } from 'react-router';
 import { useSettings } from '../helpers/AppSettings';
-const wait = (ms: number) => new Promise(r => setTimeout(r, ms));
+import { useNavigate, useRouter } from '@tanstack/react-router';
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function wrapWithTransition<F extends (...args: any[]) => Promise<void>>(
+  disabled: boolean,
+  cb: F,
+) {
+  if (disabled || !document.startViewTransition) {
+    return cb;
+  }
+
+  return (...args: Parameters<F>) =>
+    document.startViewTransition(() => {
+      return new Promise<void>(resolve => {
+        flushSync(() => {
+          cb(...args).then(() => resolve());
+        });
+      });
+    }).updateCallbackDone as Promise<void>;
+}
 
 /**
- * A wrapper around react-router's navigate function that will trigger css view transitions if enabled.
+ * A wrapper around tanstack-router's navigate function that will trigger css view transitions if enabled.
  */
 export function useNavigateWithTransition() {
   const navigate = useNavigate();
   const { viewTransitionsDisabled } = useSettings();
 
-  const navigateWithTransition = useCallback(
-    (to: string | number) => {
-      // @ts-ignore
-      if (viewTransitionsDisabled || !document.startViewTransition) {
-        //@ts-ignore
-        navigate(to);
-
-        return;
-      }
-
-      // @ts-ignore
-      document.startViewTransition(
-        async () =>
-          new Promise<void>(resolve => {
-            flushSync(() => {
-              // @ts-ignore
-              navigate(to);
-              wait(1).then(() => {
-                resolve();
-              });
-            });
-          }),
-      );
+  const navigateWithTransition = wrapWithTransition(
+    viewTransitionsDisabled,
+    (options: Parameters<typeof navigate>[0] | string) => {
+      const newOptions =
+        typeof options === 'string'
+          ? ({
+              to: options,
+            } satisfies Parameters<typeof navigate>[0])
+          : options;
+
+      return navigate(newOptions);
     },
-    [navigate],
   );
 
   return navigateWithTransition;
 }
+
+export function useBackForward() {
+  const router = useRouter();
+  const { viewTransitionsDisabled } = useSettings();
+
+  const back = wrapWithTransition(
+    viewTransitionsDisabled,
+    () =>
+      new Promise(resolve => {
+        router.history.back();
+        setTimeout(() => resolve(), 10);
+      }),
+  );
+
+  const forward = wrapWithTransition(
+    viewTransitionsDisabled,
+    () =>
+      new Promise(resolve => {
+        router.history.forward();
+        setTimeout(() => resolve(), 10);
+      }),
+  );
+
+  return { back, forward };
+}
diff --git a/browser/data-browser/src/hooks/useQueryScope.ts b/browser/data-browser/src/hooks/useQueryScope.ts
index a6ab27399..00e8fb1b0 100644
--- a/browser/data-browser/src/hooks/useQueryScope.ts
+++ b/browser/data-browser/src/hooks/useQueryScope.ts
@@ -1,6 +1,6 @@
-import { useCallback } from 'react';
-import { useNavigate } from 'react-router';
-import { useQueryString } from '../helpers/navigation';
+import { useSearch } from '@tanstack/react-router';
+import { paths } from '../routes/paths';
+import { SearchRoute } from '../routes/SearchRoute';
 
 export interface QueryScopeHandler {
   scope: string | undefined;
@@ -11,23 +11,25 @@ export interface QueryScopeHandler {
 export function useQueryScopeHandler(subject: string): QueryScopeHandler;
 export function useQueryScopeHandler(): Omit<QueryScopeHandler, 'enableScope'>;
 export function useQueryScopeHandler(subject?: string): QueryScopeHandler {
-  const [scope, setScope] = useQueryString('queryscope');
-  const navigate = useNavigate();
+  const { queryscope } = useSearch({ strict: false });
+  const navigate = SearchRoute.useNavigate();
 
-  const enableScope = useCallback(() => {
-    const params = new URLSearchParams({
-      queryscope: subject ?? '',
+  const enableScope = () => {
+    navigate({
+      to: paths.search,
+      search: prev => ({ ...prev, queryscope: subject ?? '' }),
     });
+  };
 
-    navigate(`/app/search?${params.toString()}`, { replace: true });
-  }, [setScope, subject]);
-
-  const clearScope = useCallback(() => {
-    setScope(undefined);
-  }, [setScope]);
+  const clearScope = () => {
+    navigate({
+      to: '.',
+      search: prev => ({ ...prev, queryscope: undefined }),
+    });
+  };
 
   return {
-    scope,
+    scope: queryscope,
     enableScope,
     clearScope,
   };
diff --git a/browser/data-browser/src/hooks/useResizable.ts b/browser/data-browser/src/hooks/useResizable.ts
index b522c3d1d..806b474b9 100644
--- a/browser/data-browser/src/hooks/useResizable.ts
+++ b/browser/data-browser/src/hooks/useResizable.ts
@@ -9,10 +9,9 @@ import {
 } from 'react';
 import { styled } from 'styled-components';
 
-interface UseResizeResult<E extends HTMLElement> {
+interface UseResizeResult {
   size: string;
-  targetRef: React.RefObject<E>;
-  dragAreaRef: React.RefObject<HTMLDivElement>;
+  dragAreaRef: React.RefObject<HTMLDivElement | null>;
   dragAreaListeners: Pick<React.DOMAttributes<HTMLDivElement>, 'onMouseDown'>;
   isDragging: boolean;
 }
@@ -58,18 +57,21 @@ function setDragStyling(id: string, enable: boolean) {
   }
 }
 
+export type UseResizableProps<E extends HTMLElement> = {
+  initialSize: number;
+  onResize?: (size: number) => void;
+  minSize?: number;
+  maxSize?: number;
+  targetRef: React.RefObject<E | null>;
+};
+
 export function useResizable<E extends HTMLElement>({
   initialSize,
   onResize,
   minSize = 0,
   maxSize = Infinity,
-}: {
-  initialSize: number;
-  onResize?: (size: number) => void;
-  minSize?: number;
-  maxSize?: number;
-}): UseResizeResult<E> {
-  const targetRef = useRef<E>(null);
+  targetRef,
+}: UseResizableProps<E>): UseResizeResult {
   const dragAreaRef = useRef<HTMLDivElement>(null);
 
   const [dragging, setDragging] = useState(false);
@@ -137,7 +139,6 @@ export function useResizable<E extends HTMLElement>({
 
   return {
     size,
-    targetRef,
     dragAreaRef,
     isDragging: dragging,
     dragAreaListeners: {
diff --git a/browser/data-browser/src/routes/AboutRoute.tsx b/browser/data-browser/src/routes/AboutRoute.tsx
index 30f4c4a5b..ae99c692d 100644
--- a/browser/data-browser/src/routes/AboutRoute.tsx
+++ b/browser/data-browser/src/routes/AboutRoute.tsx
@@ -3,6 +3,16 @@ import { ContainerNarrow } from '../components/Containers';
 import { AtomicLink } from '../components/AtomicLink';
 import { Logo } from '../components/Logo';
 
+import { createRoute } from '@tanstack/react-router';
+import { pathNames } from './paths';
+import { appRoute } from './RootRoutes';
+
+export const AboutRoute = createRoute({
+  path: pathNames.about,
+  component: () => <About />,
+  getParentRoute: () => appRoute,
+});
+
 export const About: React.FunctionComponent = () => {
   return (
     <ContainerNarrow>
diff --git a/browser/data-browser/src/routes/SettingsTheme.tsx b/browser/data-browser/src/routes/AppSettings.tsx
similarity index 91%
rename from browser/data-browser/src/routes/SettingsTheme.tsx
rename to browser/data-browser/src/routes/AppSettings.tsx
index 76adadd5f..980f94a13 100644
--- a/browser/data-browser/src/routes/SettingsTheme.tsx
+++ b/browser/data-browser/src/routes/AppSettings.tsx
@@ -1,17 +1,26 @@
 import * as React from 'react';
-import { ContainerNarrow } from '../components/Containers';
+import { createRoute } from '@tanstack/react-router';
 import { HexColorPicker } from 'react-colorful';
+import { styled } from 'styled-components';
+import { ContainerNarrow } from '../components/Containers';
 import { Button } from '../components/Button';
 import { useSettings } from '../helpers/AppSettings';
 import { NavStyleButton } from '../components/NavStyleButton';
 import { DarkModeOption } from '../helpers/useDarkMode';
 import { Column, Row } from '../components/Row';
-import { styled } from 'styled-components';
 import { Checkbox, CheckboxLabel } from '../components/forms/Checkbox';
 import { Main } from '../components/Main';
 import { Panel, usePanelList } from '../components/SideBar/usePanelList';
+import { pathNames } from './paths';
+import { appRoute } from './RootRoutes';
+
+export const AppSettingsRoute = createRoute({
+  path: pathNames.appSettings,
+  component: () => <AppSettings />,
+  getParentRoute: () => appRoute,
+});
 
-export const SettingsTheme: React.FunctionComponent = () => {
+const AppSettings: React.FunctionComponent = () => {
   const {
     darkModeSetting,
     setDarkMode,
diff --git a/browser/data-browser/src/routes/DataRoute.tsx b/browser/data-browser/src/routes/DataRoute.tsx
index 1aa41f022..712f52c43 100644
--- a/browser/data-browser/src/routes/DataRoute.tsx
+++ b/browser/data-browser/src/routes/DataRoute.tsx
@@ -1,4 +1,4 @@
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { useResource, signRequest, HeadersObject } from '@tomic/react';
 
 import AllProps from '../components/AllProps';
@@ -17,8 +17,17 @@ import { ResourceUsage } from '../components/ResourceUsage';
 import { Main } from '../components/Main';
 import { IconButton } from '../components/IconButton/IconButton';
 import { FaArrowLeft } from 'react-icons/fa';
-import { useNavigate } from 'react-router';
 import { constructOpenURL } from '../helpers/navigation';
+import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
+import { pathNames } from './paths';
+import { appRoute } from './RootRoutes';
+import { createRoute } from '@tanstack/react-router';
+
+export const DataRoute = createRoute({
+  path: pathNames.data,
+  component: () => <Data />,
+  getParentRoute: () => appRoute,
+});
 
 /** Renders the data of some Resource */
 function Data(): JSX.Element {
@@ -30,7 +39,7 @@ function Data(): JSX.Element {
   const [textResponseLoading, setTextResponseLoading] = useState(false);
   const [err, setErr] = useState<Error | undefined>(undefined);
   const { agent } = useSettings();
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
 
   if (!subject) {
     <ContainerNarrow>No subject passed</ContainerNarrow>;
@@ -149,5 +158,3 @@ function Data(): JSX.Element {
     </Main>
   );
 }
-
-export default Data;
diff --git a/browser/data-browser/src/routes/EditRoute.tsx b/browser/data-browser/src/routes/EditRoute.tsx
index 0d8337aba..a561a1056 100644
--- a/browser/data-browser/src/routes/EditRoute.tsx
+++ b/browser/data-browser/src/routes/EditRoute.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState, type JSX } from 'react';
 import { useResource } from '@tomic/react';
 import { constructOpenURL, newURL } from '../helpers/navigation';
 import { ContainerNarrow } from '../components/Containers';
@@ -12,9 +12,18 @@ import { Column, Row } from '../components/Row';
 import { IconButton } from '../components/IconButton/IconButton';
 import { FaArrowLeft } from 'react-icons/fa';
 import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
+import { createRoute } from '@tanstack/react-router';
+import { pathNames } from './paths';
+import { appRoute } from './RootRoutes';
+
+export const EditRoute = createRoute({
+  path: pathNames.edit,
+  component: () => <Edit />,
+  getParentRoute: () => appRoute,
+});
 
 /** Form for instantiating a new Resource from some Class */
-export function Edit(): JSX.Element {
+function Edit(): JSX.Element {
   const [subject] = useCurrentSubject();
   const resource = useResource(subject);
   const [subjectInput, setSubjectInput] = useState<string | undefined>(
diff --git a/browser/data-browser/src/routes/History/HistoryRoute.tsx b/browser/data-browser/src/routes/History/HistoryRoute.tsx
index 577fe4632..bd5994065 100644
--- a/browser/data-browser/src/routes/History/HistoryRoute.tsx
+++ b/browser/data-browser/src/routes/History/HistoryRoute.tsx
@@ -1,4 +1,4 @@
-import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useCallback, useEffect, useMemo, useState, type JSX } from 'react';
 import { useResource, Version } from '@tomic/react';
 
 import { ContainerNarrow } from '../../components/Containers';
@@ -16,9 +16,18 @@ import { useMediaQuery } from '../../hooks/useMediaQuery';
 import { Column, Row } from '../../components/Row';
 import { ProgressBar } from '../../components/ProgressBar';
 import { Main } from '../../components/Main';
+import { pathNames } from '../paths';
+import { appRoute } from '../RootRoutes';
+import { createRoute } from '@tanstack/react-router';
+
+export const HistoryRoute = createRoute({
+  path: pathNames.history,
+  component: () => <History />,
+  getParentRoute: () => appRoute,
+});
 
 /** Shows an activity log of previous versions */
-export function History(): JSX.Element {
+function History(): JSX.Element {
   const navigate = useNavigateWithTransition();
   const isSmallScreen = useMediaQuery('(max-width: 500px)');
   const [subject] = useCurrentSubject();
diff --git a/browser/data-browser/src/routes/History/VersionScroller.tsx b/browser/data-browser/src/routes/History/VersionScroller.tsx
index 9f2233928..b366fd16f 100644
--- a/browser/data-browser/src/routes/History/VersionScroller.tsx
+++ b/browser/data-browser/src/routes/History/VersionScroller.tsx
@@ -1,4 +1,4 @@
-import { useId, Fragment } from 'react';
+import { useId, Fragment, type JSX } from 'react';
 import { GroupedVersions } from './HistoryViewProps';
 import { Version, useStore } from '@tomic/react';
 import { styled } from 'styled-components';
diff --git a/browser/data-browser/src/routes/History/VersionTitle.tsx b/browser/data-browser/src/routes/History/VersionTitle.tsx
index f245448fe..af3438306 100644
--- a/browser/data-browser/src/routes/History/VersionTitle.tsx
+++ b/browser/data-browser/src/routes/History/VersionTitle.tsx
@@ -2,6 +2,8 @@ import { Version, useResource, useTitle } from '@tomic/react';
 
 import { AtomicLink } from '../../components/AtomicLink';
 
+import type { JSX } from 'react';
+
 const formatter = new Intl.DateTimeFormat('default', {
   month: 'long',
   year: 'numeric',
diff --git a/browser/data-browser/src/routes/History/index.ts b/browser/data-browser/src/routes/History/index.ts
deleted file mode 100644
index ca30bb37a..000000000
--- a/browser/data-browser/src/routes/History/index.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export { History } from './HistoryRoute';
diff --git a/browser/data-browser/src/routes/ImportRoute.tsx b/browser/data-browser/src/routes/ImportRoute.tsx
new file mode 100644
index 000000000..919e28e58
--- /dev/null
+++ b/browser/data-browser/src/routes/ImportRoute.tsx
@@ -0,0 +1,10 @@
+import { createRoute } from '@tanstack/react-router';
+import { pathNames } from './paths';
+import { appRoute } from './RootRoutes';
+import { ImporterPage } from '../views/ImporterPage';
+
+export const ImportRoute = createRoute({
+  path: pathNames.import,
+  component: () => <ImporterPage />,
+  getParentRoute: () => appRoute,
+});
diff --git a/browser/data-browser/src/routes/LocalRoute.tsx b/browser/data-browser/src/routes/LocalRoute.tsx
deleted file mode 100644
index 42e2f5aca..000000000
--- a/browser/data-browser/src/routes/LocalRoute.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { useLocation } from 'react-router-dom';
-import ResourcePage from '../views/ResourcePage';
-
-/** Show a resource where the domain matches the current domain */
-function Local(): JSX.Element {
-  const { pathname, search } = useLocation();
-
-  const subject = window.location.origin + pathname + search;
-
-  // The key makes sure the component re-renders when it changes
-  return <ResourcePage key={subject} subject={subject} />;
-}
-
-export default Local;
diff --git a/browser/data-browser/src/routes/NewResource/BaseButtons.tsx b/browser/data-browser/src/routes/NewResource/BaseButtons.tsx
index 95eaf01fa..260898ed2 100644
--- a/browser/data-browser/src/routes/NewResource/BaseButtons.tsx
+++ b/browser/data-browser/src/routes/NewResource/BaseButtons.tsx
@@ -2,6 +2,8 @@ import { core, dataBrowser } from '@tomic/react';
 import { OutlinedSection } from '../../components/OutlinedSection';
 import { ClassButton } from './ClassButton';
 
+import type { JSX } from 'react';
+
 interface BaseButtonsProps {
   parent: string;
 }
diff --git a/browser/data-browser/src/routes/NewResource/ClassButton.tsx b/browser/data-browser/src/routes/NewResource/ClassButton.tsx
index b3983a948..56c8e59f1 100644
--- a/browser/data-browser/src/routes/NewResource/ClassButton.tsx
+++ b/browser/data-browser/src/routes/NewResource/ClassButton.tsx
@@ -2,6 +2,8 @@ import { useResource, useTitle } from '@tomic/react';
 import { getIconForClass } from '../../helpers/iconMap';
 import { NewInstanceButton } from '../../components/NewInstanceButton';
 
+import type { JSX } from 'react';
+
 interface ClassButtonProps {
   classType: string;
   parent: string;
diff --git a/browser/data-browser/src/routes/NewResource/NewRoute.tsx b/browser/data-browser/src/routes/NewResource/NewRoute.tsx
index edb9e307c..d7bf49ba3 100644
--- a/browser/data-browser/src/routes/NewResource/NewRoute.tsx
+++ b/browser/data-browser/src/routes/NewResource/NewRoute.tsx
@@ -1,8 +1,7 @@
 import { useResource, core } from '@tomic/react';
-import { useCallback } from 'react';
-import { useNavigate } from 'react-router';
+import { useCallback, type JSX } from 'react';
 
-import { constructOpenURL, useQueryString } from '../../helpers/navigation';
+import { constructOpenURL } from '../../helpers/navigation';
 import {
   ContainerFull,
   ContainerNarrow,
@@ -21,10 +20,33 @@ import { OntologySections } from './OntologySections';
 import { useNewResourceUI } from '../../components/forms/NewForm/useNewResourceUI';
 import { Column } from '../../components/Row';
 import { TemplateList } from '../../components/Template/TemplateList';
+import { useNavigateWithTransition } from '../../hooks/useNavigateWithTransition';
+import { pathNames } from '../paths';
+import { createRoute } from '@tanstack/react-router';
+import { appRoute } from '../RootRoutes';
+
+export interface NewRouteSearchParams {
+  classSubject: string | undefined;
+  parent: string | undefined;
+  parentSubject: string | undefined;
+  newSubject: string | undefined;
+}
+
+export const NewRoute = createRoute({
+  path: pathNames.new,
+  component: () => <NewRoutePage />,
+  getParentRoute: () => appRoute,
+  validateSearch: (search: Record<string, unknown>): NewRouteSearchParams => ({
+    classSubject: (search.classSubject as string) ?? undefined,
+    parent: (search.parent as string) ?? undefined,
+    parentSubject: (search.parentSubject as string) ?? undefined,
+    newSubject: (search.newSubject as string) ?? undefined,
+  }),
+});
 
 /** Start page for instantiating a new Resource from some Class */
-function NewRoute(): JSX.Element {
-  const [classSubject] = useQueryString('classSubject');
+function NewRoutePage(): JSX.Element {
+  const { classSubject } = NewRoute.useSearch();
 
   return (
     <Main>
@@ -42,7 +64,7 @@ function NewRoute(): JSX.Element {
 }
 
 function NewResourceSelector() {
-  const [parentSubject] = useQueryString('parentSubject');
+  const { parentSubject } = NewRoute.useSearch();
   const { drive, hideTemplates } = useSettings();
   const calculatedParent = parentSubject || drive;
   const parentResource = useResource(calculatedParent);
@@ -50,7 +72,7 @@ function NewResourceSelector() {
   const showTemplates = !hideTemplates && calculatedParent === drive;
   const Container = showTemplates ? ContainerWide : ContainerNarrow;
 
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
   const showNewResourceUI = useNewResourceUI();
 
   function handleClassSet(subject: string | undefined) {
@@ -128,5 +150,3 @@ const SideBySide = styled.div<{ noTemplates: boolean }>`
 const Devider = styled.div`
   border-right: 1px solid ${p => p.theme.colors.bg2};
 `;
-
-export default NewRoute;
diff --git a/browser/data-browser/src/routes/NewResource/OntologySections.tsx b/browser/data-browser/src/routes/NewResource/OntologySections.tsx
index 846d4b9fe..69115d8a5 100644
--- a/browser/data-browser/src/routes/NewResource/OntologySections.tsx
+++ b/browser/data-browser/src/routes/NewResource/OntologySections.tsx
@@ -1,7 +1,7 @@
 import { OutlinedSection } from '../../components/OutlinedSection';
 import { Core, core, useResource, useServerSearch } from '@tomic/react';
 import { ClassButton } from './ClassButton';
-import { FC } from 'react';
+import { FC, type JSX } from 'react';
 import { useSettings } from '../../helpers/AppSettings';
 
 interface OntologySectionsProps {
diff --git a/browser/data-browser/src/routes/PruneTestsRoute.tsx b/browser/data-browser/src/routes/PruneTestsRoute.tsx
index 98c4f29c6..3fb32493a 100644
--- a/browser/data-browser/src/routes/PruneTestsRoute.tsx
+++ b/browser/data-browser/src/routes/PruneTestsRoute.tsx
@@ -3,8 +3,9 @@ import { useState } from 'react';
 import { Button } from '../components/Button';
 import { ContainerFull } from '../components/Containers';
 import { Column } from '../components/Row';
+import { createLazyRoute } from '@tanstack/react-router';
 
-export function PruneTestsRoute(): JSX.Element {
+const PruneTestsRoute: React.FC = () => {
   const store = useStore();
   const [result, setResult] = useState<Resource<Server.EndpointResponse>>();
   const [isWaiting, setIsWaiting] = useState(false);
@@ -37,4 +38,8 @@ export function PruneTestsRoute(): JSX.Element {
       </ContainerFull>
     </main>
   );
-}
+};
+
+export const pruneTestRouteLazy = createLazyRoute('/$')({
+  component: PruneTestsRoute,
+});
diff --git a/browser/data-browser/src/routes/RootRoutes.tsx b/browser/data-browser/src/routes/RootRoutes.tsx
new file mode 100644
index 000000000..c9c7b88da
--- /dev/null
+++ b/browser/data-browser/src/routes/RootRoutes.tsx
@@ -0,0 +1,42 @@
+import {
+  createRootRoute,
+  createRoute,
+  Outlet,
+  useLocation,
+} from '@tanstack/react-router';
+import { pathNames } from './paths';
+// import { TanStackRouterDevtools } from '@tanstack/router-devtools';
+import { Providers } from '../Providers';
+import ResourcePage from '../views/ResourcePage';
+
+export const appRoute = createRoute({
+  getParentRoute: () => rootRoute,
+  path: pathNames.app,
+  component: () => <Outlet />,
+  notFoundComponent: () => <p>404 Not found</p>,
+});
+
+export const rootRoute = createRootRoute({
+  component: () => (
+    <Providers>
+      <Outlet />
+      {/* Uncomment to get Tanstack Router Devtools */}
+      {/* <TanStackRouterDevtools position='bottom-right' /> */}
+    </Providers>
+  ),
+});
+
+const TopRouteComponent: React.FC = () => {
+  const { href } = useLocation();
+
+  // We need to combine origin with tanstack's href because tanstack does not include the origin in the href but the normal window.location.href is not reactive.
+  const subject = window.location.origin + href;
+
+  return <ResourcePage subject={subject} key={subject} />;
+};
+
+export const topRoute = createRoute({
+  path: '$',
+  component: TopRouteComponent,
+  getParentRoute: () => rootRoute,
+});
diff --git a/browser/data-browser/src/routes/Router.tsx b/browser/data-browser/src/routes/Router.tsx
new file mode 100644
index 000000000..792277f22
--- /dev/null
+++ b/browser/data-browser/src/routes/Router.tsx
@@ -0,0 +1,81 @@
+import { createRoute, createRouter, Link } from '@tanstack/react-router';
+import { ShowRoute } from './ShowRoute';
+import { SearchRoute } from './SearchRoute';
+import { NewRoute } from './NewResource/NewRoute';
+import { AppSettingsRoute } from './AppSettings';
+import { EditRoute } from './EditRoute';
+import { DataRoute } from './DataRoute';
+import { ShortcutsRoute } from './ShortcutsRoute';
+import { AboutRoute } from './AboutRoute';
+import { AgentSettingsRoute } from './SettingsAgent';
+import { ServerSettingsRoute } from './SettingsServer';
+import { pathNames } from './paths';
+import { ShareRoute } from './Share/ShareRoute';
+import { TokenRoute } from './TokenRoute';
+import { isDev } from '../config';
+import { rootRoute, topRoute, appRoute } from './RootRoutes';
+import { unavailableLazyRoute } from './UnavailableLazyRoute';
+import { ImportRoute } from './ImportRoute';
+import { HistoryRoute } from './History/HistoryRoute';
+
+const PruneTestsRoute = createRoute({
+  getParentRoute: () => appRoute,
+  path: pathNames.pruneTests,
+}).lazy(() => {
+  if (isDev()) {
+    return import('./PruneTestsRoute').then(mod => mod.pruneTestRouteLazy);
+  } else {
+    return Promise.resolve(unavailableLazyRoute);
+  }
+});
+
+const SandboxRoute = createRoute({
+  getParentRoute: () => appRoute,
+  path: pathNames.sandbox,
+}).lazy(() => {
+  if (isDev()) {
+    return import('./Sandbox').then(mod => mod.sandboxRouteLazy);
+  } else {
+    return Promise.resolve(unavailableLazyRoute);
+  }
+});
+
+const routeTree = rootRoute.addChildren({
+  appRoute: appRoute.addChildren({
+    ShowRoute,
+    SearchRoute,
+    AppSettingsRoute,
+    ShortcutsRoute,
+    AgentSettingsRoute,
+    ServerSettingsRoute,
+    DataRoute,
+    EditRoute,
+    ImportRoute,
+    ShareRoute,
+    AboutRoute,
+    TokenRoute,
+    HistoryRoute,
+    NewRoute,
+    PruneTestsRoute,
+    SandboxRoute,
+  }),
+  topRoute,
+});
+
+export const router = createRouter({
+  routeTree,
+  defaultNotFoundComponent: () => {
+    return (
+      <div>
+        <p>Not found!</p>
+        <Link to='/'>Go home</Link>
+      </div>
+    );
+  },
+});
+
+declare module '@tanstack/react-router' {
+  interface Register {
+    router: typeof router;
+  }
+}
diff --git a/browser/data-browser/src/routes/Routes.tsx b/browser/data-browser/src/routes/Routes.tsx
deleted file mode 100644
index 3c4cc7d40..000000000
--- a/browser/data-browser/src/routes/Routes.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-/// <reference types="vite/client" />
-
-import { Route, Routes } from 'react-router-dom';
-
-import Show from './ShowRoute';
-import { Search } from './SearchRoute';
-import NewRoute from './NewResource/NewRoute';
-import { SettingsTheme } from './SettingsTheme';
-import { Edit } from './EditRoute';
-import Data from './DataRoute';
-import { Shortcuts } from './ShortcutsRoute';
-import { About as About } from './AboutRoute';
-import Local from './LocalRoute';
-import SettingsAgent from './SettingsAgent';
-import { SettingsServer } from './SettingsServer';
-import { paths } from './paths';
-import ResourcePage from '../views/ResourcePage';
-import { ShareRoute } from './Share/ShareRoute';
-import { Sandbox } from './Sandbox';
-import { TokenRoute } from './TokenRoute';
-import { ImporterPage } from '../views/ImporterPage';
-import { History } from './History';
-import { PruneTestsRoute } from './PruneTestsRoute';
-
-const homeURL = window.location.origin;
-
-const isDev = import.meta.env.MODE === 'development';
-
-/**
- * Handles the browser URL navigation paths. Some rules:
- *
- * - Resource defined by this app should start with `/app`
- * - The home page should show the atomic data resource of the same URL
- */
-export function AppRoutes(): JSX.Element {
-  return (
-    <Routes>
-      <Route path={paths.new} element={<NewRoute />} />
-      <Route path={paths.themeSettings} element={<SettingsTheme />} />
-      <Route path={paths.agentSettings} element={<SettingsAgent />} />
-      <Route path={paths.serverSettings} element={<SettingsServer />} />
-      <Route path={paths.shortcuts} element={<Shortcuts />} />
-      <Route path={paths.data} element={<Data />} />
-      <Route path={paths.edit} element={<Edit />} />
-      <Route path={paths.import} element={<ImporterPage />} />
-      <Route path={paths.share} element={<ShareRoute />} />
-      <Route path={paths.show} element={<Show />} />
-      <Route path={paths.about} element={<About />} />
-      <Route path={paths.search} element={<Search />} />
-      <Route path={paths.token} element={<TokenRoute />} />
-      <Route path={paths.history} element={<History />} />
-      {isDev && <Route path={paths.pruneTests} element={<PruneTestsRoute />} />}
-      {isDev && <Route path={paths.sandbox} element={<Sandbox />} />}
-      <Route path='/' element={<ResourcePage subject={homeURL} />} />
-      <Route path='*' element={<Local />} />
-    </Routes>
-  );
-}
diff --git a/browser/data-browser/src/routes/Sandbox.tsx b/browser/data-browser/src/routes/Sandbox.tsx
index 8685fc42f..93a560bcf 100644
--- a/browser/data-browser/src/routes/Sandbox.tsx
+++ b/browser/data-browser/src/routes/Sandbox.tsx
@@ -1,6 +1,9 @@
+import { createLazyRoute } from '@tanstack/react-router';
 import { ContainerFull } from '../components/Containers';
 
-export function Sandbox(): JSX.Element {
+import type { JSX } from 'react';
+
+function Sandbox(): JSX.Element {
   return (
     <main>
       <ContainerFull>
@@ -13,3 +16,7 @@ export function Sandbox(): JSX.Element {
     </main>
   );
 }
+
+export const sandboxRouteLazy = createLazyRoute('/$')({
+  component: Sandbox,
+});
diff --git a/browser/data-browser/src/routes/SearchRoute.tsx b/browser/data-browser/src/routes/SearchRoute.tsx
index f0ddc4ef0..5bb9d80e0 100644
--- a/browser/data-browser/src/routes/SearchRoute.tsx
+++ b/browser/data-browser/src/routes/SearchRoute.tsx
@@ -1,8 +1,7 @@
-import { useRef, useState } from 'react';
+import { useRef, useState, type JSX } from 'react';
 import { ContainerNarrow } from '../components/Containers';
 import { useHotkeys } from 'react-hotkeys-hook';
-import { useNavigate } from 'react-router-dom';
-import { constructOpenURL, useSearchQuery } from '../helpers/navigation';
+import { constructOpenURL } from '../helpers/navigation';
 import ResourceCard from '../views/Card/ResourceCard';
 import { useServerSearch } from '@tomic/react';
 import { ErrorLook } from '../components/ErrorLook';
@@ -12,22 +11,35 @@ import { useQueryScopeHandler } from '../hooks/useQueryScope';
 import { useSettings } from '../helpers/AppSettings';
 import { Column } from '../components/Row';
 import { Main } from '../components/Main';
+import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
+import { createRoute } from '@tanstack/react-router';
+import { pathNames } from './paths';
+import { appRoute } from './RootRoutes';
+
+type SearchRouteQueryParams = {
+  query?: string;
+  queryscope?: string;
+};
+
+export const SearchRoute = createRoute({
+  path: pathNames.search,
+  component: () => <Search />,
+  getParentRoute: () => appRoute,
+  validateSearch: {
+    parse: (search: Record<string, unknown>): SearchRouteQueryParams => {
+      return {
+        query: (search.query as string) ?? undefined,
+        queryscope: (search.queryscope as string) ?? undefined,
+      };
+    },
+  },
+});
 
 /** Full text search route */
 export function Search(): JSX.Element {
-  const [query] = useSearchQuery();
+  const query = SearchRoute.useSearch({ select: state => state.query });
   const { drive } = useSettings();
   const { scope } = useQueryScopeHandler();
-  const [enableFilter, setEnableFilter] = useState(false);
-
-  useHotkeys(
-    'f12',
-    e => {
-      e.preventDefault();
-      setEnableFilter(!enableFilter);
-    },
-    [enableFilter],
-  );
 
   const [selectedIndex, setSelected] = useState(0);
   const { results, loading, error } = useServerSearch(query, {
@@ -35,7 +47,7 @@ export function Search(): JSX.Element {
     parents: scope || drive,
     include: true,
   });
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
   const resultsDiv = useRef<HTMLDivElement | null>(null);
 
   function selectResult(index: number) {
@@ -68,6 +80,7 @@ export function Search(): JSX.Element {
       selectResult(newSelected);
     },
     { enableOnTags: ['INPUT'] },
+    [selectedIndex, selectResult],
   );
   useHotkeys(
     'down',
@@ -80,6 +93,7 @@ export function Search(): JSX.Element {
       selectResult(newSelected);
     },
     { enableOnTags: ['INPUT'] },
+    [selectedIndex, selectResult],
   );
 
   let message: string | undefined = 'No hits';
diff --git a/browser/data-browser/src/routes/SettingsAgent.tsx b/browser/data-browser/src/routes/SettingsAgent.tsx
index 44dc5ed41..3191b9f66 100644
--- a/browser/data-browser/src/routes/SettingsAgent.tsx
+++ b/browser/data-browser/src/routes/SettingsAgent.tsx
@@ -16,10 +16,19 @@ import { ResourceInline } from '../views/ResourceInline';
 import { ContainerNarrow } from '../components/Containers';
 import { AtomicLink } from '../components/AtomicLink';
 import { editURL } from '../helpers/navigation';
-import { useNavigate } from 'react-router';
 import { Main } from '../components/Main';
 import { Column } from '../components/Row';
 import { WarningBlock } from '../components/WarningBlock';
+import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
+import { createRoute } from '@tanstack/react-router';
+import { pathNames } from './paths';
+import { appRoute } from './RootRoutes';
+
+export const AgentSettingsRoute = createRoute({
+  path: pathNames.agentSettings,
+  component: () => <SettingsAgent />,
+  getParentRoute: () => appRoute,
+});
 
 const SettingsAgent: React.FunctionComponent = () => {
   const { agent, setAgent } = useSettings();
@@ -29,7 +38,7 @@ const SettingsAgent: React.FunctionComponent = () => {
   const [showPrivateKey, setShowPrivateKey] = useState(false);
   const [advanced, setAdvanced] = useState(false);
   const [secret, setSecret] = useState<string | undefined>(undefined);
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
 
   // When there is an agent, set the advanced values
   // Otherwise, reset the secret value
@@ -278,5 +287,3 @@ const SettingsAgent: React.FunctionComponent = () => {
     </Main>
   );
 };
-
-export default SettingsAgent;
diff --git a/browser/data-browser/src/routes/SettingsServer/DrivesCard.tsx b/browser/data-browser/src/routes/SettingsServer/DrivesCard.tsx
index 508734f77..6488169de 100644
--- a/browser/data-browser/src/routes/SettingsServer/DrivesCard.tsx
+++ b/browser/data-browser/src/routes/SettingsServer/DrivesCard.tsx
@@ -5,6 +5,8 @@ import { styled } from 'styled-components';
 import { useSettings } from '../../helpers/AppSettings';
 import { DriveRow } from './DriveRow';
 
+import type { JSX } from 'react';
+
 export interface DriveCardProps {
   drives: string[];
   showNewOption?: boolean;
diff --git a/browser/data-browser/src/routes/SettingsServer/WSIndicator.tsx b/browser/data-browser/src/routes/SettingsServer/WSIndicator.tsx
index 4d40a316c..771fe8062 100644
--- a/browser/data-browser/src/routes/SettingsServer/WSIndicator.tsx
+++ b/browser/data-browser/src/routes/SettingsServer/WSIndicator.tsx
@@ -1,5 +1,5 @@
 import { useStore } from '@tomic/react';
-import { useEffect, useState } from 'react';
+import { useEffect, useState, type JSX } from 'react';
 import { FaExclamationTriangle, FaSignal } from 'react-icons/fa';
 import { styled } from 'styled-components';
 import { useSettings } from '../../helpers/AppSettings';
diff --git a/browser/data-browser/src/routes/SettingsServer/index.tsx b/browser/data-browser/src/routes/SettingsServer/index.tsx
index fd7ce7dd2..bc3dc142e 100644
--- a/browser/data-browser/src/routes/SettingsServer/index.tsx
+++ b/browser/data-browser/src/routes/SettingsServer/index.tsx
@@ -4,7 +4,7 @@ import {
   InputWrapper,
   LabelStyled,
 } from '../../components/forms/InputStyles';
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { useSettings } from '../../helpers/AppSettings';
 import { ContainerWide } from '../../components/Containers';
 import { Column, Row } from '../../components/Row';
@@ -13,13 +13,22 @@ import { DrivesCard } from './DrivesCard';
 import { styled } from 'styled-components';
 import { useSavedDrives } from '../../hooks/useSavedDrives';
 import { constructOpenURL } from '../../helpers/navigation';
-import { useNavigate } from 'react-router';
 import { ErrorLook } from '../../components/ErrorLook';
 import { Main } from '../../components/Main';
+import { useNavigateWithTransition } from '../../hooks/useNavigateWithTransition';
+import { createRoute } from '@tanstack/react-router';
+import { pathNames } from '../paths';
+import { appRoute } from '../RootRoutes';
 
-export function SettingsServer(): JSX.Element {
+export const ServerSettingsRoute = createRoute({
+  path: pathNames.serverSettings,
+  component: () => <SettingsServer />,
+  getParentRoute: () => appRoute,
+});
+
+function SettingsServer(): JSX.Element {
   const { drive: baseURL, setDrive: setBaseURL } = useSettings();
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
   const [baseUrlInput, setBaseUrlInput] = useState<string>(baseURL);
   const [baseUrlErr, setErrBaseUrl] = useState<Error | undefined>();
 
diff --git a/browser/data-browser/src/routes/Share/AgentRights.tsx b/browser/data-browser/src/routes/Share/AgentRights.tsx
index c4ebe41a2..2cb430b30 100644
--- a/browser/data-browser/src/routes/Share/AgentRights.tsx
+++ b/browser/data-browser/src/routes/Share/AgentRights.tsx
@@ -6,6 +6,8 @@ import { ResourceInline } from '../../views/ResourceInline';
 import type { MergedRight } from './useRights';
 import { PermissionRow } from './PermissionRow';
 
+import type { JSX } from 'react';
+
 interface AgentRightsProps extends MergedRight {
   hideInherit?: boolean;
   handleSetRight?: (agent: string, write: boolean, setToTrue: boolean) => void;
diff --git a/browser/data-browser/src/routes/Share/ShareRoute.tsx b/browser/data-browser/src/routes/Share/ShareRoute.tsx
index 765b5a466..3eb2ecfec 100644
--- a/browser/data-browser/src/routes/Share/ShareRoute.tsx
+++ b/browser/data-browser/src/routes/Share/ShareRoute.tsx
@@ -1,14 +1,12 @@
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { useCanWrite, useResource } from '@tomic/react';
 import { ContainerNarrow } from '../../components/Containers';
-import { useCurrentSubject } from '../../helpers/useCurrentSubject';
 import { Card, CardInsideFull } from '../../components/Card';
 import { Button } from '../../components/Button';
 import { InviteForm } from '../../components/InviteForm';
 import toast from 'react-hot-toast';
 import { Title } from '../../components/Title';
 import { constructOpenURL } from '../../helpers/navigation';
-import { useNavigate } from 'react-router-dom';
 import { ErrorLook } from '../../components/ErrorLook';
 import { Column } from '../../components/Row';
 import { Main } from '../../components/Main';
@@ -18,15 +16,32 @@ import { AgentRights } from './AgentRights';
 import { useInheritedRights } from './useInheritedRights';
 import { PermissionRow } from './PermissionRow';
 import styled from 'styled-components';
+import { useNavigateWithTransition } from '../../hooks/useNavigateWithTransition';
+import { appRoute } from '../RootRoutes';
+import { pathNames } from '../paths';
+import { createRoute } from '@tanstack/react-router';
+
+export interface ShareRouteSearchParams {
+  subject: string;
+}
+
+export const ShareRoute = createRoute({
+  path: pathNames.share,
+  component: () => <SharePage />,
+  getParentRoute: () => appRoute,
+  validateSearch: search => ({
+    subject: search.subject as string,
+  }),
+});
 
 /** Form for managing and viewing rights for this resource */
-export function ShareRoute(): JSX.Element {
-  const [subject] = useCurrentSubject();
+function SharePage(): JSX.Element {
+  const { subject } = ShareRoute.useSearch();
   const resource = useResource(subject);
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
   const [showInviteForm, setShowInviteForm] = useState(false);
   const [err, setErr] = useState<Error | undefined>(undefined);
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
   const inheritedRights = useInheritedRights(resource);
 
   const [resourceRights, updateResourceRights] = useRights(resource, setErr);
diff --git a/browser/data-browser/src/routes/ShortcutsRoute.tsx b/browser/data-browser/src/routes/ShortcutsRoute.tsx
index ee4d1a43c..17535eec4 100644
--- a/browser/data-browser/src/routes/ShortcutsRoute.tsx
+++ b/browser/data-browser/src/routes/ShortcutsRoute.tsx
@@ -4,9 +4,18 @@ import { ContainerNarrow } from '../components/Containers';
 import { shortcuts } from '../components/HotKeyWrapper';
 import { Shortcut } from '../components/Shortcut';
 import { Main } from '../components/Main';
+import { createRoute } from '@tanstack/react-router';
+import { pathNames } from './paths';
+import { appRoute } from './RootRoutes';
+
+export const ShortcutsRoute = createRoute({
+  path: pathNames.shortcuts,
+  component: () => <Shortcuts />,
+  getParentRoute: () => appRoute,
+});
 
 /** List of all the keyboard shorcuts */
-export const Shortcuts: React.FunctionComponent = () => {
+const Shortcuts: React.FunctionComponent = () => {
   return (
     <Main>
       <ContainerNarrow>
diff --git a/browser/data-browser/src/routes/ShowRoute.tsx b/browser/data-browser/src/routes/ShowRoute.tsx
index 9bb437973..097860de4 100644
--- a/browser/data-browser/src/routes/ShowRoute.tsx
+++ b/browser/data-browser/src/routes/ShowRoute.tsx
@@ -1,14 +1,29 @@
 import * as React from 'react';
 import { Client } from '@tomic/react';
 import ResourcePage from '../views/ResourcePage';
-import { useCurrentSubject } from '../helpers/useCurrentSubject';
 import { Search } from './SearchRoute';
 import { About } from './AboutRoute';
+import { createRoute } from '@tanstack/react-router';
+import { appRoute } from './RootRoutes';
+import { pathNames } from './paths';
+
+export type ShowRouteSearch = {
+  subject: string;
+};
+
+export const ShowRoute = createRoute({
+  path: pathNames.show,
+  component: () => <ShowComponent />,
+  getParentRoute: () => appRoute,
+  validateSearch: (search): ShowRouteSearch => ({
+    subject: (search.subject as string) ?? '',
+  }),
+});
 
 /** Renders either the Welcome page, an Individual resource, or search results. */
-const Show: React.FunctionComponent = () => {
+export const ShowComponent: React.FunctionComponent = () => {
   // Value shown in navbar, after Submitting
-  const [subject] = useCurrentSubject();
+  const subject = ShowRoute.useSearch({ select: state => state.subject });
 
   if (subject === undefined || subject === '') {
     return <About />;
@@ -20,5 +35,3 @@ const Show: React.FunctionComponent = () => {
     return <Search />;
   }
 };
-
-export default Show;
diff --git a/browser/data-browser/src/routes/TokenRoute.tsx b/browser/data-browser/src/routes/TokenRoute.tsx
index 0f0f4d136..f48a02aba 100644
--- a/browser/data-browser/src/routes/TokenRoute.tsx
+++ b/browser/data-browser/src/routes/TokenRoute.tsx
@@ -4,9 +4,18 @@ import { CodeBlock } from '../components/CodeBlock';
 import { createAuthentication, useServerURL } from '@tomic/react';
 import { useSettings } from '../helpers/AppSettings';
 import { Main } from '../components/Main';
+import { pathNames } from './paths';
+import { appRoute } from './RootRoutes';
+import { createRoute } from '@tanstack/react-router';
+
+export const TokenRoute = createRoute({
+  path: pathNames.token,
+  component: () => <TokenRoutePage />,
+  getParentRoute: () => appRoute,
+});
 
 /** Lets user create bearer tokens */
-export const TokenRoute: React.FunctionComponent = () => {
+const TokenRoutePage: React.FunctionComponent = () => {
   const [token, setToken] = React.useState('');
   const { agent } = useSettings();
   const [server] = useServerURL();
diff --git a/browser/data-browser/src/routes/UnavailableLazyRoute.tsx b/browser/data-browser/src/routes/UnavailableLazyRoute.tsx
new file mode 100644
index 000000000..3ece7c41b
--- /dev/null
+++ b/browser/data-browser/src/routes/UnavailableLazyRoute.tsx
@@ -0,0 +1,5 @@
+import { createLazyRoute } from '@tanstack/react-router';
+
+export const unavailableLazyRoute = createLazyRoute('/$')({
+  component: () => <div>Unavailable</div>,
+});
diff --git a/browser/data-browser/src/routes/paths.tsx b/browser/data-browser/src/routes/paths.tsx
index 66531d2a7..8fe7f169b 100644
--- a/browser/data-browser/src/routes/paths.tsx
+++ b/browser/data-browser/src/routes/paths.tsx
@@ -1,20 +1,43 @@
-export const paths = {
-  agentSettings: '/app/agent',
-  themeSettings: '/app/theme',
-  serverSettings: '/app/server',
-  new: '/app/new',
-  shortcuts: '/app/shortcuts',
-  search: '/app/search',
-  share: '/app/share',
-  show: '/app/show',
-  token: '/app/token',
-  data: '/app/data',
-  edit: '/app/edit',
-  about: '/app/about',
-  import: '/app/import',
-  history: '/app/history',
+export const pathNames = {
+  // Main app route
+  app: '/app',
+  // sub routes
+  agentSettings: '/agent',
+  appSettings: '/settings',
+  serverSettings: '/server',
+  new: '/new',
+  shortcuts: '/shortcuts',
+  search: '/search',
+  share: '/share',
+  show: '/show',
+  token: '/token',
+  data: '/data',
+  edit: '/edit',
+  about: '/about',
+  import: '/import',
+  history: '/history',
   allVersions: '/all-versions',
   sandbox: '/sandbox',
   fetchBookmark: '/fetch-bookmark',
   pruneTests: '/prunetests',
-};
+} as const;
+export const paths = {
+  agentSettings: `${pathNames.app}${pathNames.agentSettings}`,
+  appSettings: `${pathNames.app}${pathNames.appSettings}`,
+  serverSettings: `${pathNames.app}${pathNames.serverSettings}`,
+  new: `${pathNames.app}${pathNames.new}`,
+  shortcuts: `${pathNames.app}${pathNames.shortcuts}`,
+  search: `${pathNames.app}${pathNames.search}`,
+  share: `${pathNames.app}${pathNames.share}`,
+  show: `${pathNames.app}${pathNames.show}`,
+  token: `${pathNames.app}${pathNames.token}`,
+  data: `${pathNames.app}${pathNames.data}`,
+  edit: `${pathNames.app}${pathNames.edit}`,
+  about: `${pathNames.app}${pathNames.about}`,
+  import: `${pathNames.app}${pathNames.import}`,
+  history: `${pathNames.app}${pathNames.history}`,
+  allVersions: `${pathNames.app}${pathNames.allVersions}`,
+  sandbox: `${pathNames.app}${pathNames.sandbox}`,
+  fetchBookmark: pathNames.fetchBookmark,
+  pruneTests: `${pathNames.app}${pathNames.pruneTests}`,
+} as const;
diff --git a/browser/data-browser/src/styling.tsx b/browser/data-browser/src/styling.tsx
index 94f9e0f72..7141aa0fc 100644
--- a/browser/data-browser/src/styling.tsx
+++ b/browser/data-browser/src/styling.tsx
@@ -5,7 +5,7 @@ import {
 } from 'styled-components';
 import { darken, lighten, setLightness } from 'polished';
 import './reset.css';
-import { useContext } from 'react';
+import { useContext, type JSX } from 'react';
 import { SettingsContext } from './helpers/AppSettings';
 import { CurrentBackgroundColor } from './globalCssVars';
 
diff --git a/browser/data-browser/src/views/AgentPage.tsx b/browser/data-browser/src/views/AgentPage.tsx
index 8f56b6808..65dca667b 100644
--- a/browser/data-browser/src/views/AgentPage.tsx
+++ b/browser/data-browser/src/views/AgentPage.tsx
@@ -6,6 +6,8 @@ import { ResourceInline } from './ResourceInline';
 import { ValueForm } from '../components/forms/ValueForm';
 import { ResourcePageProps } from './ResourcePage';
 
+import type { JSX } from 'react';
+
 /** A View for Drives, which function similar to a homepage or dashboard. */
 function AgentPage({ resource }: ResourcePageProps): JSX.Element {
   const [title] = useTitle(resource);
diff --git a/browser/data-browser/src/views/Article/ArticleCard.tsx b/browser/data-browser/src/views/Article/ArticleCard.tsx
index 3a4fa2ed2..4b4d3dd33 100644
--- a/browser/data-browser/src/views/Article/ArticleCard.tsx
+++ b/browser/data-browser/src/views/Article/ArticleCard.tsx
@@ -10,6 +10,8 @@ import {
 import { ViewTransitionProps } from '../../helpers/ViewTransitionProps';
 import { CardViewProps } from '../Card/CardViewProps';
 
+import type { JSX } from 'react';
+
 const TRUNCATE_THRESHOLD = 200;
 
 export function ArticleCard({ resource }: CardViewProps): JSX.Element {
diff --git a/browser/data-browser/src/views/Article/ArticleCover.tsx b/browser/data-browser/src/views/Article/ArticleCover.tsx
index 334aeccad..3efb77509 100644
--- a/browser/data-browser/src/views/Article/ArticleCover.tsx
+++ b/browser/data-browser/src/views/Article/ArticleCover.tsx
@@ -1,5 +1,5 @@
 import { properties, Resource, useResource, useString } from '@tomic/react';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { FileDropzoneInput } from '../../components/forms/FileDropzone/FileDropzoneInput';
 import { transition } from '../../helpers/transition';
diff --git a/browser/data-browser/src/views/Article/ArticleDescription.tsx b/browser/data-browser/src/views/Article/ArticleDescription.tsx
index 44032c941..aa9e2eaad 100644
--- a/browser/data-browser/src/views/Article/ArticleDescription.tsx
+++ b/browser/data-browser/src/views/Article/ArticleDescription.tsx
@@ -1,5 +1,5 @@
 import { Resource, useString, core } from '@tomic/react';
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 
 import toast from 'react-hot-toast';
 import { FaEdit, FaPlus } from 'react-icons/fa';
diff --git a/browser/data-browser/src/views/Article/ArticlePage.tsx b/browser/data-browser/src/views/Article/ArticlePage.tsx
index 4b8f968aa..473eb6f11 100644
--- a/browser/data-browser/src/views/Article/ArticlePage.tsx
+++ b/browser/data-browser/src/views/Article/ArticlePage.tsx
@@ -5,7 +5,7 @@ import {
   useChildren,
   useString,
 } from '@tomic/react';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { CommitDetail } from '../../components/CommitDetail';
 import { ContainerWide } from '../../components/Containers';
@@ -22,7 +22,7 @@ import { useNewResourceUI } from '../../components/forms/NewForm/useNewResourceU
 export function ArticlePage({ resource }: ResourcePageProps): JSX.Element {
   const [lastCommit] = useString(resource, commits.properties.lastCommit);
 
-  const [canEdit] = useCanWrite(resource);
+  const canEdit = useCanWrite(resource);
   const children = useChildren(resource);
 
   const showNewResourceUI = useNewResourceUI();
diff --git a/browser/data-browser/src/views/BookmarkPage/BookmarkPage.tsx b/browser/data-browser/src/views/BookmarkPage/BookmarkPage.tsx
index 205942354..06821cfc4 100644
--- a/browser/data-browser/src/views/BookmarkPage/BookmarkPage.tsx
+++ b/browser/data-browser/src/views/BookmarkPage/BookmarkPage.tsx
@@ -1,5 +1,5 @@
 import { ResourcePageProps } from '../ResourcePage';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { urls, useCanWrite, useString } from '@tomic/react';
 import { EditableTitle } from '../../components/EditableTitle';
 import { styled } from 'styled-components';
@@ -20,7 +20,7 @@ export function BookmarkPage({ resource }: ResourcePageProps): JSX.Element {
 
   const { preview, error, update, loading } = usePreview(resource);
 
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
 
   const handleUrlChange = useCallback(
     async (e: React.ChangeEvent<HTMLInputElement>) => {
diff --git a/browser/data-browser/src/views/BookmarkPage/BookmarkPreview.tsx b/browser/data-browser/src/views/BookmarkPage/BookmarkPreview.tsx
index ca4d0a412..2f6586cce 100644
--- a/browser/data-browser/src/views/BookmarkPage/BookmarkPreview.tsx
+++ b/browser/data-browser/src/views/BookmarkPage/BookmarkPreview.tsx
@@ -3,6 +3,8 @@ import { ContainerNarrow } from '../../components/Containers.jsx';
 import Markdown from '../../components/datatypes/Markdown.jsx';
 import { ErrorLook } from '../../components/ErrorLook';
 
+import type { JSX } from 'react';
+
 export interface BookmarkPreviewProps {
   preview: string;
   error?: Error;
diff --git a/browser/data-browser/src/views/Card/BookmarkCard.tsx b/browser/data-browser/src/views/Card/BookmarkCard.tsx
index fedfb2c5b..65ae33602 100644
--- a/browser/data-browser/src/views/Card/BookmarkCard.tsx
+++ b/browser/data-browser/src/views/Card/BookmarkCard.tsx
@@ -10,6 +10,8 @@ import { CardViewProps } from './CardViewProps';
 import { ResourceCardTitle } from './ResourceCardTitle';
 import { Column } from '../../components/Row';
 
+import type { JSX } from 'react';
+
 export function BookmarkCard({ resource }: CardViewProps): JSX.Element {
   const [url] = useString(resource, urls.properties.bookmark.url);
   const [preview] = useString(resource, urls.properties.bookmark.preview);
diff --git a/browser/data-browser/src/views/Card/CollectionCard.tsx b/browser/data-browser/src/views/Card/CollectionCard.tsx
index 754999b5c..280738632 100644
--- a/browser/data-browser/src/views/Card/CollectionCard.tsx
+++ b/browser/data-browser/src/views/Card/CollectionCard.tsx
@@ -1,5 +1,5 @@
 import { useArray, useString, core, collections } from '@tomic/react';
-import { FC, PropsWithChildren, useState } from 'react';
+import { FC, PropsWithChildren, useState, type JSX } from 'react';
 
 import Markdown from '../../components/datatypes/Markdown';
 import { CardInsideFull, CardRow } from '../../components/Card';
diff --git a/browser/data-browser/src/views/Card/ElementCard.tsx b/browser/data-browser/src/views/Card/ElementCard.tsx
index 835355fa1..ad0535145 100644
--- a/browser/data-browser/src/views/Card/ElementCard.tsx
+++ b/browser/data-browser/src/views/Card/ElementCard.tsx
@@ -5,6 +5,8 @@ import { CardViewProps } from './CardViewProps';
 import { ResourceCardTitle } from './ResourceCardTitle';
 import { Column } from '../../components/Row';
 
+import type { JSX } from 'react';
+
 export function ElementCard({ resource }: CardViewProps): JSX.Element {
   const [documentSubject] = useString(resource, urls.properties.parent);
   const document = useResource(documentSubject);
diff --git a/browser/data-browser/src/views/Card/MessageCard.tsx b/browser/data-browser/src/views/Card/MessageCard.tsx
index 7883ba08f..9d9c4fc42 100644
--- a/browser/data-browser/src/views/Card/MessageCard.tsx
+++ b/browser/data-browser/src/views/Card/MessageCard.tsx
@@ -1,4 +1,4 @@
-import { useString, properties } from '@tomic/react';
+import { useString, core, commits } from '@tomic/react';
 
 import { CommitDetail } from '../../components/CommitDetail';
 import Markdown from '../../components/datatypes/Markdown';
@@ -8,9 +8,9 @@ import { ResourcePageProps } from '../ResourcePage';
 
 /** Card Message view that shows parent */
 export function MessageCard({ resource }: ResourcePageProps) {
-  const [description] = useString(resource, properties.description);
-  const [parent] = useString(resource, properties.parent);
-  const [lastCommit] = useString(resource, properties.commit.lastCommit);
+  const [description] = useString(resource, core.properties.description);
+  const [parent] = useString(resource, core.properties.parent);
+  const [lastCommit] = useString(resource, commits.properties.lastCommit);
 
   return (
     <>
diff --git a/browser/data-browser/src/views/Card/ResourceCard.tsx b/browser/data-browser/src/views/Card/ResourceCard.tsx
index a0a57d188..3753e0f53 100644
--- a/browser/data-browser/src/views/Card/ResourceCard.tsx
+++ b/browser/data-browser/src/views/Card/ResourceCard.tsx
@@ -1,4 +1,4 @@
-import { Suspense, useEffect, useState } from 'react';
+import { Suspense, useEffect, useState, type JSX } from 'react';
 import { useInView } from 'react-intersection-observer';
 import {
   useString,
diff --git a/browser/data-browser/src/views/ChatRoomPage.tsx b/browser/data-browser/src/views/ChatRoomPage.tsx
index 49f2c5d69..9a522d1de 100644
--- a/browser/data-browser/src/views/ChatRoomPage.tsx
+++ b/browser/data-browser/src/views/ChatRoomPage.tsx
@@ -14,7 +14,6 @@ import { memo, useCallback, useEffect, useRef, useState } from 'react';
 import toast from 'react-hot-toast';
 import { useHotkeys } from 'react-hotkeys-hook';
 import { FaCopy, FaLink, FaPencilAlt, FaReply, FaTimes } from 'react-icons/fa';
-import { useNavigate } from 'react-router-dom';
 import { styled } from 'styled-components';
 import { AtomicLink } from '../components/AtomicLink';
 import { Button } from '../components/Button';
@@ -26,6 +25,7 @@ import { NavBarSpacer } from '../components/NavBarSpacer';
 import { editURL } from '../helpers/navigation';
 import { ResourceInline } from './ResourceInline';
 import { ResourcePageProps } from './ResourcePage';
+import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
 
 /** Full page ChatRoom that shows a message list and a form to add Messages. */
 export function ChatRoomPage({ resource }: ResourcePageProps) {
@@ -99,12 +99,13 @@ export function ChatRoomPage({ resource }: ResourcePageProps) {
     }
   }
 
-  const handleReplyCallback = useCallback(handleReplyTo, [inputRef]);
-
-  function handleReplyTo(subject: string) {
-    setReplyTo(subject);
-    inputRef?.current?.focus();
-  }
+  const handleReply = useCallback(
+    (subject: string) => {
+      setReplyTo(subject);
+      inputRef?.current?.focus();
+    },
+    [setReplyTo],
+  );
 
   const handleChangeMessageText: React.ChangeEventHandler<
     HTMLTextAreaElement
@@ -136,10 +137,7 @@ export function ChatRoomPage({ resource }: ResourcePageProps) {
     <FullPageWrapper>
       <EditableTitle resource={resource} />
       <ScrollingContent ref={scrollRef}>
-        <MessagesPage
-          subject={resource.getSubject()}
-          setReplyTo={handleReplyCallback}
-        />
+        <MessagesPage subject={resource.subject} setReplyTo={handleReply} />
       </ScrollingContent>
       {isReplyTo && (
         <Detail>
@@ -190,8 +188,8 @@ const Message = memo(function Message({ subject, setReplyTo }: MessageProps) {
   const [description] = useString(resource, core.properties.description);
   const [lastCommit] = useSubject(resource, commits.properties.lastCommit);
   const [replyTo] = useSubject(resource, dataBrowser.properties.replyTo);
-  const navigate = useNavigate();
-  const [canWrite] = useCanWrite(resource);
+  const navigate = useNavigateWithTransition();
+  const canWrite = useCanWrite(resource);
 
   function handleCopyUrl() {
     navigator.clipboard.writeText(subject);
@@ -297,6 +295,7 @@ const MessageDetails = styled.div`
   margin-bottom: 0;
   opacity: 0.4;
   display: flex;
+  gap: 1ch;
   flex: 1;
 `;
 
@@ -307,6 +306,7 @@ const MessageActions = styled.div`
   justify-content: flex-end;
   flex: 1;
   opacity: 0;
+  gap: 0.5ch;
   margin-right: 1rem;
 `;
 
diff --git a/browser/data-browser/src/views/CollectionPage.tsx b/browser/data-browser/src/views/CollectionPage.tsx
index e467a39c6..ea3febfd9 100644
--- a/browser/data-browser/src/views/CollectionPage.tsx
+++ b/browser/data-browser/src/views/CollectionPage.tsx
@@ -36,6 +36,8 @@ import { Row } from '../components/Row';
 import { EditableTitle } from '../components/EditableTitle';
 import { useLocalStorage } from '../hooks/useLocalStorage';
 
+import type { JSX } from 'react';
+
 const displayStyles = [
   {
     id: 'cards',
diff --git a/browser/data-browser/src/views/CrashPage.tsx b/browser/data-browser/src/views/CrashPage.tsx
index 520f82586..1ece7985b 100644
--- a/browser/data-browser/src/views/CrashPage.tsx
+++ b/browser/data-browser/src/views/CrashPage.tsx
@@ -6,6 +6,8 @@ import { ErrorBlock } from '../components/ErrorLook';
 import { Button } from '../components/Button';
 import { Column, Row } from '../components/Row';
 
+import type { JSX } from 'react';
+
 type ErrorPageProps = {
   resource?: Resource;
   children?: React.ReactNode;
diff --git a/browser/data-browser/src/views/DocumentPage.tsx b/browser/data-browser/src/views/DocumentPage.tsx
index bcb943a34..71e4114f3 100644
--- a/browser/data-browser/src/views/DocumentPage.tsx
+++ b/browser/data-browser/src/views/DocumentPage.tsx
@@ -1,5 +1,4 @@
-import * as React from 'react';
-import { useState } from 'react';
+import { useRef, useEffect, useState, type JSX } from 'react';
 import { useHotkeys } from 'react-hotkeys-hook';
 import {
   Resource,
@@ -39,10 +38,10 @@ import { FileDropZone } from '../components/forms/FileDropzone/FileDropzone';
 
 /** A full page, editable document, consisting of Elements */
 export function DocumentPage({ resource }: ResourcePageProps): JSX.Element {
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
   const [editMode, setEditMode] = useState(canWrite);
 
-  React.useEffect(() => {
+  useEffect(() => {
     setEditMode(canWrite);
   }, [canWrite]);
 
@@ -74,11 +73,11 @@ function DocumentPageEdit({
     { commit: false, validate: false, commitDebounce: 0 },
   );
 
-  const titleRef = React.useRef<HTMLInputElement>(null);
+  const titleRef = useRef<HTMLInputElement>(null);
   const store = useStore();
-  const ref = React.useRef<HTMLInputElement>(null);
+  const ref = useRef<HTMLInputElement>(null);
   const [err, setErr] = useState<Error | undefined>(undefined);
-  const [current, setCurrent] = React.useState<number>(0);
+  const [current, setCurrent] = useState<number>(0);
 
   const sensors = useSensors(
     useSensor(PointerSensor),
@@ -88,12 +87,16 @@ function DocumentPageEdit({
   );
 
   // On init, focus on the last element
-  React.useEffect(() => {
+  useEffect(() => {
     setCurrent(elements.length - 1);
+
+    if (elements === undefined) {
+      setElements([]);
+    }
   }, []);
 
   // Always have one element
-  React.useEffect(() => {
+  useEffect(() => {
     if (elements.length === 0) {
       addElement(0);
     }
@@ -115,9 +118,10 @@ function DocumentPageEdit({
     e => {
       e.preventDefault();
       addElement(0);
+      focusElement(0);
     },
     { enableOnTags: ['INPUT'] },
-    [current],
+    [addElement, focusElement],
   );
 
   useHotkeys(
@@ -241,16 +245,14 @@ function DocumentPageEdit({
       return;
     }
 
-    elements.splice(number, 1);
-    setElements([...elements]);
+    setElements(elements.toSpliced(number, 1));
     focusElement(number - 1);
     resource.save();
   }
 
   /** Sets the subject for a specific element and moves to the next element */
   async function setElement(index: number, subject: string) {
-    elements[index] = subject;
-    setElements(elements);
+    setElements(elements.with(index, subject));
 
     if (index === elements.length - 1) {
       addElement(index + 1);
@@ -262,9 +264,7 @@ function DocumentPageEdit({
 
   function moveElement(from: number, to: number) {
     const element = elements[from];
-    elements.splice(from, 1);
-    elements.splice(to, 0, element);
-    setElements([...elements]);
+    setElements(elements.toSpliced(from, 1).toSpliced(to, 0, element));
     focusElement(to);
     resource.save();
   }
@@ -295,9 +295,17 @@ function DocumentPageEdit({
   /** Add a new line, or move to the last line if it is empty */
   async function handleNewLineMaybe() {
     const lastSubject = elements[elements.length - 1];
+
+    if (!lastSubject) {
+      addElement(elements.length);
+
+      return;
+    }
+
     const lastElem = await store.getResource(lastSubject);
+    const description = lastElem.get(core.properties.description);
 
-    if (lastElem.get(core.properties.description)?.toString()?.length === 0) {
+    if (description === undefined || description.length === 0) {
       focusElement(elements.length - 1);
     } else {
       addElement(elements.length);
@@ -361,7 +369,7 @@ function DocumentPageShow({
   setEditMode,
 }: DocumentSubPageProps): JSX.Element {
   const [elements] = useArray(resource, dataBrowser.properties.elements);
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
 
   return (
     <>
diff --git a/browser/data-browser/src/views/DrivePage.tsx b/browser/data-browser/src/views/DrivePage.tsx
index 66843c550..f7157a645 100644
--- a/browser/data-browser/src/views/DrivePage.tsx
+++ b/browser/data-browser/src/views/DrivePage.tsx
@@ -10,12 +10,14 @@ import { styled } from 'styled-components';
 import InputSwitcher from '../components/forms/InputSwitcher';
 import { WarningBlock } from '../components/WarningBlock';
 
+import type { JSX } from 'react';
+
 /** A View for Drives, which function similar to a homepage or dashboard. */
 function DrivePage({ resource }: ResourcePageProps): JSX.Element {
   const { drive: baseURL, setDrive: setBaseURL } = useSettings();
 
   const defaultOntologyProp = useProperty(server.properties.defaultOntology);
-  const [canEdit] = useCanWrite(resource);
+  const canEdit = useCanWrite(resource);
 
   if (!baseURL) {
     setBaseURL(resource.subject);
diff --git a/browser/data-browser/src/views/Element.tsx b/browser/data-browser/src/views/Element.tsx
index c429b9177..5918dd8c6 100644
--- a/browser/data-browser/src/views/Element.tsx
+++ b/browser/data-browser/src/views/Element.tsx
@@ -1,5 +1,5 @@
 import * as React from 'react';
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import {
   properties,
   classes,
@@ -70,7 +70,7 @@ export function ElementEdit({
   });
   const [klass] = useArray(resource, properties.isA);
   const ref = React.useRef<HTMLTextAreaElement>(null);
-  const [canWrite, canWriteErr] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
 
   /** If it is not a text element */
   const isAResource =
@@ -138,8 +138,8 @@ export function ElementEdit({
   function Err() {
     if (err?.message) {
       return <ErrorLook>{err.message}</ErrorLook>;
-    } else if (active && !canWrite && canWriteErr) {
-      return <ErrorLook>{canWriteErr}</ErrorLook>;
+    } else if (active && !canWrite) {
+      return <ErrorLook>Agent does not have edit rights</ErrorLook>;
     } else {
       return null;
     }
diff --git a/browser/data-browser/src/views/EndpointPage.tsx b/browser/data-browser/src/views/EndpointPage.tsx
index d5be90db6..5ab5c5f62 100644
--- a/browser/data-browser/src/views/EndpointPage.tsx
+++ b/browser/data-browser/src/views/EndpointPage.tsx
@@ -7,7 +7,6 @@ import {
   useString,
   useTitle,
 } from '@tomic/react';
-import { useNavigate } from 'react-router-dom';
 
 import { ContainerNarrow } from '../components/Containers';
 import Markdown from '../components/datatypes/Markdown';
@@ -16,6 +15,9 @@ import { Button } from '../components/Button';
 import { constructOpenURL } from '../helpers/navigation';
 import ResourceCard from './Card/ResourceCard';
 
+import type { JSX } from 'react';
+import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
+
 type EndpointProps = {
   resource: Resource;
 };
@@ -28,7 +30,7 @@ function EndpointPage({ resource }: EndpointProps): JSX.Element {
   const [results] = useArray(resource, properties.endpoint.results);
   const virtualResource = useResource(undefined, { newResource: true });
   const store = useStore();
-  const navigate = useNavigate();
+  const navigate = useNavigateWithTransition();
 
   /** Create the URL using the variables */
   async function constructSubject(e?: React.SyntheticEvent) {
diff --git a/browser/data-browser/src/views/ErrorPage.tsx b/browser/data-browser/src/views/ErrorPage.tsx
index 8f21f4d8d..fbe70c765 100644
--- a/browser/data-browser/src/views/ErrorPage.tsx
+++ b/browser/data-browser/src/views/ErrorPage.tsx
@@ -10,6 +10,8 @@ import { Column, Row } from '../components/Row';
 import CrashPage from './CrashPage';
 import { clearAllLocalData } from '../helpers/clearData';
 
+import type { JSX } from 'react';
+
 /**
  * A View for Resource Errors. Not to be confused with the CrashPage, which is
  * for App wide errors.
diff --git a/browser/data-browser/src/views/File/DownloadButton.tsx b/browser/data-browser/src/views/File/DownloadButton.tsx
index ba4591779..d79acbdca 100644
--- a/browser/data-browser/src/views/File/DownloadButton.tsx
+++ b/browser/data-browser/src/views/File/DownloadButton.tsx
@@ -5,6 +5,8 @@ import { IconButton } from '../../components/IconButton/IconButton';
 import { Row } from '../../components/Row';
 import { displayFileSize } from './displayFileSize';
 
+import type { JSX } from 'react';
+
 interface DownloadButtonProps {
   downloadFile: () => void;
   fileSize?: number;
diff --git a/browser/data-browser/src/views/File/FileCard.tsx b/browser/data-browser/src/views/File/FileCard.tsx
index 872febb3b..1d59574f0 100644
--- a/browser/data-browser/src/views/File/FileCard.tsx
+++ b/browser/data-browser/src/views/File/FileCard.tsx
@@ -1,4 +1,4 @@
-import { useMemo } from 'react';
+import { useMemo, type JSX } from 'react';
 import { AtomicLink } from '../../components/AtomicLink';
 import { Row } from '../../components/Row';
 import { useFileInfo } from '../../hooks/useFile';
@@ -13,7 +13,7 @@ function FileCard(props: CardViewProps): JSX.Element {
     const Temp = () => {
       return (
         <>
-          <AtomicLink subject={props.resource.getSubject()}>
+          <AtomicLink subject={props.resource.subject}>
             {props.resource.title}
           </AtomicLink>
           <div>Can not show file due to invalid data.</div>
@@ -21,10 +21,8 @@ function FileCard(props: CardViewProps): JSX.Element {
       );
     };
 
-    Temp.displayName = 'FileError';
-
     return Temp;
-  }, [props.resource.getSubject(), props.resource.title]);
+  }, [props.resource.subject, props.resource.title]);
 
   return (
     <ErrorBoundary FallBackComponent={FileError}>
diff --git a/browser/data-browser/src/views/File/FilePreview.tsx b/browser/data-browser/src/views/File/FilePreview.tsx
index 0bc171f11..27ff4dc67 100644
--- a/browser/data-browser/src/views/File/FilePreview.tsx
+++ b/browser/data-browser/src/views/File/FilePreview.tsx
@@ -1,4 +1,4 @@
-import { lazy, Suspense, useState } from 'react';
+import { lazy, Suspense, useState, type JSX } from 'react';
 import { Resource } from '@tomic/react';
 import { ImageViewer } from '../../components/ImageViewer';
 import { useFileInfo } from '../../hooks/useFile';
diff --git a/browser/data-browser/src/views/File/FilePreviewThumbnail.tsx b/browser/data-browser/src/views/File/FilePreviewThumbnail.tsx
index f6799bdda..5df0fc9b6 100644
--- a/browser/data-browser/src/views/File/FilePreviewThumbnail.tsx
+++ b/browser/data-browser/src/views/File/FilePreviewThumbnail.tsx
@@ -11,6 +11,8 @@ import { TextPreview } from './TextPreview';
 import { ErrorBoundary } from '../ErrorPage';
 import { Row } from '../../components/Row';
 
+import type { JSX } from 'react';
+
 interface FilePreviewThumbnailProps {
   resource: Resource;
 }
diff --git a/browser/data-browser/src/views/File/TextPreview.tsx b/browser/data-browser/src/views/File/TextPreview.tsx
index 77e3b4e98..e91ab8677 100644
--- a/browser/data-browser/src/views/File/TextPreview.tsx
+++ b/browser/data-browser/src/views/File/TextPreview.tsx
@@ -1,4 +1,4 @@
-import { useState, useEffect } from 'react';
+import { useState, useEffect, type JSX } from 'react';
 import { styled } from 'styled-components';
 import Markdown from '../../components/datatypes/Markdown';
 
diff --git a/browser/data-browser/src/views/FolderPage/DisplayStyleButton.tsx b/browser/data-browser/src/views/FolderPage/DisplayStyleButton.tsx
index 5a2c4c085..04bf99fd6 100644
--- a/browser/data-browser/src/views/FolderPage/DisplayStyleButton.tsx
+++ b/browser/data-browser/src/views/FolderPage/DisplayStyleButton.tsx
@@ -1,5 +1,5 @@
 import { classes } from '@tomic/react';
-import { useMemo } from 'react';
+import { useMemo, type JSX } from 'react';
 import { FaList, FaTh } from 'react-icons/fa';
 import { ButtonGroup } from '../../components/ButtonGroup';
 
diff --git a/browser/data-browser/src/views/FolderPage/GridItem/ArticleGridItem.tsx b/browser/data-browser/src/views/FolderPage/GridItem/ArticleGridItem.tsx
index bd56486f4..411089071 100644
--- a/browser/data-browser/src/views/FolderPage/GridItem/ArticleGridItem.tsx
+++ b/browser/data-browser/src/views/FolderPage/GridItem/ArticleGridItem.tsx
@@ -4,6 +4,8 @@ import { atomicArgu } from '../../../ontologies/atomic-argu';
 import { GridItemViewProps } from './GridItemViewProps';
 import { Thumbnail } from '../../../components/Thumbnail';
 
+import type { JSX } from 'react';
+
 export function ArticleGridItem({ resource }: GridItemViewProps): JSX.Element {
   const [coverImgSubject] = useSubject(
     resource,
diff --git a/browser/data-browser/src/views/FolderPage/GridItem/BasicGridItem.tsx b/browser/data-browser/src/views/FolderPage/GridItem/BasicGridItem.tsx
index a7cc86dc8..a7831c1db 100644
--- a/browser/data-browser/src/views/FolderPage/GridItem/BasicGridItem.tsx
+++ b/browser/data-browser/src/views/FolderPage/GridItem/BasicGridItem.tsx
@@ -3,6 +3,8 @@ import { properties, useString } from '@tomic/react';
 import { GridItemDescription, InnerWrapper } from './components';
 import { GridItemViewProps } from './GridItemViewProps';
 
+import type { JSX } from 'react';
+
 /** A simple view that only renders the description */
 export function BasicGridItem({ resource }: GridItemViewProps): JSX.Element {
   const [description] = useString(resource, properties.description);
diff --git a/browser/data-browser/src/views/FolderPage/GridItem/BookmarkGridItem.tsx b/browser/data-browser/src/views/FolderPage/GridItem/BookmarkGridItem.tsx
index b18854c4a..df4fd76b5 100644
--- a/browser/data-browser/src/views/FolderPage/GridItem/BookmarkGridItem.tsx
+++ b/browser/data-browser/src/views/FolderPage/GridItem/BookmarkGridItem.tsx
@@ -5,6 +5,8 @@ import { BasicGridItem } from './BasicGridItem';
 import { InnerWrapper } from './components';
 import { GridItemViewProps } from './GridItemViewProps';
 
+import type { JSX } from 'react';
+
 export function BookmarkGridItem({ resource }: GridItemViewProps): JSX.Element {
   const [imageUrl] = useString(resource, properties.bookmark.imageUrl);
 
diff --git a/browser/data-browser/src/views/FolderPage/GridItem/ChatRoomGridItem.tsx b/browser/data-browser/src/views/FolderPage/GridItem/ChatRoomGridItem.tsx
index 8e33ce2c9..4a5000ec2 100644
--- a/browser/data-browser/src/views/FolderPage/GridItem/ChatRoomGridItem.tsx
+++ b/browser/data-browser/src/views/FolderPage/GridItem/ChatRoomGridItem.tsx
@@ -11,6 +11,8 @@ import { styled } from 'styled-components';
 import { GridItemDescription, InnerWrapper } from './components';
 import { GridItemViewProps } from './GridItemViewProps';
 
+import type { JSX } from 'react';
+
 export function ChatRoomGridItem({ resource }: GridItemViewProps): JSX.Element {
   const [messages] = useArray(resource, properties.chatRoom.messages);
 
diff --git a/browser/data-browser/src/views/FolderPage/GridItem/DefaultGridItem.tsx b/browser/data-browser/src/views/FolderPage/GridItem/DefaultGridItem.tsx
index c59a4c812..2e5a8e4fe 100644
--- a/browser/data-browser/src/views/FolderPage/GridItem/DefaultGridItem.tsx
+++ b/browser/data-browser/src/views/FolderPage/GridItem/DefaultGridItem.tsx
@@ -2,6 +2,8 @@ import { styled } from 'styled-components';
 import { AllPropsSimple } from '../../../components/AllPropsSimple';
 import { GridItemViewProps } from './GridItemViewProps';
 
+import type { JSX } from 'react';
+
 export function DefaultGridItem({ resource }: GridItemViewProps): JSX.Element {
   return (
     <DefaultGridWrapper>
diff --git a/browser/data-browser/src/views/FolderPage/GridItem/DocumentGridItem.tsx b/browser/data-browser/src/views/FolderPage/GridItem/DocumentGridItem.tsx
index 8bfd82a0b..3a51dce5c 100644
--- a/browser/data-browser/src/views/FolderPage/GridItem/DocumentGridItem.tsx
+++ b/browser/data-browser/src/views/FolderPage/GridItem/DocumentGridItem.tsx
@@ -4,6 +4,8 @@ import Markdown from '../../../components/datatypes/Markdown';
 import { GridItemDescription, InnerWrapper } from './components';
 import { GridItemViewProps } from './GridItemViewProps';
 
+import type { JSX } from 'react';
+
 export function DocumentGridItem({ resource }: GridItemViewProps): JSX.Element {
   const [elements] = useArray(resource, properties.document.elements);
   const firstElementResource = useResource(elements[0]);
diff --git a/browser/data-browser/src/views/FolderPage/GridItem/ResourceGridItem.tsx b/browser/data-browser/src/views/FolderPage/GridItem/ResourceGridItem.tsx
index 38a75af4e..74475897c 100644
--- a/browser/data-browser/src/views/FolderPage/GridItem/ResourceGridItem.tsx
+++ b/browser/data-browser/src/views/FolderPage/GridItem/ResourceGridItem.tsx
@@ -6,7 +6,7 @@ import {
   useString,
   useTitle,
 } from '@tomic/react';
-import { useCallback, useMemo } from 'react';
+import { useCallback, useMemo, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { constructOpenURL } from '../../../helpers/navigation';
 import { getIconForClass } from '../../../helpers/iconMap';
diff --git a/browser/data-browser/src/views/FolderPage/GridView.tsx b/browser/data-browser/src/views/FolderPage/GridView.tsx
index 3f26924c8..f0619dd79 100644
--- a/browser/data-browser/src/views/FolderPage/GridView.tsx
+++ b/browser/data-browser/src/views/FolderPage/GridView.tsx
@@ -8,6 +8,8 @@ import {
 } from './GridItem/components';
 import { ResourceGridItem } from './GridItem/ResourceGridItem';
 
+import type { JSX } from 'react';
+
 export function GridView({
   subResources,
   onNewClick,
diff --git a/browser/data-browser/src/views/FolderPage/ListView.tsx b/browser/data-browser/src/views/FolderPage/ListView.tsx
index 62a0231b7..65569b7d9 100644
--- a/browser/data-browser/src/views/FolderPage/ListView.tsx
+++ b/browser/data-browser/src/views/FolderPage/ListView.tsx
@@ -14,6 +14,8 @@ import { getIconForClass } from '../../helpers/iconMap';
 import { FaPlus } from 'react-icons/fa';
 import { Button } from '../../components/Button';
 
+import type { JSX } from 'react';
+
 export function ListView({
   subResources,
   onNewClick,
@@ -34,7 +36,7 @@ export function ListView({
           </thead>
           <tbody>
             {Array.from(subResources.values()).map(resource => (
-              <TableRow key={resource.getSubject()}>
+              <TableRow key={resource.subject}>
                 <td>
                   <Title resource={resource} />
                 </td>
@@ -74,7 +76,7 @@ function Title({ resource }: CellProps): JSX.Element {
       <IconWrapper>
         <Icon />
       </IconWrapper>
-      <AtomicLink subject={resource.getSubject()}>{title}</AtomicLink>
+      <AtomicLink subject={resource.subject}>{title}</AtomicLink>
     </TitleWrapper>
   );
 }
@@ -94,6 +96,10 @@ function ClassType({ resource }: CellProps): JSX.Element {
   const classTypeResource = useResource(classType);
   const [title] = useTitle(classTypeResource);
 
+  if (resource.loading) {
+    return <LinkWrapper></LinkWrapper>;
+  }
+
   return (
     <LinkWrapper>
       <AtomicLink subject={classType}>{title}</AtomicLink>
diff --git a/browser/data-browser/src/views/FolderPage/index.tsx b/browser/data-browser/src/views/FolderPage/index.tsx
index 36a0c477b..9452627d1 100644
--- a/browser/data-browser/src/views/FolderPage/index.tsx
+++ b/browser/data-browser/src/views/FolderPage/index.tsx
@@ -56,7 +56,7 @@ export function FolderPage({
 
   const subResources = useResources(resource.props.subResources);
   const navigateToNewRoute = useNewRoute(resource.subject);
-  const [canEdit] = useCanWrite(resource);
+  const canEdit = useCanWrite(resource);
 
   return (
     <FullPageWrapper view={displayStyle!}>
diff --git a/browser/data-browser/src/views/InvitePage.tsx b/browser/data-browser/src/views/InvitePage.tsx
index 742f1e982..79fb5cd2a 100644
--- a/browser/data-browser/src/views/InvitePage.tsx
+++ b/browser/data-browser/src/views/InvitePage.tsx
@@ -5,9 +5,11 @@ import {
   useTitle,
   Agent,
   generateKeyPair,
-  properties,
+  server,
+  core,
+  useStore,
+  type Server,
 } from '@tomic/react';
-import { useNavigate, useNavigationType } from 'react-router-dom';
 
 import { ContainerNarrow } from '../components/Containers';
 import { ValueForm } from '../components/forms/ValueForm';
@@ -18,56 +20,100 @@ import { ResourcePageProps } from './ResourcePage';
 import { paths } from '../routes/paths';
 import { Row } from '../components/Row';
 
-// Whether Invites should automatically be accepted.
-const autoAccept = false;
+import type { JSX } from 'react';
+import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
+import { useNavState } from '../components/NavState';
+import { toast } from 'react-hot-toast';
 
 /** A View that opens an invite */
 function InvitePage({ resource }: ResourcePageProps): JSX.Element {
-  const [usagesLeft] = useNumber(resource, properties.invite.usagesLeft);
-  const [write] = useBoolean(resource, properties.invite.write);
-  const navigate = useNavigate();
-  const navigationType = useNavigationType();
+  const store = useStore();
+  const [usagesLeft] = useNumber(resource, server.properties.usagesLeft);
+  const [write] = useBoolean(resource, server.properties.write);
+  const navigate = useNavigateWithTransition();
+  const navigationType = useNavState();
   const { agent, setAgent } = useSettings();
   const agentResource = useResource(agent?.subject);
   const [agentTitle] = useTitle(agentResource, 15);
 
-  const agentSubject = agent?.subject;
-
-  if (autoAccept && agentSubject && usagesLeft && usagesLeft > 0) {
-    // Accept the invite if an agent subject is present, but not if the user just pressed the back button
-    if (navigationType !== 'POP') {
-      handleAccept(undefined);
-    }
-  }
-
   // When the Invite is accepted, a new Agent might be created.
   // When this happens, a new keypair is made, but the subject of the Agent is not yet known.
   // It will be created by the server, and will be accessible in the Redirect response.
   async function handleNew() {
     const keypair = await generateKeyPair();
     const newAgent = new Agent(keypair.privateKey);
+
     setAgent(newAgent);
-    const publicKey = await newAgent.getPublicKey();
-    handleAccept(publicKey);
+    handleAccept(keypair);
   }
 
-  function handleAccept(publicKey?: string) {
-    const inviteURL = new URL(resource.getSubject());
+  const handleAccept = async (keys?: {
+    publicKey: string;
+    privateKey: string;
+  }) => {
+    const inviteURL = new URL(resource.subject);
 
-    if (publicKey) {
-      inviteURL.searchParams.set('public-key', publicKey);
+    if (keys) {
+      inviteURL.searchParams.set('public-key', keys.publicKey);
     } else {
       inviteURL.searchParams.set('agent', agentSubject!);
     }
 
-    // Will be a `Redirect`, see RedirectPage
-    navigate(constructOpenURL(inviteURL.href));
+    const redirect = await store.getResource<Server.Redirect>(inviteURL.href);
+
+    if (redirect.props.redirectAgent && keys) {
+      const newAgent = new Agent(keys.privateKey, redirect.props.redirectAgent);
+      setAgent(newAgent);
+
+      showAgentCreatedToast();
+    }
+
+    // Go to the destination, unless the user just hit the back button
+    if (redirect.props.destination) {
+      // React needs a cycle to update the agent so we defer the next bit of code to after the render cycle so the store has the updated agent.
+      // If we don't do this the store would refetch the resource with the old agent that does not have access to the resource.
+      requestAnimationFrame(() => {
+        // Refetch the resource now that we have read access.
+        store
+          .fetchResourceFromServer(redirect.props.destination)
+          .then(() => {
+            navigate(constructOpenURL(redirect.props.destination));
+          })
+          .catch(err => {
+            console.error(err);
+          });
+      });
+    }
+  };
+
+  const showAgentCreatedToast = () => {
+    toast.success(
+      <div>
+        <p>New User created!</p>
+        <Button onClick={() => navigate(paths.agentSettings)}>
+          User Settings
+        </Button>
+      </div>,
+      { duration: 6000 },
+    );
+  };
+
+  const agentSubject = agent?.subject;
+
+  if (agentSubject && usagesLeft && usagesLeft > 0) {
+    // Accept the invite if an agent subject is present, but not if the user just pressed the back button
+    if (navigationType !== 'POP') {
+      handleAccept();
+    }
   }
 
   return (
     <ContainerNarrow>
       <h1>Invite to {write ? 'edit' : 'view'}</h1>
-      <ValueForm resource={resource} propertyURL={properties.description} />
+      <ValueForm
+        resource={resource}
+        propertyURL={core.properties.description}
+      />
       {usagesLeft === 0 ? (
         <em>Sorry, this Invite has no usages left. Ask for a new one.</em>
       ) : (
@@ -76,7 +122,7 @@ function InvitePage({ resource }: ResourcePageProps): JSX.Element {
             <>
               <Button
                 data-test='accept-existing'
-                onClick={() => handleAccept(undefined)}
+                onClick={() => handleAccept()}
               >
                 Accept as {agentTitle}
               </Button>
diff --git a/browser/data-browser/src/views/OntologyPage/Class/AddPropertyButton.tsx b/browser/data-browser/src/views/OntologyPage/Class/AddPropertyButton.tsx
index c21d50bdc..afb1f1610 100644
--- a/browser/data-browser/src/views/OntologyPage/Class/AddPropertyButton.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Class/AddPropertyButton.tsx
@@ -1,5 +1,5 @@
 import { Resource, core, useStore } from '@tomic/react';
-import { useRef, useState } from 'react';
+import { useRef, useState, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { transition } from '../../../helpers/transition';
 import { FaPlus } from 'react-icons/fa';
diff --git a/browser/data-browser/src/views/OntologyPage/Class/ClassCardRead.tsx b/browser/data-browser/src/views/OntologyPage/Class/ClassCardRead.tsx
index 263858ea7..e913a5121 100644
--- a/browser/data-browser/src/views/OntologyPage/Class/ClassCardRead.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Class/ClassCardRead.tsx
@@ -15,6 +15,8 @@ import {
 } from '../../../helpers/transitionName';
 import { NewClassInstanceButton } from './NewClassInstanceButton';
 
+import type { JSX } from 'react';
+
 interface ClassCardReadProps {
   subject: string;
 }
diff --git a/browser/data-browser/src/views/OntologyPage/Class/ClassCardWrite.tsx b/browser/data-browser/src/views/OntologyPage/Class/ClassCardWrite.tsx
index fb9fe7a5b..f193a0243 100644
--- a/browser/data-browser/src/views/OntologyPage/Class/ClassCardWrite.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Class/ClassCardWrite.tsx
@@ -1,5 +1,9 @@
+import {
+  ContextMenuOptions,
+  ResourceContextMenu,
+} from '../../../components/ResourceContextMenu';
 import { urls, useArray, useProperty, useResource } from '@tomic/react';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { Card } from '../../../components/Card';
 import { styled } from 'styled-components';
 import { FaCube } from 'react-icons/fa';
@@ -7,9 +11,6 @@ import { Column, Row } from '../../../components/Row';
 import { OntologyDescription } from '../OntologyDescription';
 import { PropertyLineWrite } from '../Property/PropertyLineWrite';
 import InputSwitcher from '../../../components/forms/InputSwitcher';
-import ResourceContextMenu, {
-  ContextMenuOptions,
-} from '../../../components/ResourceContextMenu';
 import { toAnchorId } from '../../../helpers/toAnchorId';
 import { AddPropertyButton } from './AddPropertyButton';
 import { ErrorChipInput } from '../../../components/forms/ErrorChip';
@@ -19,13 +20,12 @@ interface ClassCardWriteProps {
   subject: string;
 }
 
-const contextOptions = [
-  ContextMenuOptions.Open,
-  ContextMenuOptions.Delete,
-  ContextMenuOptions.History,
-];
-
 export function ClassCardWrite({ subject }: ClassCardWriteProps): JSX.Element {
+  const contextOptions = [
+    ContextMenuOptions.Open,
+    ContextMenuOptions.Delete,
+    ContextMenuOptions.History,
+  ];
   const resource = useResource(subject);
   const [requires, setRequires] = useArray(resource, urls.properties.requires, {
     commit: true,
diff --git a/browser/data-browser/src/views/OntologyPage/Class/NewClassInstanceButton.tsx b/browser/data-browser/src/views/OntologyPage/Class/NewClassInstanceButton.tsx
index 3eada6900..e3a2c98ea 100644
--- a/browser/data-browser/src/views/OntologyPage/Class/NewClassInstanceButton.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Class/NewClassInstanceButton.tsx
@@ -41,7 +41,7 @@ export function NewClassInstanceButton({
     setShowTableDialogWithParent(undefined);
   };
 
-  const trigger = buildDefaultTrigger(
+  const Trigger = buildDefaultTrigger(
     <PlusIcon />,
     `New instance of ${resource.title}`,
   );
@@ -69,7 +69,7 @@ export function NewClassInstanceButton({
 
   return (
     <>
-      <DropdownMenu items={newInstanceItems} trigger={trigger} />
+      <DropdownMenu items={newInstanceItems} Trigger={Trigger} />
       <ParentPickerDialog
         open={showParentPicker}
         onOpenChange={setShowParentPicker}
diff --git a/browser/data-browser/src/views/OntologyPage/Graph.tsx b/browser/data-browser/src/views/OntologyPage/Graph.tsx
index fbf6351f7..286be211e 100644
--- a/browser/data-browser/src/views/OntologyPage/Graph.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Graph.tsx
@@ -1,5 +1,5 @@
 import { Resource } from '@tomic/react';
-import { lazy, Suspense } from 'react';
+import { lazy, Suspense, type JSX } from 'react';
 import { styled } from 'styled-components';
 
 const OntologyGraph = lazy(
diff --git a/browser/data-browser/src/views/OntologyPage/InlineDatatype.tsx b/browser/data-browser/src/views/OntologyPage/InlineDatatype.tsx
index 420fa0821..39a78662b 100644
--- a/browser/data-browser/src/views/OntologyPage/InlineDatatype.tsx
+++ b/browser/data-browser/src/views/OntologyPage/InlineDatatype.tsx
@@ -11,6 +11,8 @@ import { ResourceInline } from '../ResourceInline';
 import { toAnchorId } from '../../helpers/toAnchorId';
 import { useOntologyContext } from './OntologyContext';
 
+import type { JSX } from 'react';
+
 interface TypeSuffixProps {
   resource: Resource<Core.Property>;
 }
diff --git a/browser/data-browser/src/views/OntologyPage/NewClassButton.tsx b/browser/data-browser/src/views/OntologyPage/NewClassButton.tsx
index 9df6e8242..071ad24bf 100644
--- a/browser/data-browser/src/views/OntologyPage/NewClassButton.tsx
+++ b/browser/data-browser/src/views/OntologyPage/NewClassButton.tsx
@@ -1,5 +1,5 @@
 import { Datatype, Resource, useStore, validateDatatype } from '@tomic/react';
-import { useRef, useState } from 'react';
+import { useRef, useState, type JSX } from 'react';
 import { FaPlus } from 'react-icons/fa';
 import { styled } from 'styled-components';
 import {
diff --git a/browser/data-browser/src/views/OntologyPage/NewPropertyButton.tsx b/browser/data-browser/src/views/OntologyPage/NewPropertyButton.tsx
index d81f749bb..e4db514d9 100644
--- a/browser/data-browser/src/views/OntologyPage/NewPropertyButton.tsx
+++ b/browser/data-browser/src/views/OntologyPage/NewPropertyButton.tsx
@@ -5,7 +5,7 @@ import {
   validateDatatype,
   type Core,
 } from '@tomic/react';
-import { useRef, useState } from 'react';
+import { useRef, useState, type JSX } from 'react';
 import { FaPlus } from 'react-icons/fa';
 import {
   Dialog,
diff --git a/browser/data-browser/src/views/OntologyPage/OntologyDescription.tsx b/browser/data-browser/src/views/OntologyPage/OntologyDescription.tsx
index 041e37d50..78d179bd8 100644
--- a/browser/data-browser/src/views/OntologyPage/OntologyDescription.tsx
+++ b/browser/data-browser/src/views/OntologyPage/OntologyDescription.tsx
@@ -9,6 +9,8 @@ import {
 import Markdown from '../../components/datatypes/Markdown';
 import InputMarkdown from '../../components/forms/InputMarkdown';
 
+import type { JSX } from 'react';
+
 interface OntologyDescriptionProps {
   resource: Resource;
   edit: boolean;
@@ -21,7 +23,7 @@ export function OntologyDescription({
   const [description] = useString(resource, urls.properties.description);
   const property = useProperty(urls.properties.description);
 
-  const [canEdit] = useCanWrite(resource);
+  const canEdit = useCanWrite(resource);
 
   if (!edit || !canEdit) {
     return <Markdown text={description ?? ''} />;
diff --git a/browser/data-browser/src/views/OntologyPage/OntologyPage.tsx b/browser/data-browser/src/views/OntologyPage/OntologyPage.tsx
index ca22bed8a..ad04a0ae5 100644
--- a/browser/data-browser/src/views/OntologyPage/OntologyPage.tsx
+++ b/browser/data-browser/src/views/OntologyPage/OntologyPage.tsx
@@ -43,7 +43,7 @@ export function OntologyPage({ resource }: ResourcePageProps) {
   const [classes] = useArray(resource, core.properties.classes);
   const [properties] = useArray(resource, core.properties.properties);
   const [instances] = useArray(resource, core.properties.instances);
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
 
   const [editMode, setEditMode] = useState(
     isEmpty(classes) && isEmpty(properties) && isEmpty(instances),
diff --git a/browser/data-browser/src/views/OntologyPage/OntologySidebar.tsx b/browser/data-browser/src/views/OntologyPage/OntologySidebar.tsx
index a3c900362..5731ef287 100644
--- a/browser/data-browser/src/views/OntologyPage/OntologySidebar.tsx
+++ b/browser/data-browser/src/views/OntologyPage/OntologySidebar.tsx
@@ -6,6 +6,8 @@ import { FaAtom, FaCube, FaHashtag } from 'react-icons/fa';
 import { ScrollArea } from '../../components/ScrollArea';
 import { toAnchorId } from '../../helpers/toAnchorId';
 
+import type { JSX } from 'react';
+
 interface OntologySidebarProps {
   ontology: Resource;
 }
diff --git a/browser/data-browser/src/views/OntologyPage/Property/PropertyCardRead.tsx b/browser/data-browser/src/views/OntologyPage/Property/PropertyCardRead.tsx
index 532331a43..f57c0b471 100644
--- a/browser/data-browser/src/views/OntologyPage/Property/PropertyCardRead.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Property/PropertyCardRead.tsx
@@ -9,6 +9,8 @@ import { InlineDatatype } from '../InlineDatatype';
 import { AtomicLink } from '../../../components/AtomicLink';
 import { toAnchorId } from '../../../helpers/toAnchorId';
 
+import type { JSX } from 'react';
+
 interface PropertyCardReadProps {
   subject: string;
 }
diff --git a/browser/data-browser/src/views/OntologyPage/Property/PropertyCardWrite.tsx b/browser/data-browser/src/views/OntologyPage/Property/PropertyCardWrite.tsx
index e017f6ec7..a8d486a6d 100644
--- a/browser/data-browser/src/views/OntologyPage/Property/PropertyCardWrite.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Property/PropertyCardWrite.tsx
@@ -1,4 +1,4 @@
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { Card } from '../../../components/Card';
 import { urls, useCanWrite, useProperty, useResource } from '@tomic/react';
 import { FaHashtag } from 'react-icons/fa';
@@ -6,8 +6,9 @@ import { styled } from 'styled-components';
 import { Column, Row } from '../../../components/Row';
 import { toAnchorId } from '../../../helpers/toAnchorId';
 import InputSwitcher from '../../../components/forms/InputSwitcher';
-import ResourceContextMenu, {
+import {
   ContextMenuOptions,
+  ResourceContextMenu,
 } from '../../../components/ResourceContextMenu';
 import { useOntologyContext } from '../OntologyContext';
 import { PropertyFormCommon } from './PropertyFormCommon';
@@ -16,18 +17,17 @@ interface PropertyCardWriteProps {
   subject: string;
 }
 
-const contextOptions = [
-  ContextMenuOptions.Open,
-  ContextMenuOptions.Delete,
-  ContextMenuOptions.History,
-];
-
 export function PropertyCardWrite({
   subject,
 }: PropertyCardWriteProps): JSX.Element {
+  const contextOptions = [
+    ContextMenuOptions.Open,
+    ContextMenuOptions.Delete,
+    ContextMenuOptions.History,
+  ];
   const resource = useResource(subject);
   const shortnameProp = useProperty(urls.properties.shortname);
-  const [canEdit] = useCanWrite(resource);
+  const canEdit = useCanWrite(resource);
 
   const { removeProperty } = useOntologyContext();
 
diff --git a/browser/data-browser/src/views/OntologyPage/Property/PropertyFormCommon.tsx b/browser/data-browser/src/views/OntologyPage/Property/PropertyFormCommon.tsx
index b3b48ae80..62a260400 100644
--- a/browser/data-browser/src/views/OntologyPage/Property/PropertyFormCommon.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Property/PropertyFormCommon.tsx
@@ -8,7 +8,7 @@ import {
   useStore,
   useString,
 } from '@tomic/react';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { Column, Row } from '../../../components/Row';
 import { SearchBox } from '../../../components/forms/SearchBox';
 import { OntologyDescription } from '../OntologyDescription';
diff --git a/browser/data-browser/src/views/OntologyPage/Property/PropertyLineRead.tsx b/browser/data-browser/src/views/OntologyPage/Property/PropertyLineRead.tsx
index 374c33a00..2dca287dd 100644
--- a/browser/data-browser/src/views/OntologyPage/Property/PropertyLineRead.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Property/PropertyLineRead.tsx
@@ -8,6 +8,8 @@ import { CARD_CONTAINER } from '../../../helpers/containers';
 import { dataTypeIconMap } from '../../../helpers/iconMap';
 import { Row } from '../../../components/Row';
 
+import type { JSX } from 'react';
+
 interface PropertyLineReadProps {
   subject: string;
 }
diff --git a/browser/data-browser/src/views/OntologyPage/Property/PropertyLineWrite.tsx b/browser/data-browser/src/views/OntologyPage/Property/PropertyLineWrite.tsx
index a6b9c383c..c1450226b 100644
--- a/browser/data-browser/src/views/OntologyPage/Property/PropertyLineWrite.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Property/PropertyLineWrite.tsx
@@ -13,6 +13,8 @@ import { useOntologyContext } from '../OntologyContext';
 import { ErrorLook } from '../../../components/ErrorLook';
 import { Button } from '../../../components/Button';
 
+import type { JSX } from 'react';
+
 interface PropertyLineWriteProps {
   subject: string;
   onRemove: (subject: string) => void;
@@ -26,7 +28,7 @@ export function PropertyLineWrite({
   const shortnameProp = useProperty(core.properties.shortname);
   const descriptionProp = useProperty(core.properties.description);
   const [dialogProps, show, hide, isOpen] = useDialog();
-  const [canEdit] = useCanWrite(resource);
+  const canEdit = useCanWrite(resource);
 
   const { hasProperty } = useOntologyContext();
 
diff --git a/browser/data-browser/src/views/OntologyPage/Property/PropertyWriteDialog.tsx b/browser/data-browser/src/views/OntologyPage/Property/PropertyWriteDialog.tsx
index e062ebce6..8c2b9e521 100644
--- a/browser/data-browser/src/views/OntologyPage/Property/PropertyWriteDialog.tsx
+++ b/browser/data-browser/src/views/OntologyPage/Property/PropertyWriteDialog.tsx
@@ -10,6 +10,8 @@ import { styled } from 'styled-components';
 import InputSwitcher from '../../../components/forms/InputSwitcher';
 import { PropertyFormCommon } from './PropertyFormCommon';
 
+import type { JSX } from 'react';
+
 interface PropertyWriteDialogProps {
   resource: Resource;
   close: () => void;
@@ -22,7 +24,7 @@ export function PropertyWriteDialog({
   isOpen,
   ...dialogProps
 }: PropertyWriteDialogProps & InternalDialogProps): JSX.Element {
-  const [canEdit] = useCanWrite(resource);
+  const canEdit = useCanWrite(resource);
   const shortnameProp = useProperty(urls.properties.shortname);
 
   return (
diff --git a/browser/data-browser/src/views/OntologyPage/PropertyDatatypePicker.tsx b/browser/data-browser/src/views/OntologyPage/PropertyDatatypePicker.tsx
index 331f98686..c358d8d43 100644
--- a/browser/data-browser/src/views/OntologyPage/PropertyDatatypePicker.tsx
+++ b/browser/data-browser/src/views/OntologyPage/PropertyDatatypePicker.tsx
@@ -8,6 +8,7 @@ import {
 } from '@tomic/react';
 import { AtomicSelectInput } from '../../components/forms/AtomicSelectInput';
 import styled from 'styled-components';
+import type { JSX } from 'react';
 interface PropertyDatatypePickerProps {
   resource: Resource;
   disabled?: boolean;
diff --git a/browser/data-browser/src/views/RedirectPage.tsx b/browser/data-browser/src/views/RedirectPage.tsx
deleted file mode 100644
index f547d8a63..000000000
--- a/browser/data-browser/src/views/RedirectPage.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import { useStore, useString, properties } from '@tomic/react';
-import * as React from 'react';
-import { useNavigate, useNavigationType } from 'react-router-dom';
-
-import { ContainerNarrow } from '../components/Containers';
-import { ValueForm } from '../components/forms/ValueForm';
-import { constructOpenURL } from '../helpers/navigation';
-import AllProps from '../components/AllProps';
-import { useSettings } from '../helpers/AppSettings';
-import { Button } from '../components/Button';
-import toast from 'react-hot-toast';
-import { paths } from '../routes/paths';
-import { ResourcePageProps } from './ResourcePage';
-import { useEffect } from 'react';
-import { ErrorBlock } from '../components/ErrorLook';
-
-/** A View that redirects!. */
-function RedirectPage({ resource }: ResourcePageProps): JSX.Element {
-  const [error, setError] = React.useState<Error | undefined>();
-  const [destination] = useString(resource, properties.redirect.destination);
-  const [redirectAgent] = useString(
-    resource,
-    properties.redirect.redirectAgent,
-  );
-  const navigate = useNavigate();
-  const { agent, setAgent } = useSettings();
-  const store = useStore();
-  const navigationType = useNavigationType();
-
-  // Navigate to the target resource, optionally create an Agent.
-  useEffect(() => {
-    if (redirectAgent) {
-      // If there is an agent without a Subject, that is because the Browser has just sent a query param to the invite resource, as part of the invite process
-      if (agent && !agent.subject) {
-        agent.subject = redirectAgent;
-        toast.success(
-          <div>
-            <p>New User created!</p>
-            <Button onClick={() => navigate(paths.agentSettings)}>
-              User Settings
-            </Button>
-          </div>,
-          { duration: 6000 },
-        );
-        setAgent(agent);
-      }
-    }
-
-    if (destination) {
-      // go to the destination, unless the user just hit the back button
-      if (navigationType !== 'POP') {
-        store
-          .fetchResourceFromServer(destination)
-          .then(() => {
-            navigate(constructOpenURL(destination));
-          })
-          .catch(err => {
-            setError(err);
-          });
-        // Fetch that resource again
-      }
-    }
-  }, [redirectAgent, agent, destination]);
-
-  return (
-    <ContainerNarrow>
-      <ValueForm resource={resource} propertyURL={properties.description} />
-      <h1>Redirect</h1>
-      <p>
-        This page should redirect you automatically (unless you have just
-        pressed the back button)
-      </p>
-      {error && <ErrorBlock error={error} />}
-      <AllProps resource={resource} except={[properties.isA]} />
-    </ContainerNarrow>
-  );
-}
-
-export default RedirectPage;
diff --git a/browser/data-browser/src/views/ResourceInline/FileInline.tsx b/browser/data-browser/src/views/ResourceInline/FileInline.tsx
index 165ff25f7..f20086ff9 100644
--- a/browser/data-browser/src/views/ResourceInline/FileInline.tsx
+++ b/browser/data-browser/src/views/ResourceInline/FileInline.tsx
@@ -2,6 +2,7 @@ import { useString, useResource, server, Image } from '@tomic/react';
 import { imageMimeTypes, getFileIcon } from '../../helpers/filetypes';
 import { ResourceInlineInstanceProps } from './ResourceInline';
 import { styled } from 'styled-components';
+import type { JSX } from 'react';
 const THUMB_SIZE = '2rem';
 
 export function FileInline({
diff --git a/browser/data-browser/src/views/ResourceInline/ResourceInline.tsx b/browser/data-browser/src/views/ResourceInline/ResourceInline.tsx
index 612ab894b..4fd6ac040 100644
--- a/browser/data-browser/src/views/ResourceInline/ResourceInline.tsx
+++ b/browser/data-browser/src/views/ResourceInline/ResourceInline.tsx
@@ -15,6 +15,8 @@ import { LoaderInline } from '../../components/Loader';
 import { TagInline } from './TagInline';
 import { FileInline } from './FileInline';
 
+import type { JSX } from 'react';
+
 export type ResourceInlineInstanceProps = {
   subject: string;
 };
@@ -69,7 +71,7 @@ export function ResourceInline({
   }
 
   if (resource.loading) {
-    return <LoaderInline about={subject}>loading...</LoaderInline>;
+    return <LoaderInline about={subject}>loading</LoaderInline>;
   }
 
   if (!Client.isValidSubject(subject)) {
diff --git a/browser/data-browser/src/views/ResourceInline/TagInline.tsx b/browser/data-browser/src/views/ResourceInline/TagInline.tsx
index 3577ab635..593d23cdc 100644
--- a/browser/data-browser/src/views/ResourceInline/TagInline.tsx
+++ b/browser/data-browser/src/views/ResourceInline/TagInline.tsx
@@ -2,6 +2,8 @@ import type { ResourceInlineInstanceProps } from './ResourceInline';
 import { Tag } from '../../components/Tag';
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 export function TagInline({
   subject,
 }: ResourceInlineInstanceProps): JSX.Element {
diff --git a/browser/data-browser/src/views/ResourceLine.tsx b/browser/data-browser/src/views/ResourceLine.tsx
index 36f9c01a6..b1db89919 100644
--- a/browser/data-browser/src/views/ResourceLine.tsx
+++ b/browser/data-browser/src/views/ResourceLine.tsx
@@ -3,6 +3,8 @@ import { ResourceInline } from './ResourceInline';
 import { ErrorLook } from '../components/ErrorLook';
 import { styled } from 'styled-components';
 
+import type { JSX } from 'react';
+
 type Props = {
   subject: string;
   clickable?: boolean;
diff --git a/browser/data-browser/src/views/ResourcePage.tsx b/browser/data-browser/src/views/ResourcePage.tsx
index afc517a2a..3c25f5537 100644
--- a/browser/data-browser/src/views/ResourcePage.tsx
+++ b/browser/data-browser/src/views/ResourcePage.tsx
@@ -1,4 +1,4 @@
-import { useEffect } from 'react';
+import { useEffect, type JSX } from 'react';
 import {
   useString,
   useResource,
@@ -14,7 +14,6 @@ import { ContainerNarrow } from '../components/Containers';
 import Collection from '../views/CollectionPage';
 import EndpointPage from './EndpointPage';
 import DrivePage from './DrivePage';
-import RedirectPage from './RedirectPage';
 import InvitePage from './InvitePage';
 import { DocumentPage } from './DocumentPage';
 import ErrorPage, { ErrorBoundary } from './ErrorPage';
@@ -50,9 +49,8 @@ type Props = {
 function ResourcePage({ subject }: Props): JSX.Element {
   const resource = useResource(subject);
   const [klass] = useString(resource, core.properties.isA);
-
   // The body can have an inert attribute when the user navigated from an open dialog.
-  // we remove it to make the page becomes interavtive again.
+  // we remove it to make the page becomes interactive again.
   useEffect(() => {
     document.body.removeAttribute('inert');
   }, []);
@@ -95,8 +93,6 @@ function selectComponent(klass: string) {
       return EndpointPage;
     case server.classes.drive:
       return DrivePage;
-    case server.classes.redirect:
-      return RedirectPage;
     case server.classes.invite:
       return InvitePage;
     case dataBrowser.classes.document:
diff --git a/browser/data-browser/src/views/ResourcePageDefault.tsx b/browser/data-browser/src/views/ResourcePageDefault.tsx
index ca593d62f..b6e1f1a16 100644
--- a/browser/data-browser/src/views/ResourcePageDefault.tsx
+++ b/browser/data-browser/src/views/ResourcePageDefault.tsx
@@ -23,6 +23,8 @@ import { Column, Row } from '../components/Row';
 import { useNavigateWithTransition } from '../hooks/useNavigateWithTransition';
 import { editURL } from '../helpers/navigation';
 
+import type { JSX } from 'react';
+
 /**
  * The properties that are shown in an alternative, custom way in default views.
  * If you use this, make sure you check the list every once in a while to make
@@ -55,7 +57,7 @@ export function ResourcePageDefault({
   resource,
 }: ResourcePageProps): JSX.Element {
   const [lastCommit] = useString(resource, commits.properties.lastCommit);
-  const [canEdit] = useCanWrite(resource);
+  const canEdit = useCanWrite(resource);
   const navigate = useNavigateWithTransition();
 
   return (
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/AtomicURLCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/AtomicURLCell.tsx
index 0ccc12697..60673568b 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/AtomicURLCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/AtomicURLCell.tsx
@@ -10,7 +10,14 @@ import {
   useString,
   useTitle,
 } from '@tomic/react';
-import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+import {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+  type JSX,
+} from 'react';
 import { FaEdit } from 'react-icons/fa';
 import { styled } from 'styled-components';
 import { FileDropzoneInput } from '../../../components/forms/FileDropzone/FileDropzoneInput';
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/BooleanCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/BooleanCell.tsx
index 24726fc5e..a68fb46c0 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/BooleanCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/BooleanCell.tsx
@@ -3,6 +3,8 @@ import { JSONValue } from '@tomic/react';
 import { Checkbox } from '../../../components/forms/Checkbox';
 import { CellContainer, DisplayCellProps, EditCellProps } from './Type';
 
+import type { JSX } from 'react';
+
 function BooleanCellEdit({
   value,
   onChange,
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/DateCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/DateCell.tsx
index f7d6cca19..ed9998156 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/DateCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/DateCell.tsx
@@ -7,7 +7,7 @@ import {
   useString,
   validateDatatype,
 } from '@tomic/react';
-import { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState, type JSX } from 'react';
 import { formatDate } from '../../../helpers/dates/formatDate';
 import { InputBase } from './InputBase';
 import { CellContainer, DisplayCellProps, EditCellProps } from './Type';
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/DateTimeCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/DateTimeCell.tsx
index d2f3de231..71a1545d3 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/DateTimeCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/DateTimeCell.tsx
@@ -5,7 +5,7 @@ import {
   useResource,
   useString,
 } from '@tomic/react';
-import { useEffect, useState } from 'react';
+import { useEffect, useState, type JSX } from 'react';
 import { formatDate } from '../../../helpers/dates/formatDate';
 import { InputBase } from './InputBase';
 import { CellContainer, DisplayCellProps, EditCellProps } from './Type';
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/FloatCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/FloatCell.tsx
index dd9bc8787..644ca5660 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/FloatCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/FloatCell.tsx
@@ -13,6 +13,8 @@ import { ProgressBar } from './ProgressBar';
 import { CellContainer, DisplayCellProps, EditCellProps } from './Type';
 import { formatNumber } from '../helpers/formatNumber';
 
+import type { JSX } from 'react';
+
 const { numberFormats } = urls.instances;
 
 function FloatCellEdit({
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/IntegerCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/IntegerCell.tsx
index 43dfd56ea..5c46e654b 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/IntegerCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/IntegerCell.tsx
@@ -6,6 +6,8 @@ import { ProgressBar } from './ProgressBar';
 import { CellContainer, DisplayCellProps, EditCellProps } from './Type';
 import { formatNumber } from '../helpers/formatNumber';
 
+import type { JSX } from 'react';
+
 const { numberFormats } = urls.instances;
 
 function IntegerCellEdit({
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/MultiRelationCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/MultiRelationCell.tsx
index 44a65f68b..2bf433867 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/MultiRelationCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/MultiRelationCell.tsx
@@ -7,7 +7,14 @@ import {
   useResource,
   useTitle,
 } from '@tomic/react';
-import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
+import {
+  useCallback,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+  type JSX,
+} from 'react';
 import { styled } from 'styled-components';
 import {
   InputStyled,
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/ResourceArrayCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/ResourceArrayCell.tsx
index c1b9b6d21..6fcd558be 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/ResourceArrayCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/ResourceArrayCell.tsx
@@ -4,6 +4,8 @@ import { getCategoryFromResource } from '../PropertyForm/categories';
 import { SelectCell } from './SelectCell';
 import { MultiRelationCell } from './MultiRelationCell';
 
+import type { JSX } from 'react';
+
 function ResourceArrayCellEdit(props: EditCellProps<JSONValue>): JSX.Element {
   const propResource = useResource(props.property);
 
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/ResourceCells/SimpleResourceLink.tsx b/browser/data-browser/src/views/TablePage/EditorCells/ResourceCells/SimpleResourceLink.tsx
index d9083c783..49d575dbf 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/ResourceCells/SimpleResourceLink.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/ResourceCells/SimpleResourceLink.tsx
@@ -1,5 +1,5 @@
 import { Resource } from '@tomic/react';
-import { useMemo } from 'react';
+import { useMemo, type JSX } from 'react';
 import { constructOpenURL } from '../../../../helpers/navigation';
 import { useNavigateWithTransition } from '../../../../hooks/useNavigateWithTransition';
 import { styled } from 'styled-components';
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/SelectCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/SelectCell.tsx
index 09dcceb66..ff32c2da7 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/SelectCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/SelectCell.tsx
@@ -6,7 +6,7 @@ import {
   useResource,
   useStore,
 } from '@tomic/react';
-import { useCallback, useEffect, useMemo, useState } from 'react';
+import { useCallback, useEffect, useMemo, useState, type JSX } from 'react';
 import { FaPlus } from 'react-icons/fa';
 import * as RadixPopover from '@radix-ui/react-popover';
 import { styled } from 'styled-components';
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/SlugCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/SlugCell.tsx
index 4f4abcf77..2562cbc6a 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/SlugCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/SlugCell.tsx
@@ -1,5 +1,5 @@
 import { JSONValue } from '@tomic/react';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { InputBase } from './InputBase';
 import { CellContainer, DisplayCellProps, EditCellProps } from './Type';
 
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/StringCell.tsx b/browser/data-browser/src/views/TablePage/EditorCells/StringCell.tsx
index 030dfb795..010ca7b44 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/StringCell.tsx
+++ b/browser/data-browser/src/views/TablePage/EditorCells/StringCell.tsx
@@ -3,6 +3,8 @@ import { JSONValue } from '@tomic/react';
 import { InputBase } from './InputBase';
 import { CellContainer, DisplayCellProps, EditCellProps } from './Type';
 
+import type { JSX } from 'react';
+
 function StringCellEdit({
   value,
   onChange,
diff --git a/browser/data-browser/src/views/TablePage/EditorCells/Type.ts b/browser/data-browser/src/views/TablePage/EditorCells/Type.ts
index 714a409ab..4b4203405 100644
--- a/browser/data-browser/src/views/TablePage/EditorCells/Type.ts
+++ b/browser/data-browser/src/views/TablePage/EditorCells/Type.ts
@@ -1,5 +1,7 @@
 import { JSONValue, Resource } from '@tomic/react';
 
+import type { JSX } from 'react';
+
 export interface EditCellProps<T extends JSONValue> {
   value: T;
   onChange: (value: T) => void;
diff --git a/browser/data-browser/src/views/TablePage/ExpandedRowDialog.tsx b/browser/data-browser/src/views/TablePage/ExpandedRowDialog.tsx
index fe5076611..93e71c578 100644
--- a/browser/data-browser/src/views/TablePage/ExpandedRowDialog.tsx
+++ b/browser/data-browser/src/views/TablePage/ExpandedRowDialog.tsx
@@ -1,5 +1,5 @@
 import { commits, core, useResource, dataBrowser } from '@tomic/react';
-import { useEffect } from 'react';
+import { useEffect, type JSX } from 'react';
 import {
   Dialog,
   DialogContent,
diff --git a/browser/data-browser/src/views/TablePage/NewColumnButton.tsx b/browser/data-browser/src/views/TablePage/NewColumnButton.tsx
index 146852cff..65063f61b 100644
--- a/browser/data-browser/src/views/TablePage/NewColumnButton.tsx
+++ b/browser/data-browser/src/views/TablePage/NewColumnButton.tsx
@@ -1,5 +1,5 @@
 import { Datatype, useResource } from '@tomic/react';
-import { useCallback, useContext, useMemo, useState } from 'react';
+import { useCallback, useContext, useMemo, useState, type JSX } from 'react';
 import { FaChevronCircleDown, FaFile, FaHashtag, FaPlus } from 'react-icons/fa';
 import { DIVIDER, DropdownMenu, DropdownItem } from '../../components/Dropdown';
 import { buildDefaultTrigger } from '../../components/Dropdown/DefaultTrigger';
@@ -90,7 +90,7 @@ export function NewColumnButton(): JSX.Element {
 
   return (
     <>
-      <DropdownMenu trigger={NewColumnTrigger} items={items} />
+      <DropdownMenu Trigger={NewColumnTrigger} items={items} />
       <NewPropertyDialog
         showDialog={showDialog}
         tableClassResource={tableClassResource}
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/CheckboxPropertyForm.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/CheckboxPropertyForm.tsx
index 885f6bd82..77f4ec7a8 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/CheckboxPropertyForm.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/CheckboxPropertyForm.tsx
@@ -1,5 +1,5 @@
 import { Datatype, core } from '@tomic/react';
-import { useEffect } from 'react';
+import { useEffect, type JSX } from 'react';
 import { PropertyCategoryFormProps } from './PropertyCategoryFormProps';
 
 export function CheckboxPropertyForm({
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/DatePropertyForm.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/DatePropertyForm.tsx
index 998632ecb..f4dd51e1a 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/DatePropertyForm.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/DatePropertyForm.tsx
@@ -1,5 +1,5 @@
 import { Datatype, core, dataBrowser, urls, useString } from '@tomic/react';
-import { Suspense, useEffect, useState } from 'react';
+import { Suspense, useEffect, useState, type JSX } from 'react';
 import { Checkbox, CheckboxLabel } from '../../../components/forms/Checkbox';
 import { DateFormatPicker } from './Inputs/DateFormatPicker';
 import { PropertyCategoryFormProps } from './PropertyCategoryFormProps';
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/EditPropertyDialog.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/EditPropertyDialog.tsx
index 1b47c3f9d..10e39cb67 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/EditPropertyDialog.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/EditPropertyDialog.tsx
@@ -1,5 +1,5 @@
 import { Resource } from '@tomic/react';
-import { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState, type JSX } from 'react';
 import { PropertyForm } from './PropertyForm';
 import { FormValidationContextProvider } from '../../../components/forms/formValidation/FormValidationContextProvider';
 import {
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/ExternalPropertyDialog.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/ExternalPropertyDialog.tsx
index ab1e62480..03001e36a 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/ExternalPropertyDialog.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/ExternalPropertyDialog.tsx
@@ -1,4 +1,4 @@
-import { useEffect, useState } from 'react';
+import { useEffect, useState, type JSX } from 'react';
 import {
   Dialog,
   DialogActions,
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/FilePropertyForm.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/FilePropertyForm.tsx
index af326df25..f5494ba1c 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/FilePropertyForm.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/FilePropertyForm.tsx
@@ -1,5 +1,5 @@
 import { Datatype, core, server } from '@tomic/react';
-import { useEffect } from 'react';
+import { useEffect, type JSX } from 'react';
 import { PropertyCategoryFormProps } from './PropertyCategoryFormProps';
 
 export function FilePropertyForm({
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/DateFormatPicker.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/DateFormatPicker.tsx
index 52ea2dfe7..3b3bacef0 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/DateFormatPicker.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/DateFormatPicker.tsx
@@ -4,6 +4,8 @@ import { styled } from 'styled-components';
 import { RadioInput } from '../../../../components/forms/RadioInput';
 import { formatDate } from '../../../../helpers/dates/formatDate';
 
+import type { JSX } from 'react';
+
 const {
   instances: { dateFormats },
 } = urls;
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/DecimalPlacesInput.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/DecimalPlacesInput.tsx
index fe2e052af..3af4a3307 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/DecimalPlacesInput.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/DecimalPlacesInput.tsx
@@ -1,5 +1,5 @@
 import { Resource, urls, useNumber, useString } from '@tomic/react';
-import { useCallback, useId } from 'react';
+import { useCallback, useId, type JSX } from 'react';
 import { ErrorChip } from '../../../../components/forms/ErrorChip';
 import { useValidation } from '../../../../components/forms/formValidation/useValidation';
 import {
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/TableRangeInput.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/TableRangeInput.tsx
index b82dc8541..2a4879df6 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/TableRangeInput.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/Inputs/TableRangeInput.tsx
@@ -1,5 +1,5 @@
 import { Resource, useNumber } from '@tomic/react';
-import { useCallback } from 'react';
+import { useCallback, type JSX } from 'react';
 import { ErrorChip } from '../../../../components/forms/ErrorChip';
 import { useValidation } from '../../../../components/forms/formValidation/useValidation';
 import {
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/NewPropertyDialog.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/NewPropertyDialog.tsx
index da9dde3a2..b162a23b6 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/NewPropertyDialog.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/NewPropertyDialog.tsx
@@ -7,7 +7,7 @@ import {
   useArray,
   useStore,
 } from '@tomic/react';
-import { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { Button } from '../../../components/Button';
 import {
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/NumberPropertyForm.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/NumberPropertyForm.tsx
index d470cb937..9d75f7c91 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/NumberPropertyForm.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/NumberPropertyForm.tsx
@@ -6,7 +6,7 @@ import {
   useNumber,
   useString,
 } from '@tomic/react';
-import { Suspense, lazy, useEffect } from 'react';
+import { Suspense, lazy, useEffect, type JSX } from 'react';
 import { RadioGroup, RadioInput } from '../../../components/forms/RadioInput';
 import { FormGroupHeading } from './FormGroupHeading';
 import { DecimalPlacesInput } from './Inputs/DecimalPlacesInput';
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/PropertyForm.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/PropertyForm.tsx
index 03da27222..54319c1bb 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/PropertyForm.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/PropertyForm.tsx
@@ -1,5 +1,5 @@
 import { core, Resource, useString } from '@tomic/react';
-import { useCallback, useEffect, useMemo } from 'react';
+import { useCallback, useEffect, useMemo, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { ErrorChip } from '../../../components/forms/ErrorChip';
 import { useValidation } from '../../../components/forms/formValidation/useValidation';
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/RelationPropertyForm.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/RelationPropertyForm.tsx
index e0bf9ab62..f5689c77e 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/RelationPropertyForm.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/RelationPropertyForm.tsx
@@ -1,5 +1,5 @@
 import { Datatype, core, useString } from '@tomic/react';
-import { useEffect } from 'react';
+import { useEffect, type JSX } from 'react';
 import { styled } from 'styled-components';
 import { ResourceSelector } from '../../../components/forms/ResourceSelector';
 import { PropertyCategoryFormProps } from './PropertyCategoryFormProps';
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/SelectPropertyForm.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/SelectPropertyForm.tsx
index 0c82462f2..063c3975d 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/SelectPropertyForm.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/SelectPropertyForm.tsx
@@ -6,7 +6,7 @@ import {
   useArray,
   useStore,
 } from '@tomic/react';
-import { useCallback, useEffect } from 'react';
+import { useCallback, useEffect, type JSX } from 'react';
 import { Row } from '../../../components/Row';
 import { PropertyCategoryFormProps } from './PropertyCategoryFormProps';
 import { CreateTagRow, EditableTag } from '../../../components/Tag';
diff --git a/browser/data-browser/src/views/TablePage/PropertyForm/TextPropertyForm.tsx b/browser/data-browser/src/views/TablePage/PropertyForm/TextPropertyForm.tsx
index cd3640c13..c63c3a4bc 100644
--- a/browser/data-browser/src/views/TablePage/PropertyForm/TextPropertyForm.tsx
+++ b/browser/data-browser/src/views/TablePage/PropertyForm/TextPropertyForm.tsx
@@ -1,5 +1,5 @@
 import { Datatype, core, dataBrowser } from '@tomic/react';
-import { useState } from 'react';
+import { useState, type JSX } from 'react';
 import { RadioGroup, RadioInput } from '../../../components/forms/RadioInput';
 import { FormGroupHeading } from './FormGroupHeading';
 import { TableRangeInput } from './Inputs/TableRangeInput';
diff --git a/browser/data-browser/src/views/TablePage/TableCell.tsx b/browser/data-browser/src/views/TablePage/TableCell.tsx
index 03da41808..d1d90bb98 100644
--- a/browser/data-browser/src/views/TablePage/TableCell.tsx
+++ b/browser/data-browser/src/views/TablePage/TableCell.tsx
@@ -3,10 +3,10 @@ import {
   JSONValue,
   Property,
   Resource,
-  useDebouncedCallback,
+  useDebouncedSave,
   useValue,
 } from '@tomic/react';
-import { useCallback, useContext, useMemo } from 'react';
+import { useCallback, useContext, useMemo, type JSX } from 'react';
 import { Cell } from '../../components/TableEditor';
 import { CellAlign } from '../../components/TableEditor/Cell';
 import {
@@ -56,13 +56,7 @@ export function TableCell({
 }: TableCell): JSX.Element {
   const { setActiveCell } = useTableEditorContext();
   const { addItemsToHistoryStack } = useContext(TablePageContext);
-  const [save, savePending] = useDebouncedCallback(
-    async () => {
-      await resource.save();
-    },
-    200,
-    [resource],
-  );
+  const [save, savePending] = useDebouncedSave(resource, 200);
   const [value, setValue] = useValue(resource, property.subject, valueOpts);
 
   const [createdAt, setCreatedAt] = useValue(
diff --git a/browser/data-browser/src/views/TablePage/TableHeading.tsx b/browser/data-browser/src/views/TablePage/TableHeading.tsx
index 697630751..c7727e759 100644
--- a/browser/data-browser/src/views/TablePage/TableHeading.tsx
+++ b/browser/data-browser/src/views/TablePage/TableHeading.tsx
@@ -14,7 +14,7 @@ import { TableHeadingMenu } from './TableHeadingMenu';
 import { TablePageContext } from './tablePageContext';
 import { IconType } from 'react-icons';
 import { TableSorting } from './tableSorting';
-import { useContext, useState } from 'react';
+import { useContext, useState, type JSX } from 'react';
 import { TableHeadingComponent } from '../../components/TableEditor/TableHeader';
 import { dataTypeIconMap } from '../../helpers/iconMap';
 
diff --git a/browser/data-browser/src/views/TablePage/TableHeadingMenu.tsx b/browser/data-browser/src/views/TablePage/TableHeadingMenu.tsx
index 0807b938d..6f248ff40 100644
--- a/browser/data-browser/src/views/TablePage/TableHeadingMenu.tsx
+++ b/browser/data-browser/src/views/TablePage/TableHeadingMenu.tsx
@@ -6,7 +6,14 @@ import {
   useString,
   core,
 } from '@tomic/react';
-import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
+import {
+  useCallback,
+  useContext,
+  useEffect,
+  useMemo,
+  useState,
+  type JSX,
+} from 'react';
 import { DropdownMenu, DropdownItem } from '../../components/Dropdown';
 import { buildDefaultTrigger } from '../../components/Dropdown/DefaultTrigger';
 import { FaEdit, FaEllipsisV, FaEye, FaTimes } from 'react-icons/fa';
@@ -19,10 +26,10 @@ import {
 } from '../../components/ConfirmationDialog';
 import { ResourceInline } from '../ResourceInline';
 import { ResourceUsage } from '../../components/ResourceUsage';
-import { useNavigate } from 'react-router';
 import { constructOpenURL } from '../../helpers/navigation';
 import { Checkbox, CheckboxLabel } from '../../components/forms/Checkbox';
 import { Column } from '../../components/Row';
+import { useNavigateWithTransition } from '../../hooks/useNavigateWithTransition';
 
 interface TableHeadingMenuProps {
   resource: Resource;
@@ -46,9 +53,9 @@ export function TableHeadingMenu({
 
   const { tableClassSubject } = useContext(TablePageContext);
   const tableClassResource = useResource(tableClassSubject);
-  const [canWriteClass] = useCanWrite(tableClassResource);
-  const [canWriteProperty] = useCanWrite(resource);
-  const navigate = useNavigate();
+  const canWriteClass = useCanWrite(tableClassResource);
+  const canWriteProperty = useCanWrite(resource);
+  const navigate = useNavigateWithTransition();
 
   const isExternalProperty = useIsExternalProperty(resource);
 
@@ -124,7 +131,7 @@ export function TableHeadingMenu({
 
   return (
     <Wrapper>
-      <DropdownMenu trigger={Trigger} items={items} />
+      <DropdownMenu Trigger={Trigger} items={items} />
       <EditPropertyDialog
         resource={resource}
         showDialog={showEditDialog}
diff --git a/browser/data-browser/src/views/TablePage/TablePage.tsx b/browser/data-browser/src/views/TablePage/TablePage.tsx
index 672315193..9ab12c676 100644
--- a/browser/data-browser/src/views/TablePage/TablePage.tsx
+++ b/browser/data-browser/src/views/TablePage/TablePage.tsx
@@ -1,5 +1,5 @@
 import { Property, unknownSubject, useStore } from '@tomic/react';
-import { useCallback, useId, useMemo, useState } from 'react';
+import { useCallback, useId, useMemo, useState, type JSX } from 'react';
 import { ContainerFull } from '../../components/Containers';
 import { EditableTitle } from '../../components/EditableTitle';
 import { FancyTable } from '../../components/TableEditor';
diff --git a/browser/data-browser/src/views/TablePage/TableRow.tsx b/browser/data-browser/src/views/TablePage/TableRow.tsx
index 8ade88d3f..96cb928d9 100644
--- a/browser/data-browser/src/views/TablePage/TableRow.tsx
+++ b/browser/data-browser/src/views/TablePage/TableRow.tsx
@@ -1,4 +1,4 @@
-import { memo, useEffect, useState } from 'react';
+import { memo, useEffect, useState, type JSX } from 'react';
 import {
   Collection,
   DataBrowser,
diff --git a/browser/data-browser/src/views/TablePage/useTableData.ts b/browser/data-browser/src/views/TablePage/useTableData.ts
index de2a0548b..1ae949601 100644
--- a/browser/data-browser/src/views/TablePage/useTableData.ts
+++ b/browser/data-browser/src/views/TablePage/useTableData.ts
@@ -22,26 +22,23 @@ type UseTableDataResult = {
 } & UseCollectionResult;
 
 const useTableSorting = () =>
-  useReducer<(state: TableSorting, property: string) => TableSorting>(
-    (state, property) => {
-      if (state.prop === property && state.sortDesc) {
-        return DEFAULT_SORT;
-      }
-
-      if (state.prop === property) {
-        return {
-          ...state,
-          sortDesc: true,
-        };
-      }
+  useReducer((state: TableSorting, property: string) => {
+    if (state.prop === property && state.sortDesc) {
+      return DEFAULT_SORT;
+    }
 
+    if (state.prop === property) {
       return {
-        prop: property,
-        sortDesc: false,
+        ...state,
+        sortDesc: true,
       };
-    },
-    DEFAULT_SORT,
-  );
+    }
+
+    return {
+      prop: property,
+      sortDesc: false,
+    };
+  }, DEFAULT_SORT);
 
 export function useTableData(resource: Resource): UseTableDataResult {
   const [sorting, setSortBy] = useTableSorting();
diff --git a/browser/data-browser/src/views/TagPage/TagPage.tsx b/browser/data-browser/src/views/TagPage/TagPage.tsx
index e608127c2..67dfeb8f5 100644
--- a/browser/data-browser/src/views/TagPage/TagPage.tsx
+++ b/browser/data-browser/src/views/TagPage/TagPage.tsx
@@ -27,7 +27,7 @@ export function TagPage({ resource }: ResourcePageProps<DataBrowser.Tag>) {
     commit: true,
   });
   const shortnameProp = useProperty(core.properties.shortname);
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
 
   return (
     <ContainerNarrow>
diff --git a/browser/data-browser/tsconfig.json b/browser/data-browser/tsconfig.json
index fe3f523b7..3893f7550 100644
--- a/browser/data-browser/tsconfig.json
+++ b/browser/data-browser/tsconfig.json
@@ -3,17 +3,11 @@
   "compilerOptions": {
     "composite": true,
     // We overwrite this so we don't have to use `.js` extensions in imports
-    "moduleResolution": "node",
-    "lib": [
-      "ES6",
-      "ES7",
-      "ESNext",
-      "DOM"
-    ],
+    "module": "ESNext",
+    "moduleResolution": "bundler",
+    "lib": ["ES6", "ES7", "ESNext", "DOM"],
     "outDir": "./dist",
-    "strictNullChecks": true,
+    "strictNullChecks": true
   },
-  "include": [
-    "./src",
-  ]
+  "include": ["./src"]
 }
diff --git a/browser/data-browser/vite.config.ts b/browser/data-browser/vite.config.ts
index b35ce773e..6d8a44b34 100644
--- a/browser/data-browser/vite.config.ts
+++ b/browser/data-browser/vite.config.ts
@@ -1,12 +1,19 @@
 import { defineConfig } from 'vite';
-import react from '@vitejs/plugin-react-swc';
+import react from '@vitejs/plugin-react';
 import { VitePWA } from 'vite-plugin-pwa';
 import webfontDownload from 'vite-plugin-webfont-dl';
 import prismjs from 'vite-plugin-prismjs';
 export default defineConfig({
   plugins: [
     webfontDownload(),
-    react({ plugins: [['@swc/plugin-styled-components', {}]] }),
+    react({
+      babel: {
+        plugins: [
+          ['babel-plugin-react-compiler', {}],
+          'babel-plugin-styled-components',
+        ],
+      },
+    }),
     VitePWA({
       registerType: 'autoUpdate',
       injectRegister: 'auto',
diff --git a/browser/lib/src/agent.ts b/browser/lib/src/agent.ts
index ee5ef85f7..55e73d72f 100644
--- a/browser/lib/src/agent.ts
+++ b/browser/lib/src/agent.ts
@@ -1,6 +1,6 @@
 import { Client } from './client.js';
 import { generatePublicKeyFromPrivate } from './commit.js';
-import { AtomicError } from './error.js';
+import { AtomicError, ErrorType } from './error.js';
 import { core } from './ontologies/core.js';
 
 /**
@@ -20,7 +20,7 @@ export class Agent implements AgentInterface {
     }
 
     if (!privateKey) {
-      throw new AtomicError(`Agent requires a private key`);
+      throw new AtomicError(`Agent requires a private key`, ErrorType.Client);
     }
 
     this.client = new Client();
@@ -64,7 +64,7 @@ export class Agent implements AgentInterface {
   /** Fetches the public key for the agent, checks if it matches with the current one */
   public async verifyPublicKeyWithServer(): Promise<void> {
     if (!this.subject) {
-      throw new AtomicError(`Agent has no subject`);
+      throw new AtomicError(`Agent has no subject`, ErrorType.Client);
     }
 
     const { resource } = await this.client.fetchResourceHTTP(this.subject);
diff --git a/browser/package.json b/browser/package.json
index cd25da5d3..d1bf8afae 100644
--- a/browser/package.json
+++ b/browser/package.json
@@ -9,6 +9,7 @@
     "eslint-plugin-jsx-a11y": "^6.10.1",
     "eslint-plugin-prettier": "^5.2.1",
     "eslint-plugin-react": "^7.37.2",
+    "eslint-plugin-react-compiler": "19.0.0-beta-37ed2a7-20241206",
     "eslint-plugin-react-hooks": "^4.6.2",
     "husky": "^8.0.3",
     "netlify-cli": "17.37.1",
diff --git a/browser/pnpm-lock.yaml b/browser/pnpm-lock.yaml
index af5767a12..bcfbc52b7 100644
--- a/browser/pnpm-lock.yaml
+++ b/browser/pnpm-lock.yaml
@@ -35,6 +35,9 @@ importers:
       eslint-plugin-react:
         specifier: ^7.37.2
         version: 7.37.2(eslint@8.57.1)
+      eslint-plugin-react-compiler:
+        specifier: 19.0.0-beta-37ed2a7-20241206
+        version: 19.0.0-beta-37ed2a7-20241206(eslint@8.57.1)
       eslint-plugin-react-hooks:
         specifier: ^4.6.2
         version: 4.6.2(eslint@8.57.1)
@@ -117,28 +120,31 @@ importers:
         version: 1.1.4
       '@dnd-kit/core':
         specifier: ^6.1.0
-        version: 6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 6.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       '@dnd-kit/sortable':
         specifier: ^8.0.0
-        version: 8.0.0(@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)
+        version: 8.0.0(@dnd-kit/core@6.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)
       '@dnd-kit/utilities':
         specifier: ^3.2.2
-        version: 3.2.2(react@18.3.1)
+        version: 3.2.2(react@19.0.0)
       '@emoji-mart/react':
         specifier: ^1.1.1
-        version: 1.1.1(emoji-mart@5.6.0)(react@18.3.1)
+        version: 1.1.1(emoji-mart@5.6.0)(react@19.0.0)
       '@emotion/is-prop-valid':
         specifier: ^1.3.1
         version: 1.3.1
       '@radix-ui/react-popover':
         specifier: ^1.1.2
-        version: 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 1.1.2(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       '@radix-ui/react-scroll-area':
         specifier: ^1.2.0
-        version: 1.2.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 1.2.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       '@radix-ui/react-tabs':
         specifier: ^1.1.1
-        version: 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 1.1.1(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@tanstack/react-router':
+        specifier: ^1.95.1
+        version: 1.95.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       '@tiptap/extension-image':
         specifier: ^2.9.1
         version: 2.9.1(@tiptap/core@2.9.1(@tiptap/pm@2.9.1))
@@ -156,7 +162,7 @@ importers:
         version: 2.9.1
       '@tiptap/react':
         specifier: ^2.9.1
-        version: 2.9.1(@tiptap/core@2.9.1(@tiptap/pm@2.9.1))(@tiptap/pm@2.9.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 2.9.1(@tiptap/core@2.9.1(@tiptap/pm@2.9.1))(@tiptap/pm@2.9.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       '@tiptap/starter-kit':
         specifier: ^2.9.1
         version: 2.9.1
@@ -182,62 +188,53 @@ importers:
         specifier: ^0.2.0
         version: 0.2.0
       react:
-        specifier: ^18.3.1
-        version: 18.3.1
+        specifier: ^19.0.0
+        version: 19.0.0
       react-colorful:
         specifier: ^5.6.1
-        version: 5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 5.6.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       react-dom:
-        specifier: ^18.3.1
-        version: 18.3.1(react@18.3.1)
+        specifier: ^19.0.0
+        version: 19.0.0(react@19.0.0)
       react-dropzone:
         specifier: ^11.7.1
-        version: 11.7.1(react@18.3.1)
-      react-helmet-async:
-        specifier: ^1.3.0
-        version: 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 11.7.1(react@19.0.0)
       react-hot-toast:
         specifier: ^2.4.1
-        version: 2.4.1(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 2.4.1(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       react-hotkeys-hook:
         specifier: ^3.4.7
-        version: 3.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 3.4.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       react-icons:
         specifier: ^4.12.0
-        version: 4.12.0(react@18.3.1)
+        version: 4.12.0(react@19.0.0)
       react-intersection-observer:
         specifier: ^9.13.1
-        version: 9.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 9.13.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       react-is:
-        specifier: ^18.3.1
-        version: 18.3.1
+        specifier: ^19.0.0
+        version: 19.0.0
       react-markdown:
-        specifier: ^8.0.7
-        version: 8.0.7(@types/react@18.3.12)(react@18.3.1)
+        specifier: ^9.0.3
+        version: 9.0.3(@types/react@19.0.1)(react@19.0.0)
       react-pdf:
         specifier: ^9.1.1
-        version: 9.1.1(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      react-router:
-        specifier: ^6.27.0
-        version: 6.27.0(react@18.3.1)
-      react-router-dom:
-        specifier: ^6.27.0
-        version: 6.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 9.1.1(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       react-virtualized-auto-sizer:
         specifier: ^1.0.24
-        version: 1.0.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 1.0.24(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       react-window:
         specifier: ^1.8.10
-        version: 1.8.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 1.8.10(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       reactflow:
         specifier: ^11.11.4
-        version: 11.11.4(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 11.11.4(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       remark-gfm:
-        specifier: ^3.0.1
-        version: 3.0.1
+        specifier: ^4.0.0
+        version: 4.0.0
       styled-components:
         specifier: ^6.1.13
-        version: 6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+        version: 6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       stylis:
         specifier: 4.3.0
         version: 4.3.0
@@ -248,30 +245,33 @@ importers:
         specifier: ^0.8.10
         version: 0.8.10(@tiptap/core@2.9.1(@tiptap/pm@2.9.1))
     devDependencies:
-      '@swc/plugin-styled-components':
-        specifier: ^2.0.12
-        version: 2.0.12
+      '@tanstack/router-devtools':
+        specifier: ^1.95.1
+        version: 1.95.1(@tanstack/react-router@1.95.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       '@types/prismjs':
         specifier: ^1.26.5
         version: 1.26.5
       '@types/react':
-        specifier: ^18.3.12
-        version: 18.3.12
+        specifier: ^19.0.0
+        version: 19.0.1
       '@types/react-dom':
-        specifier: ^18.3.1
-        version: 18.3.1
+        specifier: ^19.0.0
+        version: 19.0.1
       '@types/react-pdf':
         specifier: ^7.0.0
-        version: 7.0.0(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@types/react-router-dom':
-        specifier: ^5.3.3
-        version: 5.3.3
+        version: 7.0.0(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       '@types/react-window':
         specifier: ^1.8.8
         version: 1.8.8
-      '@vitejs/plugin-react-swc':
-        specifier: ^3.7.1
-        version: 3.7.1(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))
+      '@vitejs/plugin-react':
+        specifier: ^4.3.4
+        version: 4.3.4(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))
+      babel-plugin-react-compiler:
+        specifier: 19.0.0-beta-37ed2a7-20241206
+        version: 19.0.0-beta-37ed2a7-20241206
+      babel-plugin-styled-components:
+        specifier: ^2.1.4
+        version: 2.1.4(@babel/core@7.26.0)(styled-components@6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
       csstype:
         specifier: ^3.1.3
         version: 3.1.3
@@ -295,7 +295,7 @@ importers:
         version: 0.0.11(prismjs@1.29.0)
       vite-plugin-pwa:
         specifier: ^0.20.5
-        version: 0.20.5(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))(workbox-build@7.1.1)(workbox-window@7.1.0)
+        version: 0.20.5(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.1.0)
       vite-plugin-webfont-dl:
         specifier: ^3.9.5
         version: 3.9.5(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))
@@ -355,18 +355,21 @@ importers:
         specifier: workspace:*
         version: link:../lib
       react:
-        specifier: '>18.3.0'
-        version: 18.3.1
+        specifier: ^19.0.0
+        version: 19.0.0
+      react-dom:
+        specifier: ^19.0.0
+        version: 19.0.0(react@19.0.0)
     devDependencies:
       '@arethetypeswrong/cli':
         specifier: ^0.17.0
         version: 0.17.0
       '@types/react':
-        specifier: ^18.3.12
-        version: 18.3.12
+        specifier: ^19.0.0
+        version: 19.0.1
       '@types/react-dom':
-        specifier: ^18.3.1
-        version: 18.3.1
+        specifier: ^19.0.0
+        version: 19.0.1
       '@types/react-router-dom':
         specifier: ^5.3.3
         version: 5.3.3
@@ -424,7 +427,7 @@ importers:
         version: 5.1.4
       svelte-check:
         specifier: ^3.8.6
-        version: 3.8.6(@babel/core@7.25.9)(postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)))(postcss@8.4.47)(svelte@5.1.4)
+        version: 3.8.6(@babel/core@7.26.0)(postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)))(postcss@8.4.47)(svelte@5.1.4)
       typescript:
         specifier: ^5.6.3
         version: 5.6.3
@@ -462,20 +465,20 @@ packages:
     resolution: {integrity: sha512-FHyhFizXNetigTVsIhqXKGYLpazPS5YNojEPpZEUcBPt9wVvoEbNIvG+hybuBR+pjlRcbyuqhukHZm1fr+bDgA==}
     engines: {node: '>=18'}
 
-  '@babel/code-frame@7.25.9':
-    resolution: {integrity: sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==}
+  '@babel/code-frame@7.26.2':
+    resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==}
     engines: {node: '>=6.9.0'}
 
   '@babel/compat-data@7.25.9':
     resolution: {integrity: sha512-yD+hEuJ/+wAJ4Ox2/rpNv5HIuPG82x3ZlQvYVn8iYCprdxzE7P1udpGF1jyjQVBU4dgznN+k2h103vxZ7NdPyw==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/core@7.25.9':
-    resolution: {integrity: sha512-WYvQviPw+Qyib0v92AwNIrdLISTp7RfDkM7bPqBvpbnhY4wq8HvHBZREVdYDXk98C8BkOIVnHAY3yvj7AVISxQ==}
+  '@babel/core@7.26.0':
+    resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/generator@7.25.9':
-    resolution: {integrity: sha512-omlUGkr5EaoIJrhLf9CJ0TvjBRpd9+AXRG//0GEQ9THSo8wPiTlbpy1/Ow8ZTrbXpjd9FHXfbFQx32I04ht0FA==}
+  '@babel/generator@7.26.3':
+    resolution: {integrity: sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==}
     engines: {node: '>=6.9.0'}
 
   '@babel/helper-annotate-as-pure@7.25.9':
@@ -515,8 +518,8 @@ packages:
     resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/helper-module-transforms@7.25.9':
-    resolution: {integrity: sha512-TvLZY/F3+GvdRYFZFyxMvnsKi+4oJdgZzU3BoGN9Uc2d9C6zfNwJcKKhjqLAhK8i46mv93jsO74fDh3ih6rpHA==}
+  '@babel/helper-module-transforms@7.26.0':
+    resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==}
     engines: {node: '>=6.9.0'}
     peerDependencies:
       '@babel/core': ^7.0.0
@@ -565,12 +568,8 @@ packages:
     resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==}
     engines: {node: '>=6.9.0'}
 
-  '@babel/helpers@7.25.9':
-    resolution: {integrity: sha512-oKWp3+usOJSzDZOucZUAMayhPz/xVjzymyDzUN8dk0Wd3RWMlGLXi07UCQ/CgQVb8LvXx3XBajJH4XGgkt7H7g==}
-    engines: {node: '>=6.9.0'}
-
-  '@babel/highlight@7.25.9':
-    resolution: {integrity: sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==}
+  '@babel/helpers@7.26.0':
+    resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==}
     engines: {node: '>=6.9.0'}
 
   '@babel/parser@7.25.9':
@@ -578,6 +577,11 @@ packages:
     engines: {node: '>=6.0.0'}
     hasBin: true
 
+  '@babel/parser@7.26.3':
+    resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==}
+    engines: {node: '>=6.0.0'}
+    hasBin: true
+
   '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9':
     resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==}
     engines: {node: '>=6.9.0'}
@@ -608,6 +612,13 @@ packages:
     peerDependencies:
       '@babel/core': ^7.0.0
 
+  '@babel/plugin-proposal-private-methods@7.18.6':
+    resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==}
+    engines: {node: '>=6.9.0'}
+    deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
   '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2':
     resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==}
     engines: {node: '>=6.9.0'}
@@ -626,6 +637,12 @@ packages:
     peerDependencies:
       '@babel/core': ^7.0.0-0
 
+  '@babel/plugin-syntax-jsx@7.25.9':
+    resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
   '@babel/plugin-syntax-unicode-sets-regex@7.18.6':
     resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==}
     engines: {node: '>=6.9.0'}
@@ -860,6 +877,18 @@ packages:
     peerDependencies:
       '@babel/core': ^7.0.0-0
 
+  '@babel/plugin-transform-react-jsx-self@7.25.9':
+    resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
+  '@babel/plugin-transform-react-jsx-source@7.25.9':
+    resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==}
+    engines: {node: '>=6.9.0'}
+    peerDependencies:
+      '@babel/core': ^7.0.0-0
+
   '@babel/plugin-transform-regenerator@7.25.9':
     resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==}
     engines: {node: '>=6.9.0'}
@@ -957,6 +986,10 @@ packages:
     resolution: {integrity: sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==}
     engines: {node: '>=6.9.0'}
 
+  '@babel/types@7.26.3':
+    resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==}
+    engines: {node: '>=6.9.0'}
+
   '@bugsnag/browser@7.25.0':
     resolution: {integrity: sha512-PzzWy5d9Ly1CU1KkxTB6ZaOw/dO+CYSfVtqxVJccy832e6+7rW/dvSw5Jy7rsNhgcKSKjZq86LtNkPSvritOLA==}
 
@@ -2452,10 +2485,6 @@ packages:
   '@remirror/core-constants@3.0.0':
     resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==}
 
-  '@remix-run/router@1.20.0':
-    resolution: {integrity: sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==}
-    engines: {node: '>=14.0.0'}
-
   '@rollup/plugin-babel@5.3.1':
     resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==}
     engines: {node: '>= 10.0.0'}
@@ -2741,9 +2770,6 @@ packages:
   '@swc/counter@0.1.3':
     resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
 
-  '@swc/plugin-styled-components@2.0.12':
-    resolution: {integrity: sha512-ZlA2T++rRRH734gt3+/FGfQc/oIWVQ69xl+FbeWQflB8YYG30/ADCqDOJ90XXo21hk3FZ0sMilXfaqqFUvYy0g==}
-
   '@swc/types@0.1.13':
     resolution: {integrity: sha512-JL7eeCk6zWCbiYQg2xQSdLXQJl8Qoc9rXmG2cEKvHe3CKwMHwHGpfOb8frzNLmbycOo6I51qxnLnn9ESf4I20Q==}
 
@@ -2751,6 +2777,34 @@ packages:
     resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==}
     engines: {node: '>=14.16'}
 
+  '@tanstack/history@1.95.0':
+    resolution: {integrity: sha512-w1/yWuIBqmG0Z0MPMf1OuOCce7FXyVH4L4dIA4rvpnjIUCH8qRUgloFAVg37nTMUbOmhMsY2NZDxCpKBv+CLJg==}
+    engines: {node: '>=12'}
+
+  '@tanstack/react-router@1.95.1':
+    resolution: {integrity: sha512-P5x4yNhcdkYsCEoYeGZP8Q9Jlxf0WXJa4G/xvbmM905seZc9FqJqvCSRvX3dWTPOXRABhl4g+8DHqfft0c/AvQ==}
+    engines: {node: '>=12'}
+    peerDependencies:
+      react: '>=18'
+      react-dom: '>=18'
+
+  '@tanstack/react-store@0.7.0':
+    resolution: {integrity: sha512-S/Rq17HaGOk+tQHV/yrePMnG1xbsKZIl/VsNWnNXt4XW+tTY8dTlvpJH2ZQ3GRALsusG5K6Q3unAGJ2pd9W/Ng==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+      react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+  '@tanstack/router-devtools@1.95.1':
+    resolution: {integrity: sha512-3EtYN0k9QxamQgmIH2SeDQDkrydH3Z1noFXKovBOePXKGjebyrlXV8VxBxNerx0TWQjxvlESiJM9DOxOlGujPg==}
+    engines: {node: '>=12'}
+    peerDependencies:
+      '@tanstack/react-router': ^1.95.1
+      react: '>=18'
+      react-dom: '>=18'
+
+  '@tanstack/store@0.7.0':
+    resolution: {integrity: sha512-CNIhdoUsmD2NolYuaIs8VfWM467RK6oIBAW4nPEKZhg1smZ+/CwtCdpURgp7nxSqOaV9oKkzdWD80+bC66F/Jg==}
+
   '@tiptap/core@2.9.1':
     resolution: {integrity: sha512-tifnLL/ARzQ6/FGEJjVwj9UT3v+pENdWHdk9x6F3X0mB1y0SeCjV21wpFLYESzwNdBPAj8NMp8Behv7dBnhIfw==}
     peerDependencies:
@@ -2932,6 +2986,18 @@ packages:
   '@types/argparse@1.0.38':
     resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==}
 
+  '@types/babel__core@7.20.5':
+    resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+  '@types/babel__generator@7.6.8':
+    resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==}
+
+  '@types/babel__template@7.4.4':
+    resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+  '@types/babel__traverse@7.20.6':
+    resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==}
+
   '@types/cookie@0.6.0':
     resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==}
 
@@ -3034,6 +3100,9 @@ packages:
   '@types/eslint@9.6.1':
     resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==}
 
+  '@types/estree-jsx@1.0.5':
+    resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
+
   '@types/estree@0.0.39':
     resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==}
 
@@ -3047,8 +3116,8 @@ packages:
   '@types/geojson@7946.0.14':
     resolution: {integrity: sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==}
 
-  '@types/hast@2.3.10':
-    resolution: {integrity: sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw==}
+  '@types/hast@3.0.4':
+    resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==}
 
   '@types/history@4.7.11':
     resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==}
@@ -3086,9 +3155,6 @@ packages:
   '@types/markdown-it@14.1.2':
     resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==}
 
-  '@types/mdast@3.0.15':
-    resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==}
-
   '@types/mdast@4.0.4':
     resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==}
 
@@ -3119,8 +3185,8 @@ packages:
   '@types/pug@2.0.10':
     resolution: {integrity: sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA==}
 
-  '@types/react-dom@18.3.1':
-    resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==}
+  '@types/react-dom@19.0.1':
+    resolution: {integrity: sha512-hljHij7MpWPKF6u5vojuyfV0YA4YURsQG7KT6SzV0Zs2BXAtgdTxG6A229Ub/xiWV4w/7JL8fi6aAyjshH4meA==}
 
   '@types/react-pdf@7.0.0':
     resolution: {integrity: sha512-G0a+5UiKk3AvEauBP/Js7r9kGZNW3iBbS6kXkH0foGSaKWR6K3ElTe7Y4tlolc2VKbM9udmMxpkbxh/dtR2wXA==}
@@ -3138,6 +3204,9 @@ packages:
   '@types/react@18.3.12':
     resolution: {integrity: sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==}
 
+  '@types/react@19.0.1':
+    resolution: {integrity: sha512-YW6614BDhqbpR5KtUYzTA+zlA7nayzJRA9ljz9CQoxthR0sDisYZLuvSMsil36t4EH/uAt8T52Xb4sVw17G+SQ==}
+
   '@types/resolve@1.20.2':
     resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
 
@@ -3311,10 +3380,11 @@ packages:
     engines: {node: '>=16'}
     hasBin: true
 
-  '@vitejs/plugin-react-swc@3.7.1':
-    resolution: {integrity: sha512-vgWOY0i1EROUK0Ctg1hwhtC3SdcDjZcdit4Ups4aPkDcB1jYhmo+RMYWY87cmXMhvtD5uf8lV89j2w16vkdSVg==}
+  '@vitejs/plugin-react@4.3.4':
+    resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==}
+    engines: {node: ^14.18.0 || >=16.0.0}
     peerDependencies:
-      vite: ^4 || ^5
+      vite: ^4.2.0 || ^5.0.0 || ^6.0.0
 
   '@vitest/expect@2.1.3':
     resolution: {integrity: sha512-SNBoPubeCJhZ48agjXruCI57DvxcsivVDdWz+SSsmjTT4QN/DfHk3zB/xKsJqMs26bLZ/pNRLnCf0j679i0uWQ==}
@@ -3720,6 +3790,14 @@ packages:
     peerDependencies:
       prismjs: ^1.18.0
 
+  babel-plugin-react-compiler@19.0.0-beta-37ed2a7-20241206:
+    resolution: {integrity: sha512-nnkrHpeDKM8A5laq9tmFvvGbbDQ7laGfQLp50cvCkCXmWrPcZdCtaQpNh8UJS/yLREJnv2R4JDL5ADfxyAn+yQ==}
+
+  babel-plugin-styled-components@2.1.4:
+    resolution: {integrity: sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==}
+    peerDependencies:
+      styled-components: '>= 2'
+
   backoff@2.5.0:
     resolution: {integrity: sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==}
     engines: {node: '>= 0.6'}
@@ -3923,9 +4001,18 @@ packages:
     resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
     engines: {node: '>=10'}
 
+  character-entities-html4@2.1.0:
+    resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==}
+
+  character-entities-legacy@3.0.0:
+    resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==}
+
   character-entities@2.0.2:
     resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
 
+  character-reference-invalid@2.0.1:
+    resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
+
   chardet@0.7.0:
     resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==}
 
@@ -4518,10 +4605,6 @@ packages:
     resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
     engines: {node: '>=0.3.1'}
 
-  diff@5.2.0:
-    resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==}
-    engines: {node: '>=0.3.1'}
-
   dir-glob@3.0.1:
     resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
     engines: {node: '>=8'}
@@ -4796,6 +4879,12 @@ packages:
       eslint-config-prettier:
         optional: true
 
+  eslint-plugin-react-compiler@19.0.0-beta-37ed2a7-20241206:
+    resolution: {integrity: sha512-5Pex1fUCJwLwwqEJe6NkgTn45kUjjj9TZP6IrW4IcpWM/YaEe+QvcOeF60huDjBq0kz1svGeW2nw8WdY+qszAw==}
+    engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0}
+    peerDependencies:
+      eslint: '>=7'
+
   eslint-plugin-react-hooks@4.6.2:
     resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==}
     engines: {node: '>=10'}
@@ -4881,6 +4970,9 @@ packages:
     resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
     engines: {node: '>=4.0'}
 
+  estree-util-is-identifier-name@3.0.0:
+    resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==}
+
   estree-walker@1.0.1:
     resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==}
 
@@ -5482,8 +5574,17 @@ packages:
     resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
     engines: {node: '>= 0.4'}
 
-  hast-util-whitespace@2.0.1:
-    resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==}
+  hast-util-to-jsx-runtime@2.3.2:
+    resolution: {integrity: sha512-1ngXYb+V9UT5h+PxNRa1O1FYguZK/XL+gkeqvp7EdHlB9oHUG0eYRo/vY5inBdcqo3RkPMC58/H94HvkbfGdyg==}
+
+  hast-util-whitespace@3.0.0:
+    resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
+
+  hermes-estree@0.25.1:
+    resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==}
+
+  hermes-parser@0.25.1:
+    resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==}
 
   highlight.js@10.7.3:
     resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
@@ -5503,6 +5604,9 @@ packages:
   hotkeys-js@3.9.4:
     resolution: {integrity: sha512-2zuLt85Ta+gIyvs4N88pCYskNrxf1TFv3LR9t5mdAZIX8BcgQQ48F2opUptvHa6m8zsy5v/a0i9mWzTrlNWU0Q==}
 
+  html-url-attributes@3.0.1:
+    resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
+
   http-cache-semantics@4.1.1:
     resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
 
@@ -5626,8 +5730,8 @@ packages:
     resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==}
     engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
 
-  inline-style-parser@0.1.1:
-    resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==}
+  inline-style-parser@0.2.4:
+    resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==}
 
   inquirer-autocomplete-prompt@1.4.0:
     resolution: {integrity: sha512-qHgHyJmbULt4hI+kCmwX92MnSxDs/Yhdt4wPA30qnoa01OF6uTXV8yvH4hKXgdaTNmkZ9D01MHjqKYEuJN+ONw==}
@@ -5660,6 +5764,12 @@ packages:
   iron-webcrypto@1.2.1:
     resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==}
 
+  is-alphabetical@2.0.1:
+    resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==}
+
+  is-alphanumerical@2.0.1:
+    resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==}
+
   is-array-buffer@3.0.4:
     resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==}
     engines: {node: '>= 0.4'}
@@ -5685,10 +5795,6 @@ packages:
     resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==}
     engines: {node: '>= 0.4'}
 
-  is-buffer@2.0.5:
-    resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==}
-    engines: {node: '>=4'}
-
   is-builtin-module@3.2.1:
     resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==}
     engines: {node: '>=6'}
@@ -5709,6 +5815,9 @@ packages:
     resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
     engines: {node: '>= 0.4'}
 
+  is-decimal@2.0.1:
+    resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==}
+
   is-docker@2.2.1:
     resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==}
     engines: {node: '>=8'}
@@ -5750,6 +5859,9 @@ packages:
     resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
     engines: {node: '>=0.10.0'}
 
+  is-hexadecimal@2.0.1:
+    resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==}
+
   is-in-ci@1.0.0:
     resolution: {integrity: sha512-eUuAjybVTHMYWm/U+vBO1sY/JOCgoPCXRxzdju0K+K0BiGW0SChEL1MLC0PoCIR1OlPo5YAp8HuQoUlsWEICwg==}
     engines: {node: '>=18'}
@@ -6322,47 +6434,47 @@ packages:
     resolution: {integrity: sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==}
     engines: {node: '>=8'}
 
-  mdast-util-definitions@5.1.2:
-    resolution: {integrity: sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==}
-
-  mdast-util-find-and-replace@2.2.2:
-    resolution: {integrity: sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==}
-
-  mdast-util-from-markdown@1.3.1:
-    resolution: {integrity: sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww==}
+  mdast-util-find-and-replace@3.0.2:
+    resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==}
 
   mdast-util-from-markdown@2.0.1:
     resolution: {integrity: sha512-aJEUyzZ6TzlsX2s5B4Of7lN7EQtAxvtradMMglCQDyaTFgse6CmtmdJ15ElnVRlCg1vpNyVtbem0PWzlNieZsA==}
 
-  mdast-util-gfm-autolink-literal@1.0.3:
-    resolution: {integrity: sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==}
+  mdast-util-gfm-autolink-literal@2.0.1:
+    resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==}
 
-  mdast-util-gfm-footnote@1.0.2:
-    resolution: {integrity: sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==}
+  mdast-util-gfm-footnote@2.0.0:
+    resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==}
 
-  mdast-util-gfm-strikethrough@1.0.3:
-    resolution: {integrity: sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==}
+  mdast-util-gfm-strikethrough@2.0.0:
+    resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==}
 
-  mdast-util-gfm-table@1.0.7:
-    resolution: {integrity: sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==}
+  mdast-util-gfm-table@2.0.0:
+    resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==}
 
-  mdast-util-gfm-task-list-item@1.0.2:
-    resolution: {integrity: sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==}
+  mdast-util-gfm-task-list-item@2.0.0:
+    resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==}
 
-  mdast-util-gfm@2.0.2:
-    resolution: {integrity: sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==}
+  mdast-util-gfm@3.0.0:
+    resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==}
 
-  mdast-util-phrasing@3.0.1:
-    resolution: {integrity: sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==}
+  mdast-util-mdx-expression@2.0.1:
+    resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==}
 
-  mdast-util-to-hast@12.3.0:
-    resolution: {integrity: sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==}
+  mdast-util-mdx-jsx@3.2.0:
+    resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==}
 
-  mdast-util-to-markdown@1.5.0:
-    resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==}
+  mdast-util-mdxjs-esm@2.0.1:
+    resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==}
 
-  mdast-util-to-string@3.2.0:
-    resolution: {integrity: sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==}
+  mdast-util-phrasing@4.1.0:
+    resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==}
+
+  mdast-util-to-hast@13.2.0:
+    resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==}
+
+  mdast-util-to-markdown@2.1.2:
+    resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==}
 
   mdast-util-to-string@4.0.0:
     resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==}
@@ -6418,150 +6530,87 @@ packages:
   micro-memoize@4.1.2:
     resolution: {integrity: sha512-+HzcV2H+rbSJzApgkj0NdTakkC+bnyeiUxgT6/m7mjcz1CmM22KYFKp+EVj1sWe4UYcnriJr5uqHQD/gMHLD+g==}
 
-  micromark-core-commonmark@1.1.0:
-    resolution: {integrity: sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw==}
-
   micromark-core-commonmark@2.0.1:
     resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==}
 
-  micromark-extension-gfm-autolink-literal@1.0.5:
-    resolution: {integrity: sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==}
-
-  micromark-extension-gfm-footnote@1.1.2:
-    resolution: {integrity: sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==}
+  micromark-extension-gfm-autolink-literal@2.1.0:
+    resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==}
 
-  micromark-extension-gfm-strikethrough@1.0.7:
-    resolution: {integrity: sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==}
+  micromark-extension-gfm-footnote@2.1.0:
+    resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==}
 
-  micromark-extension-gfm-table@1.0.7:
-    resolution: {integrity: sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==}
+  micromark-extension-gfm-strikethrough@2.1.0:
+    resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==}
 
-  micromark-extension-gfm-tagfilter@1.0.2:
-    resolution: {integrity: sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==}
+  micromark-extension-gfm-table@2.1.1:
+    resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==}
 
-  micromark-extension-gfm-task-list-item@1.0.5:
-    resolution: {integrity: sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==}
+  micromark-extension-gfm-tagfilter@2.0.0:
+    resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==}
 
-  micromark-extension-gfm@2.0.3:
-    resolution: {integrity: sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==}
+  micromark-extension-gfm-task-list-item@2.1.0:
+    resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==}
 
-  micromark-factory-destination@1.1.0:
-    resolution: {integrity: sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg==}
+  micromark-extension-gfm@3.0.0:
+    resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==}
 
   micromark-factory-destination@2.0.0:
     resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==}
 
-  micromark-factory-label@1.1.0:
-    resolution: {integrity: sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w==}
-
   micromark-factory-label@2.0.0:
     resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==}
 
-  micromark-factory-space@1.1.0:
-    resolution: {integrity: sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ==}
-
   micromark-factory-space@2.0.0:
     resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==}
 
-  micromark-factory-title@1.1.0:
-    resolution: {integrity: sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ==}
-
   micromark-factory-title@2.0.0:
     resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==}
 
-  micromark-factory-whitespace@1.1.0:
-    resolution: {integrity: sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ==}
-
   micromark-factory-whitespace@2.0.0:
     resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==}
 
-  micromark-util-character@1.2.0:
-    resolution: {integrity: sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg==}
-
   micromark-util-character@2.1.0:
     resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==}
 
-  micromark-util-chunked@1.1.0:
-    resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==}
-
   micromark-util-chunked@2.0.0:
     resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==}
 
-  micromark-util-classify-character@1.1.0:
-    resolution: {integrity: sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw==}
-
   micromark-util-classify-character@2.0.0:
     resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==}
 
-  micromark-util-combine-extensions@1.1.0:
-    resolution: {integrity: sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA==}
-
   micromark-util-combine-extensions@2.0.0:
     resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==}
 
-  micromark-util-decode-numeric-character-reference@1.1.0:
-    resolution: {integrity: sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw==}
-
   micromark-util-decode-numeric-character-reference@2.0.1:
     resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==}
 
-  micromark-util-decode-string@1.1.0:
-    resolution: {integrity: sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ==}
-
   micromark-util-decode-string@2.0.0:
     resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==}
 
-  micromark-util-encode@1.1.0:
-    resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==}
-
   micromark-util-encode@2.0.0:
     resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==}
 
-  micromark-util-html-tag-name@1.2.0:
-    resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==}
-
   micromark-util-html-tag-name@2.0.0:
     resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==}
 
-  micromark-util-normalize-identifier@1.1.0:
-    resolution: {integrity: sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q==}
-
   micromark-util-normalize-identifier@2.0.0:
     resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==}
 
-  micromark-util-resolve-all@1.1.0:
-    resolution: {integrity: sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA==}
-
   micromark-util-resolve-all@2.0.0:
     resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==}
 
-  micromark-util-sanitize-uri@1.2.0:
-    resolution: {integrity: sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A==}
-
   micromark-util-sanitize-uri@2.0.0:
     resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==}
 
-  micromark-util-subtokenize@1.1.0:
-    resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==}
-
   micromark-util-subtokenize@2.0.1:
     resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==}
 
-  micromark-util-symbol@1.1.0:
-    resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==}
-
   micromark-util-symbol@2.0.0:
     resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==}
 
-  micromark-util-types@1.1.0:
-    resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==}
-
   micromark-util-types@2.0.0:
     resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==}
 
-  micromark@3.2.0:
-    resolution: {integrity: sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA==}
-
   micromark@4.0.0:
     resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==}
 
@@ -7081,6 +7130,9 @@ packages:
     resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
     engines: {node: '>=6'}
 
+  parse-entities@4.0.2:
+    resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==}
+
   parse-github-url@1.0.3:
     resolution: {integrity: sha512-tfalY5/4SqGaV/GIGzWyHnFjlpTPTNpENR9Ea2lLldSJ8EWXMsvacWucqY3m3I4YPtas15IxTLQVQ5NSYXPrww==}
     engines: {node: '>= 0.10'}
@@ -7552,10 +7604,10 @@ packages:
       react: '>=16.8.0'
       react-dom: '>=16.8.0'
 
-  react-dom@18.3.1:
-    resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==}
+  react-dom@19.0.0:
+    resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==}
     peerDependencies:
-      react: ^18.3.1
+      react: ^19.0.0
 
   react-dropzone@11.7.1:
     resolution: {integrity: sha512-zxCMwhfPy1olUEbw3FLNPLhAm/HnaYH5aELIEglRbqabizKAdHs0h+WuyOpmA+v1JXn0++fpQDdNfUagWt5hJQ==}
@@ -7563,15 +7615,6 @@ packages:
     peerDependencies:
       react: '>= 16.8'
 
-  react-fast-compare@3.2.2:
-    resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==}
-
-  react-helmet-async@1.3.0:
-    resolution: {integrity: sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==}
-    peerDependencies:
-      react: ^16.6.0 || ^17.0.0 || ^18.0.0
-      react-dom: ^16.6.0 || ^17.0.0 || ^18.0.0
-
   react-hot-toast@2.4.1:
     resolution: {integrity: sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==}
     engines: {node: '>=10'}
@@ -7605,14 +7648,14 @@ packages:
   react-is@17.0.2:
     resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
 
-  react-is@18.3.1:
-    resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
+  react-is@19.0.0:
+    resolution: {integrity: sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==}
 
-  react-markdown@8.0.7:
-    resolution: {integrity: sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==}
+  react-markdown@9.0.3:
+    resolution: {integrity: sha512-Yk7Z94dbgYTOrdk41Z74GoKA7rThnsbbqBTRYuxoe08qvfQ9tJVhmAKw6BJS/ZORG7kTy/s1QvYzSuaoBA1qfw==}
     peerDependencies:
-      '@types/react': '>=16'
-      react: '>=16'
+      '@types/react': '>=18'
+      react: '>=18'
 
   react-pdf@9.1.1:
     resolution: {integrity: sha512-Cn3RTJZMqVOOCgLMRXDamLk4LPGfyB2Np3OwQAUjmHIh47EpuGW1OpAA1Z1GVDLoHx4d5duEDo/YbUkDbr4QFQ==}
@@ -7624,6 +7667,10 @@ packages:
       '@types/react':
         optional: true
 
+  react-refresh@0.14.2:
+    resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==}
+    engines: {node: '>=0.10.0'}
+
   react-remove-scroll-bar@2.3.6:
     resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==}
     engines: {node: '>=10'}
@@ -7644,19 +7691,6 @@ packages:
       '@types/react':
         optional: true
 
-  react-router-dom@6.27.0:
-    resolution: {integrity: sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==}
-    engines: {node: '>=14.0.0'}
-    peerDependencies:
-      react: '>=16.8'
-      react-dom: '>=16.8'
-
-  react-router@6.27.0:
-    resolution: {integrity: sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==}
-    engines: {node: '>=14.0.0'}
-    peerDependencies:
-      react: '>=16.8'
-
   react-style-singleton@2.2.1:
     resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==}
     engines: {node: '>=10'}
@@ -7680,8 +7714,8 @@ packages:
       react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
       react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
 
-  react@18.3.1:
-    resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==}
+  react@19.0.0:
+    resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
     engines: {node: '>=0.10.0'}
 
   reactflow@11.11.4:
@@ -7776,14 +7810,17 @@ packages:
     resolution: {integrity: sha512-1DHODs4B8p/mQHU9kr+jv8+wIC9mtG4eBHxWxIq5mhjE3D5oORhCc6deRKzTjs9DcfRFmj9BHSDguZklqCGFWQ==}
     hasBin: true
 
-  remark-gfm@3.0.1:
-    resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==}
+  remark-gfm@4.0.0:
+    resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==}
 
-  remark-parse@10.0.2:
-    resolution: {integrity: sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==}
+  remark-parse@11.0.0:
+    resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
 
-  remark-rehype@10.1.0:
-    resolution: {integrity: sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw==}
+  remark-rehype@11.1.1:
+    resolution: {integrity: sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==}
+
+  remark-stringify@11.0.0:
+    resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
 
   remove-trailing-separator@1.1.0:
     resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==}
@@ -7927,8 +7964,8 @@ packages:
   sander@0.5.1:
     resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==}
 
-  scheduler@0.23.2:
-    resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==}
+  scheduler@0.25.0:
+    resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==}
 
   secure-json-parse@2.7.0:
     resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==}
@@ -8210,6 +8247,9 @@ packages:
   string_decoder@1.3.0:
     resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
 
+  stringify-entities@4.0.4:
+    resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==}
+
   stringify-object@3.3.0:
     resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==}
     engines: {node: '>=4'}
@@ -8279,8 +8319,8 @@ packages:
   stubborn-fs@1.2.5:
     resolution: {integrity: sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==}
 
-  style-to-object@0.4.4:
-    resolution: {integrity: sha512-HYNoHZa2GorYNyqiCaBgsxvcJIn7OHq6inEga+E6Ke3m5JkoqpQbnFssk4jwe+K7AhGa2fcha4wSOf1Kn01dMg==}
+  style-to-object@1.0.8:
+    resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==}
 
   styled-components@6.1.13:
     resolution: {integrity: sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==}
@@ -8494,6 +8534,9 @@ packages:
   tiny-invariant@1.3.3:
     resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
 
+  tiny-warning@1.0.3:
+    resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
+
   tinybench@2.9.0:
     resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
 
@@ -8807,8 +8850,8 @@ packages:
     resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
     engines: {node: '>=18'}
 
-  unified@10.1.2:
-    resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==}
+  unified@11.0.5:
+    resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==}
 
   unique-string@2.0.0:
     resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==}
@@ -8818,26 +8861,20 @@ packages:
     resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==}
     engines: {node: '>=12'}
 
-  unist-util-generated@2.0.1:
-    resolution: {integrity: sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==}
-
-  unist-util-is@5.2.1:
-    resolution: {integrity: sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==}
+  unist-util-is@6.0.0:
+    resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==}
 
-  unist-util-position@4.0.4:
-    resolution: {integrity: sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==}
-
-  unist-util-stringify-position@3.0.3:
-    resolution: {integrity: sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==}
+  unist-util-position@5.0.0:
+    resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==}
 
   unist-util-stringify-position@4.0.0:
     resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==}
 
-  unist-util-visit-parents@5.1.3:
-    resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==}
+  unist-util-visit-parents@6.0.1:
+    resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==}
 
-  unist-util-visit@4.1.2:
-    resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==}
+  unist-util-visit@5.0.0:
+    resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
 
   universal-user-agent@6.0.1:
     resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==}
@@ -8962,6 +8999,11 @@ packages:
     peerDependencies:
       react: ^16.8.0 || ^17.0.0 || ^18.0.0
 
+  use-sync-external-store@1.4.0:
+    resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==}
+    peerDependencies:
+      react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
   util-deprecate@1.0.2:
     resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
 
@@ -8973,11 +9015,6 @@ packages:
     resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
     hasBin: true
 
-  uvu@0.5.6:
-    resolution: {integrity: sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA==}
-    engines: {node: '>=8'}
-    hasBin: true
-
   v8-compile-cache-lib@3.0.1:
     resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
 
@@ -8996,11 +9033,11 @@ packages:
     resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
     engines: {node: '>= 0.8'}
 
-  vfile-message@3.1.4:
-    resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==}
+  vfile-message@4.0.2:
+    resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
 
-  vfile@5.3.7:
-    resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==}
+  vfile@6.0.3:
+    resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
 
   vite-node@2.1.3:
     resolution: {integrity: sha512-I1JadzO+xYX887S39Do+paRePCKoiDrWRRjp9kkG5he0t7RXNvPAJPCQSJqbGN4uCrFFeS3Kj3sLqY8NMYBEdA==}
@@ -9345,6 +9382,12 @@ packages:
     resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==}
     engines: {node: '>= 14'}
 
+  zod-validation-error@3.4.0:
+    resolution: {integrity: sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==}
+    engines: {node: '>=18.0.0'}
+    peerDependencies:
+      zod: ^3.18.0
+
   zod@3.23.8:
     resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==}
 
@@ -9402,25 +9445,26 @@ snapshots:
       typescript: 5.6.1-rc
       validate-npm-package-name: 5.0.1
 
-  '@babel/code-frame@7.25.9':
+  '@babel/code-frame@7.26.2':
     dependencies:
-      '@babel/highlight': 7.25.9
+      '@babel/helper-validator-identifier': 7.25.9
+      js-tokens: 4.0.0
       picocolors: 1.1.1
 
   '@babel/compat-data@7.25.9': {}
 
-  '@babel/core@7.25.9':
+  '@babel/core@7.26.0':
     dependencies:
       '@ampproject/remapping': 2.3.0
-      '@babel/code-frame': 7.25.9
-      '@babel/generator': 7.25.9
+      '@babel/code-frame': 7.26.2
+      '@babel/generator': 7.26.3
       '@babel/helper-compilation-targets': 7.25.9
-      '@babel/helper-module-transforms': 7.25.9(@babel/core@7.25.9)
-      '@babel/helpers': 7.25.9
-      '@babel/parser': 7.25.9
+      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
+      '@babel/helpers': 7.26.0
+      '@babel/parser': 7.26.3
       '@babel/template': 7.25.9
       '@babel/traverse': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
       convert-source-map: 2.0.0
       debug: 4.3.7(supports-color@9.4.0)
       gensync: 1.0.0-beta.2
@@ -9429,21 +9473,22 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/generator@7.25.9':
+  '@babel/generator@7.26.3':
     dependencies:
-      '@babel/types': 7.25.9
+      '@babel/parser': 7.26.3
+      '@babel/types': 7.26.3
       '@jridgewell/gen-mapping': 0.3.5
       '@jridgewell/trace-mapping': 0.3.25
       jsesc: 3.0.2
 
   '@babel/helper-annotate-as-pure@7.25.9':
     dependencies:
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
 
   '@babel/helper-builder-binary-assignment-operator-visitor@7.25.9':
     dependencies:
       '@babel/traverse': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
     transitivePeerDependencies:
       - supports-color
 
@@ -9455,29 +9500,29 @@ snapshots:
       lru-cache: 5.1.1
       semver: 6.3.1
 
-  '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.25.9)':
+  '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-annotate-as-pure': 7.25.9
       '@babel/helper-member-expression-to-functions': 7.25.9
       '@babel/helper-optimise-call-expression': 7.25.9
-      '@babel/helper-replace-supers': 7.25.9(@babel/core@7.25.9)
+      '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
       '@babel/traverse': 7.25.9
       semver: 6.3.1
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/helper-create-regexp-features-plugin@7.25.9(@babel/core@7.25.9)':
+  '@babel/helper-create-regexp-features-plugin@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-annotate-as-pure': 7.25.9
       regexpu-core: 6.1.1
       semver: 6.3.1
 
-  '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.25.9)':
+  '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-compilation-targets': 7.25.9
       '@babel/helper-plugin-utils': 7.25.9
       debug: 4.3.7(supports-color@9.4.0)
@@ -9489,22 +9534,21 @@ snapshots:
   '@babel/helper-member-expression-to-functions@7.25.9':
     dependencies:
       '@babel/traverse': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
     transitivePeerDependencies:
       - supports-color
 
   '@babel/helper-module-imports@7.25.9':
     dependencies:
       '@babel/traverse': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/helper-module-transforms@7.25.9(@babel/core@7.25.9)':
+  '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-module-imports': 7.25.9
-      '@babel/helper-simple-access': 7.25.9
       '@babel/helper-validator-identifier': 7.25.9
       '@babel/traverse': 7.25.9
     transitivePeerDependencies:
@@ -9512,22 +9556,22 @@ snapshots:
 
   '@babel/helper-optimise-call-expression@7.25.9':
     dependencies:
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
 
   '@babel/helper-plugin-utils@7.25.9': {}
 
-  '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.25.9)':
+  '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-annotate-as-pure': 7.25.9
       '@babel/helper-wrap-function': 7.25.9
       '@babel/traverse': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/helper-replace-supers@7.25.9(@babel/core@7.25.9)':
+  '@babel/helper-replace-supers@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-member-expression-to-functions': 7.25.9
       '@babel/helper-optimise-call-expression': 7.25.9
       '@babel/traverse': 7.25.9
@@ -9537,14 +9581,14 @@ snapshots:
   '@babel/helper-simple-access@7.25.9':
     dependencies:
       '@babel/traverse': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
     transitivePeerDependencies:
       - supports-color
 
   '@babel/helper-skip-transparent-expression-wrappers@7.25.9':
     dependencies:
       '@babel/traverse': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
     transitivePeerDependencies:
       - supports-color
 
@@ -9558,477 +9602,497 @@ snapshots:
     dependencies:
       '@babel/template': 7.25.9
       '@babel/traverse': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/helpers@7.25.9':
+  '@babel/helpers@7.26.0':
     dependencies:
       '@babel/template': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
 
-  '@babel/highlight@7.25.9':
+  '@babel/parser@7.25.9':
     dependencies:
-      '@babel/helper-validator-identifier': 7.25.9
-      chalk: 2.4.2
-      js-tokens: 4.0.0
-      picocolors: 1.1.1
+      '@babel/types': 7.26.3
 
-  '@babel/parser@7.25.9':
+  '@babel/parser@7.26.3':
     dependencies:
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
 
-  '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/traverse': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
-      '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.25.9)
+      '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/traverse': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.9)':
+  '@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.26.0)':
+    dependencies:
+      '@babel/core': 7.26.0
+      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
+      '@babel/helper-plugin-utils': 7.25.9
+    transitivePeerDependencies:
+      - supports-color
+
+  '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)':
+    dependencies:
+      '@babel/core': 7.26.0
+
+  '@babel/plugin-syntax-import-assertions@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
+      '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-syntax-import-assertions@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-syntax-import-attributes@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-syntax-import-attributes@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.25.9)':
+  '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-async-generator-functions@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-async-generator-functions@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
-      '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.25.9)
+      '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0)
       '@babel/traverse': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-module-imports': 7.25.9
       '@babel/helper-plugin-utils': 7.25.9
-      '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.25.9)
+      '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-block-scoped-functions@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-block-scoped-functions@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-class-static-block@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-class-static-block@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-classes@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-annotate-as-pure': 7.25.9
       '@babel/helper-compilation-targets': 7.25.9
       '@babel/helper-plugin-utils': 7.25.9
-      '@babel/helper-replace-supers': 7.25.9(@babel/core@7.25.9)
+      '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0)
       '@babel/traverse': 7.25.9
       globals: 11.12.0
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/template': 7.25.9
 
-  '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-exponentiation-operator@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-exponentiation-operator@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-builder-binary-assignment-operator-visitor': 7.25.9
       '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-for-of@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-for-of@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-compilation-targets': 7.25.9
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/traverse': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-literals@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-module-transforms': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-modules-commonjs@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-modules-commonjs@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-module-transforms': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-simple-access': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-module-transforms': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-validator-identifier': 7.25.9
       '@babel/traverse': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-module-transforms': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-nullish-coalescing-operator@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-nullish-coalescing-operator@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-compilation-targets': 7.25.9
       '@babel/helper-plugin-utils': 7.25.9
-      '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.25.9)
+      '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0)
 
-  '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
-      '@babel/helper-replace-supers': 7.25.9(@babel/core@7.25.9)
+      '@babel/helper-replace-supers': 7.25.9(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-annotate-as-pure': 7.25.9
-      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/helper-create-class-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.0)':
+    dependencies:
+      '@babel/core': 7.26.0
+      '@babel/helper-plugin-utils': 7.25.9
+
+  '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.0)':
+    dependencies:
+      '@babel/core': 7.26.0
+      '@babel/helper-plugin-utils': 7.25.9
+
+  '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
       regenerator-transform: 0.15.2
 
-  '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-spread@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-skip-transparent-expression-wrappers': 7.25.9
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-template-literals@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-template-literals@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-typeof-symbol@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-typeof-symbol@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.25.9)':
+  '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-create-regexp-features-plugin': 7.25.9(@babel/core@7.26.0)
       '@babel/helper-plugin-utils': 7.25.9
 
-  '@babel/preset-env@7.25.9(@babel/core@7.25.9)':
+  '@babel/preset-env@7.25.9(@babel/core@7.26.0)':
     dependencies:
       '@babel/compat-data': 7.25.9
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-compilation-targets': 7.25.9
       '@babel/helper-plugin-utils': 7.25.9
       '@babel/helper-validator-option': 7.25.9
-      '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.25.9)
-      '@babel/plugin-syntax-import-assertions': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-syntax-import-attributes': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.25.9)
-      '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-async-generator-functions': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-block-scoped-functions': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-class-static-block': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-exponentiation-operator': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-for-of': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-nullish-coalescing-operator': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-template-literals': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-typeof-symbol': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.25.9)
-      '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.25.9)
-      '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.25.9)
-      babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.25.9)
-      babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.25.9)
-      babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.25.9)
+      '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.0)
+      '@babel/plugin-syntax-import-assertions': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-syntax-import-attributes': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.0)
+      '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-async-generator-functions': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-block-scoped-functions': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-class-static-block': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-exponentiation-operator': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-for-of': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-modules-commonjs': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-nullish-coalescing-operator': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-template-literals': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-typeof-symbol': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.0)
+      '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.0)
+      babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.26.0)
+      babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.26.0)
+      babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.26.0)
       core-js-compat: 3.38.1
       semver: 6.3.1
     transitivePeerDependencies:
       - supports-color
 
-  '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.25.9)':
+  '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.0)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-plugin-utils': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
       esutils: 2.0.3
 
   '@babel/runtime@7.25.9':
@@ -10037,17 +10101,17 @@ snapshots:
 
   '@babel/template@7.25.9':
     dependencies:
-      '@babel/code-frame': 7.25.9
-      '@babel/parser': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/code-frame': 7.26.2
+      '@babel/parser': 7.26.3
+      '@babel/types': 7.26.3
 
   '@babel/traverse@7.25.9':
     dependencies:
-      '@babel/code-frame': 7.25.9
-      '@babel/generator': 7.25.9
-      '@babel/parser': 7.25.9
+      '@babel/code-frame': 7.26.2
+      '@babel/generator': 7.26.3
+      '@babel/parser': 7.26.3
       '@babel/template': 7.25.9
-      '@babel/types': 7.25.9
+      '@babel/types': 7.26.3
       debug: 4.3.7(supports-color@9.4.0)
       globals: 11.12.0
     transitivePeerDependencies:
@@ -10064,6 +10128,11 @@ snapshots:
       '@babel/helper-string-parser': 7.25.9
       '@babel/helper-validator-identifier': 7.25.9
 
+  '@babel/types@7.26.3':
+    dependencies:
+      '@babel/helper-string-parser': 7.25.9
+      '@babel/helper-validator-identifier': 7.25.9
+
   '@bugsnag/browser@7.25.0':
     dependencies:
       '@bugsnag/core': 7.25.0
@@ -10124,35 +10193,35 @@ snapshots:
       gonzales-pe: 4.3.0
       node-source-walk: 6.0.2
 
-  '@dnd-kit/accessibility@3.1.0(react@18.3.1)':
+  '@dnd-kit/accessibility@3.1.0(react@19.0.0)':
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
       tslib: 2.8.0
 
-  '@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@dnd-kit/core@6.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@dnd-kit/accessibility': 3.1.0(react@18.3.1)
-      '@dnd-kit/utilities': 3.2.2(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@dnd-kit/accessibility': 3.1.0(react@19.0.0)
+      '@dnd-kit/utilities': 3.2.2(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
       tslib: 2.8.0
 
-  '@dnd-kit/sortable@8.0.0(@dnd-kit/core@6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1)':
+  '@dnd-kit/sortable@8.0.0(@dnd-kit/core@6.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@dnd-kit/core': 6.1.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@dnd-kit/utilities': 3.2.2(react@18.3.1)
-      react: 18.3.1
+      '@dnd-kit/core': 6.1.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@dnd-kit/utilities': 3.2.2(react@19.0.0)
+      react: 19.0.0
       tslib: 2.8.0
 
-  '@dnd-kit/utilities@3.2.2(react@18.3.1)':
+  '@dnd-kit/utilities@3.2.2(react@19.0.0)':
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
       tslib: 2.8.0
 
-  '@emoji-mart/react@1.1.1(emoji-mart@5.6.0)(react@18.3.1)':
+  '@emoji-mart/react@1.1.1(emoji-mart@5.6.0)(react@19.0.0)':
     dependencies:
       emoji-mart: 5.6.0
-      react: 18.3.1
+      react: 19.0.0
 
   '@emotion/is-prop-valid@1.2.2':
     dependencies:
@@ -10551,11 +10620,11 @@ snapshots:
       '@floating-ui/core': 1.6.8
       '@floating-ui/utils': 0.2.8
 
-  '@floating-ui/react-dom@2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@floating-ui/react-dom@2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
       '@floating-ui/dom': 1.6.11
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
 
   '@floating-ui/utils@0.2.8': {}
 
@@ -10939,7 +11008,7 @@ snapshots:
 
   '@netlify/zip-it-and-ship-it@9.40.2(supports-color@9.4.0)':
     dependencies:
-      '@babel/parser': 7.25.9
+      '@babel/parser': 7.26.3
       '@babel/types': 7.25.6
       '@netlify/binary-info': 1.0.0
       '@netlify/serverless-functions-api': 1.30.1
@@ -10979,7 +11048,7 @@ snapshots:
 
   '@netlify/zip-it-and-ship-it@9.41.0(supports-color@9.4.0)':
     dependencies:
-      '@babel/parser': 7.25.9
+      '@babel/parser': 7.26.3
       '@babel/types': 7.25.6
       '@netlify/binary-info': 1.0.0
       '@netlify/serverless-functions-api': 1.30.1
@@ -11188,280 +11257,280 @@ snapshots:
 
   '@radix-ui/primitive@1.1.0': {}
 
-  '@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-arrow@1.1.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-collection@1.1.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-context': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-context': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-slot': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-compose-refs@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-context@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-context@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-context@1.1.1(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-context@1.1.1(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-direction@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-direction@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-dismissable-layer@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-dismissable-layer@1.1.1(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
       '@radix-ui/primitive': 1.1.0
-      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-focus-guards@1.1.1(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-focus-guards@1.1.1(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-focus-scope@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-focus-scope@1.1.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-id@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-id@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-popover@1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-popover@1.1.2(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
       '@radix-ui/primitive': 1.1.0
-      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-dismissable-layer': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-focus-guards': 1.1.1(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-portal': 1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-presence': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1)
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-context': 1.1.1(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-dismissable-layer': 1.1.1(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-focus-guards': 1.1.1(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-id': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-popper': 1.2.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-portal': 1.1.2(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-presence': 1.1.1(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-slot': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.1)(react@19.0.0)
       aria-hidden: 1.2.4
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      react-remove-scroll: 2.6.0(@types/react@18.3.12)(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      react-remove-scroll: 2.6.0(@types/react@19.0.1)(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
-
-  '@radix-ui/react-popper@1.2.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
-    dependencies:
-      '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-arrow': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-context': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-use-rect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-use-size': 1.1.0(@types/react@18.3.12)(react@18.3.1)
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
+
+  '@radix-ui/react-popper@1.2.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+    dependencies:
+      '@floating-ui/react-dom': 2.1.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-arrow': 1.1.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-context': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-use-rect': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-use-size': 1.1.0(@types/react@19.0.1)(react@19.0.0)
       '@radix-ui/rect': 1.1.0
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-portal@1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-portal@1.1.2(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-presence@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-presence@1.1.1(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-primitive@2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-primitive@2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-slot': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-slot': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-roving-focus@1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-roving-focus@1.1.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
       '@radix-ui/primitive': 1.1.0
-      '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-context': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-collection': 1.1.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-context': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-direction': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-id': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-scroll-area@1.2.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-scroll-area@1.2.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
       '@radix-ui/number': 1.1.0
       '@radix-ui/primitive': 1.1.0
-      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-presence': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-context': 1.1.1(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-direction': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-presence': 1.1.1(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-slot@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-slot@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
+      '@radix-ui/react-compose-refs': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-tabs@1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@radix-ui/react-tabs@1.1.1(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
       '@radix-ui/primitive': 1.1.0
-      '@radix-ui/react-context': 1.1.1(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-direction': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-id': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      '@radix-ui/react-presence': 1.1.1(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.1)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@radix-ui/react-context': 1.1.1(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-direction': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-id': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      '@radix-ui/react-presence': 1.1.1(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-primitive': 2.0.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@19.0.1)(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      '@types/react-dom': 18.3.1
+      '@types/react': 19.0.1
+      '@types/react-dom': 19.0.1
 
-  '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-use-callback-ref@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-use-controllable-state@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
+      '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-use-layout-effect@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-use-rect@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-use-rect@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
       '@radix-ui/rect': 1.1.0
-      react: 18.3.1
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@radix-ui/react-use-size@1.1.0(@types/react@18.3.12)(react@18.3.1)':
+  '@radix-ui/react-use-size@1.1.0(@types/react@19.0.1)(react@19.0.0)':
     dependencies:
-      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.12)(react@18.3.1)
-      react: 18.3.1
+      '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@19.0.1)(react@19.0.0)
+      react: 19.0.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
   '@radix-ui/rect@1.1.0': {}
 
-  '@reactflow/background@11.3.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@reactflow/background@11.3.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@reactflow/core': 11.11.4(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+      '@reactflow/core': 11.11.4(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       classcat: 5.0.5
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      zustand: 4.5.5(@types/react@18.3.12)(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      zustand: 4.5.5(@types/react@19.0.1)(react@19.0.0)
     transitivePeerDependencies:
       - '@types/react'
       - immer
 
-  '@reactflow/controls@11.2.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@reactflow/controls@11.2.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@reactflow/core': 11.11.4(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+      '@reactflow/core': 11.11.4(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       classcat: 5.0.5
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      zustand: 4.5.5(@types/react@18.3.12)(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      zustand: 4.5.5(@types/react@19.0.1)(react@19.0.0)
     transitivePeerDependencies:
       - '@types/react'
       - immer
 
-  '@reactflow/core@11.11.4(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@reactflow/core@11.11.4(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
       '@types/d3': 7.4.3
       '@types/d3-drag': 3.0.7
@@ -11471,62 +11540,62 @@ snapshots:
       d3-drag: 3.0.0
       d3-selection: 3.0.0
       d3-zoom: 3.0.0
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      zustand: 4.5.5(@types/react@18.3.12)(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      zustand: 4.5.5(@types/react@19.0.1)(react@19.0.0)
     transitivePeerDependencies:
       - '@types/react'
       - immer
 
-  '@reactflow/minimap@11.7.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@reactflow/minimap@11.7.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@reactflow/core': 11.11.4(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+      '@reactflow/core': 11.11.4(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       '@types/d3-selection': 3.0.11
       '@types/d3-zoom': 3.0.8
       classcat: 5.0.5
       d3-selection: 3.0.0
       d3-zoom: 3.0.0
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      zustand: 4.5.5(@types/react@18.3.12)(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      zustand: 4.5.5(@types/react@19.0.1)(react@19.0.0)
     transitivePeerDependencies:
       - '@types/react'
       - immer
 
-  '@reactflow/node-resizer@2.2.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@reactflow/node-resizer@2.2.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@reactflow/core': 11.11.4(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+      '@reactflow/core': 11.11.4(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       classcat: 5.0.5
       d3-drag: 3.0.0
       d3-selection: 3.0.0
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      zustand: 4.5.5(@types/react@18.3.12)(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      zustand: 4.5.5(@types/react@19.0.1)(react@19.0.0)
     transitivePeerDependencies:
       - '@types/react'
       - immer
 
-  '@reactflow/node-toolbar@1.3.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@reactflow/node-toolbar@1.3.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      '@reactflow/core': 11.11.4(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+      '@reactflow/core': 11.11.4(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
       classcat: 5.0.5
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      zustand: 4.5.5(@types/react@18.3.12)(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      zustand: 4.5.5(@types/react@19.0.1)(react@19.0.0)
     transitivePeerDependencies:
       - '@types/react'
       - immer
 
   '@remirror/core-constants@3.0.0': {}
 
-  '@remix-run/router@1.20.0': {}
-
-  '@rollup/plugin-babel@5.3.1(@babel/core@7.25.9)(rollup@2.79.2)':
+  '@rollup/plugin-babel@5.3.1(@babel/core@7.26.0)(@types/babel__core@7.20.5)(rollup@2.79.2)':
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       '@babel/helper-module-imports': 7.25.9
       '@rollup/pluginutils': 3.1.0(rollup@2.79.2)
       rollup: 2.79.2
+    optionalDependencies:
+      '@types/babel__core': 7.20.5
     transitivePeerDependencies:
       - supports-color
 
@@ -11779,21 +11848,51 @@ snapshots:
       '@swc/core-win32-arm64-msvc': 1.7.39
       '@swc/core-win32-ia32-msvc': 1.7.39
       '@swc/core-win32-x64-msvc': 1.7.39
+    optional: true
 
-  '@swc/counter@0.1.3': {}
-
-  '@swc/plugin-styled-components@2.0.12':
-    dependencies:
-      '@swc/counter': 0.1.3
+  '@swc/counter@0.1.3':
+    optional: true
 
   '@swc/types@0.1.13':
     dependencies:
       '@swc/counter': 0.1.3
+    optional: true
 
   '@szmarczak/http-timer@5.0.1':
     dependencies:
       defer-to-connect: 2.0.1
 
+  '@tanstack/history@1.95.0': {}
+
+  '@tanstack/react-router@1.95.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+    dependencies:
+      '@tanstack/history': 1.95.0
+      '@tanstack/react-store': 0.7.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      jsesc: 3.0.2
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      tiny-invariant: 1.3.3
+      tiny-warning: 1.0.3
+
+  '@tanstack/react-store@0.7.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+    dependencies:
+      '@tanstack/store': 0.7.0
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      use-sync-external-store: 1.4.0(react@19.0.0)
+
+  '@tanstack/router-devtools@1.95.1(@tanstack/react-router@1.95.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
+    dependencies:
+      '@tanstack/react-router': 1.95.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      clsx: 2.1.1
+      goober: 2.1.16(csstype@3.1.3)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+    transitivePeerDependencies:
+      - csstype
+
+  '@tanstack/store@0.7.0': {}
+
   '@tiptap/core@2.9.1(@tiptap/pm@2.9.1)':
     dependencies:
       '@tiptap/pm': 2.9.1
@@ -11931,7 +12030,7 @@ snapshots:
       prosemirror-transform: 1.10.2
       prosemirror-view: 1.34.3
 
-  '@tiptap/react@2.9.1(@tiptap/core@2.9.1(@tiptap/pm@2.9.1))(@tiptap/pm@2.9.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@tiptap/react@2.9.1(@tiptap/core@2.9.1(@tiptap/pm@2.9.1))(@tiptap/pm@2.9.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
       '@tiptap/core': 2.9.1(@tiptap/pm@2.9.1)
       '@tiptap/extension-bubble-menu': 2.9.1(@tiptap/core@2.9.1(@tiptap/pm@2.9.1))(@tiptap/pm@2.9.1)
@@ -11939,9 +12038,9 @@ snapshots:
       '@tiptap/pm': 2.9.1
       '@types/use-sync-external-store': 0.0.6
       fast-deep-equal: 3.1.3
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      use-sync-external-store: 1.2.2(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
+      use-sync-external-store: 1.2.2(react@19.0.0)
 
   '@tiptap/starter-kit@2.9.1':
     dependencies:
@@ -11986,6 +12085,27 @@ snapshots:
 
   '@types/argparse@1.0.38': {}
 
+  '@types/babel__core@7.20.5':
+    dependencies:
+      '@babel/parser': 7.25.9
+      '@babel/types': 7.25.9
+      '@types/babel__generator': 7.6.8
+      '@types/babel__template': 7.4.4
+      '@types/babel__traverse': 7.20.6
+
+  '@types/babel__generator@7.6.8':
+    dependencies:
+      '@babel/types': 7.26.3
+
+  '@types/babel__template@7.4.4':
+    dependencies:
+      '@babel/parser': 7.26.3
+      '@babel/types': 7.26.3
+
+  '@types/babel__traverse@7.20.6':
+    dependencies:
+      '@babel/types': 7.26.3
+
   '@types/cookie@0.6.0': {}
 
   '@types/d3-array@3.2.1': {}
@@ -12114,6 +12234,10 @@ snapshots:
       '@types/estree': 1.0.6
       '@types/json-schema': 7.0.15
 
+  '@types/estree-jsx@1.0.5':
+    dependencies:
+      '@types/estree': 1.0.6
+
   '@types/estree@0.0.39': {}
 
   '@types/estree@1.0.6': {}
@@ -12124,9 +12248,9 @@ snapshots:
 
   '@types/geojson@7946.0.14': {}
 
-  '@types/hast@2.3.10':
+  '@types/hast@3.0.4':
     dependencies:
-      '@types/unist': 2.0.11
+      '@types/unist': 3.0.3
 
   '@types/history@4.7.11': {}
 
@@ -12164,10 +12288,6 @@ snapshots:
       '@types/linkify-it': 5.0.0
       '@types/mdurl': 2.0.0
 
-  '@types/mdast@3.0.15':
-    dependencies:
-      '@types/unist': 2.0.11
-
   '@types/mdast@4.0.4':
     dependencies:
       '@types/unist': 3.0.3
@@ -12192,13 +12312,13 @@ snapshots:
 
   '@types/pug@2.0.10': {}
 
-  '@types/react-dom@18.3.1':
+  '@types/react-dom@19.0.1':
     dependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  '@types/react-pdf@7.0.0(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+  '@types/react-pdf@7.0.0(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
     dependencies:
-      react-pdf: 9.1.1(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+      react-pdf: 9.1.1(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
     transitivePeerDependencies:
       - '@types/react'
       - encoding
@@ -12215,17 +12335,21 @@ snapshots:
   '@types/react-router@5.1.20':
     dependencies:
       '@types/history': 4.7.11
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
   '@types/react-window@1.8.8':
     dependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
   '@types/react@18.3.12':
     dependencies:
       '@types/prop-types': 15.7.13
       csstype: 3.1.3
 
+  '@types/react@19.0.1':
+    dependencies:
+      csstype: 3.1.3
+
   '@types/resolve@1.20.2': {}
 
   '@types/retry@0.12.1': {}
@@ -12456,12 +12580,16 @@ snapshots:
       - encoding
       - supports-color
 
-  '@vitejs/plugin-react-swc@3.7.1(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))':
+  '@vitejs/plugin-react@4.3.4(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))':
     dependencies:
-      '@swc/core': 1.7.39
+      '@babel/core': 7.26.0
+      '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.0)
+      '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.0)
+      '@types/babel__core': 7.20.5
+      react-refresh: 0.14.2
       vite: 5.4.10(@types/node@20.17.0)(terser@5.36.0)
     transitivePeerDependencies:
-      - '@swc/helpers'
+      - supports-color
 
   '@vitest/expect@2.1.3':
     dependencies:
@@ -12895,27 +13023,27 @@ snapshots:
 
   b4a@1.6.7: {}
 
-  babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.25.9):
+  babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.26.0):
     dependencies:
       '@babel/compat-data': 7.25.9
-      '@babel/core': 7.25.9
-      '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0)
       semver: 6.3.1
     transitivePeerDependencies:
       - supports-color
 
-  babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.25.9):
+  babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.26.0):
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0)
       core-js-compat: 3.38.1
     transitivePeerDependencies:
       - supports-color
 
-  babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.25.9):
+  babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.26.0):
     dependencies:
-      '@babel/core': 7.25.9
-      '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.26.0)
     transitivePeerDependencies:
       - supports-color
 
@@ -12923,15 +13051,31 @@ snapshots:
     dependencies:
       prismjs: 1.29.0
 
-  backoff@2.5.0:
+  babel-plugin-react-compiler@19.0.0-beta-37ed2a7-20241206:
     dependencies:
-      precond: 0.2.3
-
-  bail@2.0.2: {}
-
-  balanced-match@1.0.2: {}
+      '@babel/types': 7.26.3
 
-  bare-events@2.5.0:
+  babel-plugin-styled-components@2.1.4(@babel/core@7.26.0)(styled-components@6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)):
+    dependencies:
+      '@babel/helper-annotate-as-pure': 7.25.9
+      '@babel/helper-module-imports': 7.25.9
+      '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0)
+      lodash: 4.17.21
+      picomatch: 2.3.1
+      styled-components: 6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+    transitivePeerDependencies:
+      - '@babel/core'
+      - supports-color
+
+  backoff@2.5.0:
+    dependencies:
+      precond: 0.2.3
+
+  bail@2.0.2: {}
+
+  balanced-match@1.0.2: {}
+
+  bare-events@2.5.0:
     optional: true
 
   bare-fs@2.3.5:
@@ -12962,7 +13106,7 @@ snapshots:
 
   better-ajv-errors@1.2.0(ajv@8.17.1):
     dependencies:
-      '@babel/code-frame': 7.25.9
+      '@babel/code-frame': 7.26.2
       '@humanwhocodes/momoa': 2.0.4
       ajv: 8.17.1
       chalk: 4.1.2
@@ -13156,8 +13300,14 @@ snapshots:
 
   char-regex@1.0.2: {}
 
+  character-entities-html4@2.1.0: {}
+
+  character-entities-legacy@3.0.0: {}
+
   character-entities@2.0.2: {}
 
+  character-reference-invalid@2.0.1: {}
+
   chardet@0.7.0: {}
 
   check-error@2.1.1: {}
@@ -13733,8 +13883,6 @@ snapshots:
 
   diff@4.0.2: {}
 
-  diff@5.2.0: {}
-
   dir-glob@3.0.1:
     dependencies:
       path-type: 4.0.0
@@ -14151,6 +14299,18 @@ snapshots:
       '@types/eslint': 9.6.1
       eslint-config-prettier: 9.1.0(eslint@8.57.1)
 
+  eslint-plugin-react-compiler@19.0.0-beta-37ed2a7-20241206(eslint@8.57.1):
+    dependencies:
+      '@babel/core': 7.26.0
+      '@babel/parser': 7.25.9
+      '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.26.0)
+      eslint: 8.57.1
+      hermes-parser: 0.25.1
+      zod: 3.23.8
+      zod-validation-error: 3.4.0(zod@3.23.8)
+    transitivePeerDependencies:
+      - supports-color
+
   eslint-plugin-react-hooks@4.6.2(eslint@8.57.1):
     dependencies:
       eslint: 8.57.1
@@ -14326,6 +14486,8 @@ snapshots:
 
   estraverse@5.3.0: {}
 
+  estree-util-is-identifier-name@3.0.0: {}
+
   estree-walker@1.0.1: {}
 
   estree-walker@2.0.2: {}
@@ -15037,7 +15199,35 @@ snapshots:
     dependencies:
       function-bind: 1.1.2
 
-  hast-util-whitespace@2.0.1: {}
+  hast-util-to-jsx-runtime@2.3.2:
+    dependencies:
+      '@types/estree': 1.0.6
+      '@types/hast': 3.0.4
+      '@types/unist': 3.0.3
+      comma-separated-tokens: 2.0.3
+      devlop: 1.1.0
+      estree-util-is-identifier-name: 3.0.0
+      hast-util-whitespace: 3.0.0
+      mdast-util-mdx-expression: 2.0.1
+      mdast-util-mdx-jsx: 3.2.0
+      mdast-util-mdxjs-esm: 2.0.1
+      property-information: 6.5.0
+      space-separated-tokens: 2.0.2
+      style-to-object: 1.0.8
+      unist-util-position: 5.0.0
+      vfile-message: 4.0.2
+    transitivePeerDependencies:
+      - supports-color
+
+  hast-util-whitespace@3.0.0:
+    dependencies:
+      '@types/hast': 3.0.4
+
+  hermes-estree@0.25.1: {}
+
+  hermes-parser@0.25.1:
+    dependencies:
+      hermes-estree: 0.25.1
 
   highlight.js@10.7.3: {}
 
@@ -15055,6 +15245,8 @@ snapshots:
 
   hotkeys-js@3.9.4: {}
 
+  html-url-attributes@3.0.1: {}
+
   http-cache-semantics@4.1.1: {}
 
   http-errors@1.8.1:
@@ -15166,7 +15358,7 @@ snapshots:
 
   ini@4.1.1: {}
 
-  inline-style-parser@0.1.1: {}
+  inline-style-parser@0.2.4: {}
 
   inquirer-autocomplete-prompt@1.4.0(inquirer@6.5.2):
     dependencies:
@@ -15244,6 +15436,13 @@ snapshots:
 
   iron-webcrypto@1.2.1: {}
 
+  is-alphabetical@2.0.1: {}
+
+  is-alphanumerical@2.0.1:
+    dependencies:
+      is-alphabetical: 2.0.1
+      is-decimal: 2.0.1
+
   is-array-buffer@3.0.4:
     dependencies:
       call-bind: 1.0.7
@@ -15270,8 +15469,6 @@ snapshots:
       call-bind: 1.0.7
       has-tostringtag: 1.0.2
 
-  is-buffer@2.0.5: {}
-
   is-builtin-module@3.2.1:
     dependencies:
       builtin-modules: 3.3.0
@@ -15290,6 +15487,8 @@ snapshots:
     dependencies:
       has-tostringtag: 1.0.2
 
+  is-decimal@2.0.1: {}
+
   is-docker@2.2.1: {}
 
   is-docker@3.0.0: {}
@@ -15318,6 +15517,8 @@ snapshots:
     dependencies:
       is-extglob: 2.1.1
 
+  is-hexadecimal@2.0.1: {}
+
   is-in-ci@1.0.0: {}
 
   is-inside-container@1.0.0:
@@ -15871,35 +16072,12 @@ snapshots:
     dependencies:
       blueimp-md5: 2.19.0
 
-  mdast-util-definitions@5.1.2:
-    dependencies:
-      '@types/mdast': 3.0.15
-      '@types/unist': 2.0.11
-      unist-util-visit: 4.1.2
-
-  mdast-util-find-and-replace@2.2.2:
+  mdast-util-find-and-replace@3.0.2:
     dependencies:
-      '@types/mdast': 3.0.15
+      '@types/mdast': 4.0.4
       escape-string-regexp: 5.0.0
-      unist-util-is: 5.2.1
-      unist-util-visit-parents: 5.1.3
-
-  mdast-util-from-markdown@1.3.1:
-    dependencies:
-      '@types/mdast': 3.0.15
-      '@types/unist': 2.0.11
-      decode-named-character-reference: 1.0.2
-      mdast-util-to-string: 3.2.0
-      micromark: 3.2.0
-      micromark-util-decode-numeric-character-reference: 1.1.0
-      micromark-util-decode-string: 1.1.0
-      micromark-util-normalize-identifier: 1.1.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-      unist-util-stringify-position: 3.0.3
-      uvu: 0.5.6
-    transitivePeerDependencies:
-      - supports-color
+      unist-util-is: 6.0.0
+      unist-util-visit-parents: 6.0.1
 
   mdast-util-from-markdown@2.0.1:
     dependencies:
@@ -15918,81 +16096,131 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  mdast-util-gfm-autolink-literal@1.0.3:
+  mdast-util-gfm-autolink-literal@2.0.1:
     dependencies:
-      '@types/mdast': 3.0.15
+      '@types/mdast': 4.0.4
       ccount: 2.0.1
-      mdast-util-find-and-replace: 2.2.2
-      micromark-util-character: 1.2.0
+      devlop: 1.1.0
+      mdast-util-find-and-replace: 3.0.2
+      micromark-util-character: 2.1.0
 
-  mdast-util-gfm-footnote@1.0.2:
+  mdast-util-gfm-footnote@2.0.0:
     dependencies:
-      '@types/mdast': 3.0.15
-      mdast-util-to-markdown: 1.5.0
-      micromark-util-normalize-identifier: 1.1.0
+      '@types/mdast': 4.0.4
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.1
+      mdast-util-to-markdown: 2.1.2
+      micromark-util-normalize-identifier: 2.0.0
+    transitivePeerDependencies:
+      - supports-color
 
-  mdast-util-gfm-strikethrough@1.0.3:
+  mdast-util-gfm-strikethrough@2.0.0:
     dependencies:
-      '@types/mdast': 3.0.15
-      mdast-util-to-markdown: 1.5.0
+      '@types/mdast': 4.0.4
+      mdast-util-from-markdown: 2.0.1
+      mdast-util-to-markdown: 2.1.2
+    transitivePeerDependencies:
+      - supports-color
 
-  mdast-util-gfm-table@1.0.7:
+  mdast-util-gfm-table@2.0.0:
     dependencies:
-      '@types/mdast': 3.0.15
+      '@types/mdast': 4.0.4
+      devlop: 1.1.0
       markdown-table: 3.0.4
-      mdast-util-from-markdown: 1.3.1
-      mdast-util-to-markdown: 1.5.0
+      mdast-util-from-markdown: 2.0.1
+      mdast-util-to-markdown: 2.1.2
     transitivePeerDependencies:
       - supports-color
 
-  mdast-util-gfm-task-list-item@1.0.2:
+  mdast-util-gfm-task-list-item@2.0.0:
     dependencies:
-      '@types/mdast': 3.0.15
-      mdast-util-to-markdown: 1.5.0
+      '@types/mdast': 4.0.4
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.1
+      mdast-util-to-markdown: 2.1.2
+    transitivePeerDependencies:
+      - supports-color
 
-  mdast-util-gfm@2.0.2:
+  mdast-util-gfm@3.0.0:
     dependencies:
-      mdast-util-from-markdown: 1.3.1
-      mdast-util-gfm-autolink-literal: 1.0.3
-      mdast-util-gfm-footnote: 1.0.2
-      mdast-util-gfm-strikethrough: 1.0.3
-      mdast-util-gfm-table: 1.0.7
-      mdast-util-gfm-task-list-item: 1.0.2
-      mdast-util-to-markdown: 1.5.0
+      mdast-util-from-markdown: 2.0.1
+      mdast-util-gfm-autolink-literal: 2.0.1
+      mdast-util-gfm-footnote: 2.0.0
+      mdast-util-gfm-strikethrough: 2.0.0
+      mdast-util-gfm-table: 2.0.0
+      mdast-util-gfm-task-list-item: 2.0.0
+      mdast-util-to-markdown: 2.1.2
     transitivePeerDependencies:
       - supports-color
 
-  mdast-util-phrasing@3.0.1:
+  mdast-util-mdx-expression@2.0.1:
     dependencies:
-      '@types/mdast': 3.0.15
-      unist-util-is: 5.2.1
+      '@types/estree-jsx': 1.0.5
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.1
+      mdast-util-to-markdown: 2.1.2
+    transitivePeerDependencies:
+      - supports-color
 
-  mdast-util-to-hast@12.3.0:
+  mdast-util-mdx-jsx@3.2.0:
     dependencies:
-      '@types/hast': 2.3.10
-      '@types/mdast': 3.0.15
-      mdast-util-definitions: 5.1.2
-      micromark-util-sanitize-uri: 1.2.0
+      '@types/estree-jsx': 1.0.5
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      '@types/unist': 3.0.3
+      ccount: 2.0.1
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.1
+      mdast-util-to-markdown: 2.1.2
+      parse-entities: 4.0.2
+      stringify-entities: 4.0.4
+      unist-util-stringify-position: 4.0.0
+      vfile-message: 4.0.2
+    transitivePeerDependencies:
+      - supports-color
+
+  mdast-util-mdxjs-esm@2.0.1:
+    dependencies:
+      '@types/estree-jsx': 1.0.5
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      devlop: 1.1.0
+      mdast-util-from-markdown: 2.0.1
+      mdast-util-to-markdown: 2.1.2
+    transitivePeerDependencies:
+      - supports-color
+
+  mdast-util-phrasing@4.1.0:
+    dependencies:
+      '@types/mdast': 4.0.4
+      unist-util-is: 6.0.0
+
+  mdast-util-to-hast@13.2.0:
+    dependencies:
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      '@ungap/structured-clone': 1.2.0
+      devlop: 1.1.0
+      micromark-util-sanitize-uri: 2.0.0
       trim-lines: 3.0.1
-      unist-util-generated: 2.0.1
-      unist-util-position: 4.0.4
-      unist-util-visit: 4.1.2
+      unist-util-position: 5.0.0
+      unist-util-visit: 5.0.0
+      vfile: 6.0.3
 
-  mdast-util-to-markdown@1.5.0:
+  mdast-util-to-markdown@2.1.2:
     dependencies:
-      '@types/mdast': 3.0.15
-      '@types/unist': 2.0.11
+      '@types/mdast': 4.0.4
+      '@types/unist': 3.0.3
       longest-streak: 3.1.0
-      mdast-util-phrasing: 3.0.1
-      mdast-util-to-string: 3.2.0
-      micromark-util-decode-string: 1.1.0
-      unist-util-visit: 4.1.2
+      mdast-util-phrasing: 4.1.0
+      mdast-util-to-string: 4.0.0
+      micromark-util-classify-character: 2.0.0
+      micromark-util-decode-string: 2.0.0
+      unist-util-visit: 5.0.0
       zwitch: 2.0.4
 
-  mdast-util-to-string@3.2.0:
-    dependencies:
-      '@types/mdast': 3.0.15
-
   mdast-util-to-string@4.0.0:
     dependencies:
       '@types/mdast': 4.0.4
@@ -16015,9 +16243,9 @@ snapshots:
     dependencies:
       is-plain-obj: 2.1.0
 
-  merge-refs@1.3.0(@types/react@18.3.12):
+  merge-refs@1.3.0(@types/react@19.0.1):
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
   merge-stream@2.0.0: {}
 
@@ -16029,25 +16257,6 @@ snapshots:
 
   micro-memoize@4.1.2: {}
 
-  micromark-core-commonmark@1.1.0:
-    dependencies:
-      decode-named-character-reference: 1.0.2
-      micromark-factory-destination: 1.1.0
-      micromark-factory-label: 1.1.0
-      micromark-factory-space: 1.1.0
-      micromark-factory-title: 1.1.0
-      micromark-factory-whitespace: 1.1.0
-      micromark-util-character: 1.2.0
-      micromark-util-chunked: 1.1.0
-      micromark-util-classify-character: 1.1.0
-      micromark-util-html-tag-name: 1.2.0
-      micromark-util-normalize-identifier: 1.1.0
-      micromark-util-resolve-all: 1.1.0
-      micromark-util-subtokenize: 1.1.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-      uvu: 0.5.6
-
   micromark-core-commonmark@2.0.1:
     dependencies:
       decode-named-character-reference: 1.0.2
@@ -16067,69 +16276,63 @@ snapshots:
       micromark-util-symbol: 2.0.0
       micromark-util-types: 2.0.0
 
-  micromark-extension-gfm-autolink-literal@1.0.5:
-    dependencies:
-      micromark-util-character: 1.2.0
-      micromark-util-sanitize-uri: 1.2.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-
-  micromark-extension-gfm-footnote@1.1.2:
+  micromark-extension-gfm-autolink-literal@2.1.0:
     dependencies:
-      micromark-core-commonmark: 1.1.0
-      micromark-factory-space: 1.1.0
-      micromark-util-character: 1.2.0
-      micromark-util-normalize-identifier: 1.1.0
-      micromark-util-sanitize-uri: 1.2.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-      uvu: 0.5.6
+      micromark-util-character: 2.1.0
+      micromark-util-sanitize-uri: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
 
-  micromark-extension-gfm-strikethrough@1.0.7:
+  micromark-extension-gfm-footnote@2.1.0:
     dependencies:
-      micromark-util-chunked: 1.1.0
-      micromark-util-classify-character: 1.1.0
-      micromark-util-resolve-all: 1.1.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-      uvu: 0.5.6
+      devlop: 1.1.0
+      micromark-core-commonmark: 2.0.1
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.1.0
+      micromark-util-normalize-identifier: 2.0.0
+      micromark-util-sanitize-uri: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
 
-  micromark-extension-gfm-table@1.0.7:
+  micromark-extension-gfm-strikethrough@2.1.0:
     dependencies:
-      micromark-factory-space: 1.1.0
-      micromark-util-character: 1.2.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-      uvu: 0.5.6
+      devlop: 1.1.0
+      micromark-util-chunked: 2.0.0
+      micromark-util-classify-character: 2.0.0
+      micromark-util-resolve-all: 2.0.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
 
-  micromark-extension-gfm-tagfilter@1.0.2:
+  micromark-extension-gfm-table@2.1.1:
     dependencies:
-      micromark-util-types: 1.1.0
+      devlop: 1.1.0
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.1.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
 
-  micromark-extension-gfm-task-list-item@1.0.5:
+  micromark-extension-gfm-tagfilter@2.0.0:
     dependencies:
-      micromark-factory-space: 1.1.0
-      micromark-util-character: 1.2.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-      uvu: 0.5.6
+      micromark-util-types: 2.0.0
 
-  micromark-extension-gfm@2.0.3:
+  micromark-extension-gfm-task-list-item@2.1.0:
     dependencies:
-      micromark-extension-gfm-autolink-literal: 1.0.5
-      micromark-extension-gfm-footnote: 1.1.2
-      micromark-extension-gfm-strikethrough: 1.0.7
-      micromark-extension-gfm-table: 1.0.7
-      micromark-extension-gfm-tagfilter: 1.0.2
-      micromark-extension-gfm-task-list-item: 1.0.5
-      micromark-util-combine-extensions: 1.1.0
-      micromark-util-types: 1.1.0
+      devlop: 1.1.0
+      micromark-factory-space: 2.0.0
+      micromark-util-character: 2.1.0
+      micromark-util-symbol: 2.0.0
+      micromark-util-types: 2.0.0
 
-  micromark-factory-destination@1.1.0:
+  micromark-extension-gfm@3.0.0:
     dependencies:
-      micromark-util-character: 1.2.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
+      micromark-extension-gfm-autolink-literal: 2.1.0
+      micromark-extension-gfm-footnote: 2.1.0
+      micromark-extension-gfm-strikethrough: 2.1.0
+      micromark-extension-gfm-table: 2.1.1
+      micromark-extension-gfm-tagfilter: 2.0.0
+      micromark-extension-gfm-task-list-item: 2.1.0
+      micromark-util-combine-extensions: 2.0.0
+      micromark-util-types: 2.0.0
 
   micromark-factory-destination@2.0.0:
     dependencies:
@@ -16137,13 +16340,6 @@ snapshots:
       micromark-util-symbol: 2.0.0
       micromark-util-types: 2.0.0
 
-  micromark-factory-label@1.1.0:
-    dependencies:
-      micromark-util-character: 1.2.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-      uvu: 0.5.6
-
   micromark-factory-label@2.0.0:
     dependencies:
       devlop: 1.1.0
@@ -16151,23 +16347,11 @@ snapshots:
       micromark-util-symbol: 2.0.0
       micromark-util-types: 2.0.0
 
-  micromark-factory-space@1.1.0:
-    dependencies:
-      micromark-util-character: 1.2.0
-      micromark-util-types: 1.1.0
-
   micromark-factory-space@2.0.0:
     dependencies:
       micromark-util-character: 2.1.0
       micromark-util-types: 2.0.0
 
-  micromark-factory-title@1.1.0:
-    dependencies:
-      micromark-factory-space: 1.1.0
-      micromark-util-character: 1.2.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-
   micromark-factory-title@2.0.0:
     dependencies:
       micromark-factory-space: 2.0.0
@@ -16175,13 +16359,6 @@ snapshots:
       micromark-util-symbol: 2.0.0
       micromark-util-types: 2.0.0
 
-  micromark-factory-whitespace@1.1.0:
-    dependencies:
-      micromark-factory-space: 1.1.0
-      micromark-util-character: 1.2.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-
   micromark-factory-whitespace@2.0.0:
     dependencies:
       micromark-factory-space: 2.0.0
@@ -16189,61 +16366,30 @@ snapshots:
       micromark-util-symbol: 2.0.0
       micromark-util-types: 2.0.0
 
-  micromark-util-character@1.2.0:
-    dependencies:
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-
   micromark-util-character@2.1.0:
     dependencies:
       micromark-util-symbol: 2.0.0
       micromark-util-types: 2.0.0
 
-  micromark-util-chunked@1.1.0:
-    dependencies:
-      micromark-util-symbol: 1.1.0
-
   micromark-util-chunked@2.0.0:
     dependencies:
       micromark-util-symbol: 2.0.0
 
-  micromark-util-classify-character@1.1.0:
-    dependencies:
-      micromark-util-character: 1.2.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-
   micromark-util-classify-character@2.0.0:
     dependencies:
       micromark-util-character: 2.1.0
       micromark-util-symbol: 2.0.0
       micromark-util-types: 2.0.0
 
-  micromark-util-combine-extensions@1.1.0:
-    dependencies:
-      micromark-util-chunked: 1.1.0
-      micromark-util-types: 1.1.0
-
   micromark-util-combine-extensions@2.0.0:
     dependencies:
       micromark-util-chunked: 2.0.0
       micromark-util-types: 2.0.0
 
-  micromark-util-decode-numeric-character-reference@1.1.0:
-    dependencies:
-      micromark-util-symbol: 1.1.0
-
   micromark-util-decode-numeric-character-reference@2.0.1:
     dependencies:
       micromark-util-symbol: 2.0.0
 
-  micromark-util-decode-string@1.1.0:
-    dependencies:
-      decode-named-character-reference: 1.0.2
-      micromark-util-character: 1.2.0
-      micromark-util-decode-numeric-character-reference: 1.1.0
-      micromark-util-symbol: 1.1.0
-
   micromark-util-decode-string@2.0.0:
     dependencies:
       decode-named-character-reference: 1.0.2
@@ -16251,49 +16397,24 @@ snapshots:
       micromark-util-decode-numeric-character-reference: 2.0.1
       micromark-util-symbol: 2.0.0
 
-  micromark-util-encode@1.1.0: {}
-
   micromark-util-encode@2.0.0: {}
 
-  micromark-util-html-tag-name@1.2.0: {}
-
   micromark-util-html-tag-name@2.0.0: {}
 
-  micromark-util-normalize-identifier@1.1.0:
-    dependencies:
-      micromark-util-symbol: 1.1.0
-
   micromark-util-normalize-identifier@2.0.0:
     dependencies:
       micromark-util-symbol: 2.0.0
 
-  micromark-util-resolve-all@1.1.0:
-    dependencies:
-      micromark-util-types: 1.1.0
-
   micromark-util-resolve-all@2.0.0:
     dependencies:
       micromark-util-types: 2.0.0
 
-  micromark-util-sanitize-uri@1.2.0:
-    dependencies:
-      micromark-util-character: 1.2.0
-      micromark-util-encode: 1.1.0
-      micromark-util-symbol: 1.1.0
-
   micromark-util-sanitize-uri@2.0.0:
     dependencies:
       micromark-util-character: 2.1.0
       micromark-util-encode: 2.0.0
       micromark-util-symbol: 2.0.0
 
-  micromark-util-subtokenize@1.1.0:
-    dependencies:
-      micromark-util-chunked: 1.1.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-      uvu: 0.5.6
-
   micromark-util-subtokenize@2.0.1:
     dependencies:
       devlop: 1.1.0
@@ -16301,36 +16422,10 @@ snapshots:
       micromark-util-symbol: 2.0.0
       micromark-util-types: 2.0.0
 
-  micromark-util-symbol@1.1.0: {}
-
   micromark-util-symbol@2.0.0: {}
 
-  micromark-util-types@1.1.0: {}
-
   micromark-util-types@2.0.0: {}
 
-  micromark@3.2.0:
-    dependencies:
-      '@types/debug': 4.1.12
-      debug: 4.3.7(supports-color@9.4.0)
-      decode-named-character-reference: 1.0.2
-      micromark-core-commonmark: 1.1.0
-      micromark-factory-space: 1.1.0
-      micromark-util-character: 1.2.0
-      micromark-util-chunked: 1.1.0
-      micromark-util-combine-extensions: 1.1.0
-      micromark-util-decode-numeric-character-reference: 1.1.0
-      micromark-util-encode: 1.1.0
-      micromark-util-normalize-identifier: 1.1.0
-      micromark-util-resolve-all: 1.1.0
-      micromark-util-sanitize-uri: 1.2.0
-      micromark-util-subtokenize: 1.1.0
-      micromark-util-symbol: 1.1.0
-      micromark-util-types: 1.1.0
-      uvu: 0.5.6
-    transitivePeerDependencies:
-      - supports-color
-
   micromark@4.0.0:
     dependencies:
       '@types/debug': 4.1.12
@@ -16692,7 +16787,7 @@ snapshots:
 
   node-source-walk@6.0.2:
     dependencies:
-      '@babel/parser': 7.25.9
+      '@babel/parser': 7.26.3
 
   node-stream-zip@1.15.0: {}
 
@@ -16990,20 +17085,30 @@ snapshots:
     dependencies:
       callsites: 3.1.0
 
+  parse-entities@4.0.2:
+    dependencies:
+      '@types/unist': 2.0.11
+      character-entities-legacy: 3.0.0
+      character-reference-invalid: 2.0.1
+      decode-named-character-reference: 1.0.2
+      is-alphanumerical: 2.0.1
+      is-decimal: 2.0.1
+      is-hexadecimal: 2.0.1
+
   parse-github-url@1.0.3: {}
 
   parse-gitignore@2.0.0: {}
 
   parse-json@5.2.0:
     dependencies:
-      '@babel/code-frame': 7.25.9
+      '@babel/code-frame': 7.26.2
       error-ex: 1.3.2
       json-parse-even-better-errors: 2.3.1
       lines-and-columns: 1.2.4
 
   parse-json@8.1.0:
     dependencies:
-      '@babel/code-frame': 7.25.9
+      '@babel/code-frame': 7.26.2
       index-to-position: 0.1.2
       type-fest: 4.26.1
 
@@ -17466,172 +17571,142 @@ snapshots:
       minimist: 1.2.8
       strip-json-comments: 2.0.1
 
-  react-colorful@5.6.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  react-colorful@5.6.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
     dependencies:
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
 
-  react-dom@18.3.1(react@18.3.1):
+  react-dom@19.0.0(react@19.0.0):
     dependencies:
-      loose-envify: 1.4.0
-      react: 18.3.1
-      scheduler: 0.23.2
+      react: 19.0.0
+      scheduler: 0.25.0
 
-  react-dropzone@11.7.1(react@18.3.1):
+  react-dropzone@11.7.1(react@19.0.0):
     dependencies:
       attr-accept: 2.2.4
       file-selector: 0.4.0
       prop-types: 15.8.1
-      react: 18.3.1
-
-  react-fast-compare@3.2.2: {}
-
-  react-helmet-async@1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
-    dependencies:
-      '@babel/runtime': 7.25.9
-      invariant: 2.2.4
-      prop-types: 15.8.1
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      react-fast-compare: 3.2.2
-      shallowequal: 1.1.0
+      react: 19.0.0
 
-  react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  react-hot-toast@2.4.1(csstype@3.1.3)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
     dependencies:
       goober: 2.1.16(csstype@3.1.3)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     transitivePeerDependencies:
       - csstype
 
-  react-hotkeys-hook@3.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  react-hotkeys-hook@3.4.7(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
     dependencies:
       hotkeys-js: 3.9.4
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
 
-  react-icons@4.12.0(react@18.3.1):
+  react-icons@4.12.0(react@19.0.0):
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
 
-  react-intersection-observer@9.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  react-intersection-observer@9.13.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
     optionalDependencies:
-      react-dom: 18.3.1(react@18.3.1)
+      react-dom: 19.0.0(react@19.0.0)
 
   react-is@16.13.1: {}
 
   react-is@17.0.2: {}
 
-  react-is@18.3.1: {}
+  react-is@19.0.0: {}
 
-  react-markdown@8.0.7(@types/react@18.3.12)(react@18.3.1):
+  react-markdown@9.0.3(@types/react@19.0.1)(react@19.0.0):
     dependencies:
-      '@types/hast': 2.3.10
-      '@types/prop-types': 15.7.13
-      '@types/react': 18.3.12
-      '@types/unist': 2.0.11
-      comma-separated-tokens: 2.0.3
-      hast-util-whitespace: 2.0.1
-      prop-types: 15.8.1
-      property-information: 6.5.0
-      react: 18.3.1
-      react-is: 18.3.1
-      remark-parse: 10.0.2
-      remark-rehype: 10.1.0
-      space-separated-tokens: 2.0.2
-      style-to-object: 0.4.4
-      unified: 10.1.2
-      unist-util-visit: 4.1.2
-      vfile: 5.3.7
+      '@types/hast': 3.0.4
+      '@types/react': 19.0.1
+      devlop: 1.1.0
+      hast-util-to-jsx-runtime: 2.3.2
+      html-url-attributes: 3.0.1
+      mdast-util-to-hast: 13.2.0
+      react: 19.0.0
+      remark-parse: 11.0.0
+      remark-rehype: 11.1.1
+      unified: 11.0.5
+      unist-util-visit: 5.0.0
+      vfile: 6.0.3
     transitivePeerDependencies:
       - supports-color
 
-  react-pdf@9.1.1(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  react-pdf@9.1.1(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
     dependencies:
       clsx: 2.1.1
       dequal: 2.0.3
       make-cancellable-promise: 1.3.2
       make-event-props: 1.6.2
-      merge-refs: 1.3.0(@types/react@18.3.12)
+      merge-refs: 1.3.0(@types/react@19.0.1)
       pdfjs-dist: 4.4.168
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
       tiny-invariant: 1.3.3
       warning: 4.0.3
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
     transitivePeerDependencies:
       - encoding
       - supports-color
 
-  react-remove-scroll-bar@2.3.6(@types/react@18.3.12)(react@18.3.1):
+  react-refresh@0.14.2: {}
+
+  react-remove-scroll-bar@2.3.6(@types/react@19.0.1)(react@19.0.0):
     dependencies:
-      react: 18.3.1
-      react-style-singleton: 2.2.1(@types/react@18.3.12)(react@18.3.1)
+      react: 19.0.0
+      react-style-singleton: 2.2.1(@types/react@19.0.1)(react@19.0.0)
       tslib: 2.8.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  react-remove-scroll@2.6.0(@types/react@18.3.12)(react@18.3.1):
+  react-remove-scroll@2.6.0(@types/react@19.0.1)(react@19.0.0):
     dependencies:
-      react: 18.3.1
-      react-remove-scroll-bar: 2.3.6(@types/react@18.3.12)(react@18.3.1)
-      react-style-singleton: 2.2.1(@types/react@18.3.12)(react@18.3.1)
+      react: 19.0.0
+      react-remove-scroll-bar: 2.3.6(@types/react@19.0.1)(react@19.0.0)
+      react-style-singleton: 2.2.1(@types/react@19.0.1)(react@19.0.0)
       tslib: 2.8.0
-      use-callback-ref: 1.3.2(@types/react@18.3.12)(react@18.3.1)
-      use-sidecar: 1.1.2(@types/react@18.3.12)(react@18.3.1)
+      use-callback-ref: 1.3.2(@types/react@19.0.1)(react@19.0.0)
+      use-sidecar: 1.1.2(@types/react@19.0.1)(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-
-  react-router-dom@6.27.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
-    dependencies:
-      '@remix-run/router': 1.20.0
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
-      react-router: 6.27.0(react@18.3.1)
+      '@types/react': 19.0.1
 
-  react-router@6.27.0(react@18.3.1):
-    dependencies:
-      '@remix-run/router': 1.20.0
-      react: 18.3.1
-
-  react-style-singleton@2.2.1(@types/react@18.3.12)(react@18.3.1):
+  react-style-singleton@2.2.1(@types/react@19.0.1)(react@19.0.0):
     dependencies:
       get-nonce: 1.0.1
       invariant: 2.2.4
-      react: 18.3.1
+      react: 19.0.0
       tslib: 2.8.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  react-virtualized-auto-sizer@1.0.24(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  react-virtualized-auto-sizer@1.0.24(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
     dependencies:
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
 
-  react-window@1.8.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  react-window@1.8.10(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
     dependencies:
       '@babel/runtime': 7.25.9
       memoize-one: 5.2.1
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
 
-  react@18.3.1:
-    dependencies:
-      loose-envify: 1.4.0
+  react@19.0.0: {}
 
-  reactflow@11.11.4(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  reactflow@11.11.4(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
     dependencies:
-      '@reactflow/background': 11.3.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@reactflow/controls': 11.2.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@reactflow/core': 11.11.4(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@reactflow/minimap': 11.7.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@reactflow/node-resizer': 2.2.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      '@reactflow/node-toolbar': 1.3.14(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      '@reactflow/background': 11.3.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@reactflow/controls': 11.2.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@reactflow/core': 11.11.4(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@reactflow/minimap': 11.7.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@reactflow/node-resizer': 2.2.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      '@reactflow/node-toolbar': 1.3.14(@types/react@19.0.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
     transitivePeerDependencies:
       - '@types/react'
       - immer
@@ -17755,29 +17830,39 @@ snapshots:
     dependencies:
       jsesc: 3.0.2
 
-  remark-gfm@3.0.1:
+  remark-gfm@4.0.0:
     dependencies:
-      '@types/mdast': 3.0.15
-      mdast-util-gfm: 2.0.2
-      micromark-extension-gfm: 2.0.3
-      unified: 10.1.2
+      '@types/mdast': 4.0.4
+      mdast-util-gfm: 3.0.0
+      micromark-extension-gfm: 3.0.0
+      remark-parse: 11.0.0
+      remark-stringify: 11.0.0
+      unified: 11.0.5
     transitivePeerDependencies:
       - supports-color
 
-  remark-parse@10.0.2:
+  remark-parse@11.0.0:
     dependencies:
-      '@types/mdast': 3.0.15
-      mdast-util-from-markdown: 1.3.1
-      unified: 10.1.2
+      '@types/mdast': 4.0.4
+      mdast-util-from-markdown: 2.0.1
+      micromark-util-types: 2.0.0
+      unified: 11.0.5
     transitivePeerDependencies:
       - supports-color
 
-  remark-rehype@10.1.0:
+  remark-rehype@11.1.1:
     dependencies:
-      '@types/hast': 2.3.10
-      '@types/mdast': 3.0.15
-      mdast-util-to-hast: 12.3.0
-      unified: 10.1.2
+      '@types/hast': 3.0.4
+      '@types/mdast': 4.0.4
+      mdast-util-to-hast: 13.2.0
+      unified: 11.0.5
+      vfile: 6.0.3
+
+  remark-stringify@11.0.0:
+    dependencies:
+      '@types/mdast': 4.0.4
+      mdast-util-to-markdown: 2.1.2
+      unified: 11.0.5
 
   remove-trailing-separator@1.1.0: {}
 
@@ -17924,9 +18009,7 @@ snapshots:
       mkdirp: 0.5.6
       rimraf: 2.7.1
 
-  scheduler@0.23.2:
-    dependencies:
-      loose-envify: 1.4.0
+  scheduler@0.25.0: {}
 
   secure-json-parse@2.7.0: {}
 
@@ -18261,6 +18344,11 @@ snapshots:
     dependencies:
       safe-buffer: 5.2.1
 
+  stringify-entities@4.0.4:
+    dependencies:
+      character-entities-html4: 2.1.0
+      character-entities-legacy: 3.0.0
+
   stringify-object@3.3.0:
     dependencies:
       get-own-enumerable-property-symbols: 3.0.2
@@ -18319,11 +18407,11 @@ snapshots:
 
   stubborn-fs@1.2.5: {}
 
-  style-to-object@0.4.4:
+  style-to-object@1.0.8:
     dependencies:
-      inline-style-parser: 0.1.1
+      inline-style-parser: 0.2.4
 
-  styled-components@6.1.13(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+  styled-components@6.1.13(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
     dependencies:
       '@emotion/is-prop-valid': 1.2.2
       '@emotion/unitless': 0.8.1
@@ -18331,8 +18419,8 @@ snapshots:
       css-to-react-native: 3.2.0
       csstype: 3.1.3
       postcss: 8.4.38
-      react: 18.3.1
-      react-dom: 18.3.1(react@18.3.1)
+      react: 19.0.0
+      react-dom: 19.0.0(react@19.0.0)
       shallowequal: 1.1.0
       stylis: 4.3.2
       tslib: 2.6.2
@@ -18377,14 +18465,14 @@ snapshots:
 
   supports-preserve-symlinks-flag@1.0.0: {}
 
-  svelte-check@3.8.6(@babel/core@7.25.9)(postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)))(postcss@8.4.47)(svelte@5.1.4):
+  svelte-check@3.8.6(@babel/core@7.26.0)(postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)))(postcss@8.4.47)(svelte@5.1.4):
     dependencies:
       '@jridgewell/trace-mapping': 0.3.25
       chokidar: 3.6.0
       picocolors: 1.1.1
       sade: 1.8.1
       svelte: 5.1.4
-      svelte-preprocess: 5.1.4(@babel/core@7.25.9)(postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)))(postcss@8.4.47)(svelte@5.1.4)(typescript@5.6.3)
+      svelte-preprocess: 5.1.4(@babel/core@7.26.0)(postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)))(postcss@8.4.47)(svelte@5.1.4)(typescript@5.6.3)
       typescript: 5.6.3
     transitivePeerDependencies:
       - '@babel/core'
@@ -18407,7 +18495,7 @@ snapshots:
     optionalDependencies:
       svelte: 5.1.4
 
-  svelte-preprocess@5.1.4(@babel/core@7.25.9)(postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)))(postcss@8.4.47)(svelte@5.1.4)(typescript@5.6.3):
+  svelte-preprocess@5.1.4(@babel/core@7.26.0)(postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)))(postcss@8.4.47)(svelte@5.1.4)(typescript@5.6.3):
     dependencies:
       '@types/pug': 2.0.10
       detect-indent: 6.1.0
@@ -18416,7 +18504,7 @@ snapshots:
       strip-indent: 3.0.0
       svelte: 5.1.4
     optionalDependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       postcss: 8.4.47
       postcss-load-config: 3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3))
       typescript: 5.6.3
@@ -18586,6 +18674,8 @@ snapshots:
 
   tiny-invariant@1.3.3: {}
 
+  tiny-warning@1.0.3: {}
+
   tinybench@2.9.0: {}
 
   tinyexec@0.3.1: {}
@@ -18886,15 +18976,15 @@ snapshots:
 
   unicorn-magic@0.1.0: {}
 
-  unified@10.1.2:
+  unified@11.0.5:
     dependencies:
-      '@types/unist': 2.0.11
+      '@types/unist': 3.0.3
       bail: 2.0.2
+      devlop: 1.1.0
       extend: 3.0.2
-      is-buffer: 2.0.5
       is-plain-obj: 4.1.0
       trough: 2.2.0
-      vfile: 5.3.7
+      vfile: 6.0.3
 
   unique-string@2.0.0:
     dependencies:
@@ -18904,34 +18994,28 @@ snapshots:
     dependencies:
       crypto-random-string: 4.0.0
 
-  unist-util-generated@2.0.1: {}
-
-  unist-util-is@5.2.1:
+  unist-util-is@6.0.0:
     dependencies:
-      '@types/unist': 2.0.11
-
-  unist-util-position@4.0.4:
-    dependencies:
-      '@types/unist': 2.0.11
+      '@types/unist': 3.0.3
 
-  unist-util-stringify-position@3.0.3:
+  unist-util-position@5.0.0:
     dependencies:
-      '@types/unist': 2.0.11
+      '@types/unist': 3.0.3
 
   unist-util-stringify-position@4.0.0:
     dependencies:
       '@types/unist': 3.0.3
 
-  unist-util-visit-parents@5.1.3:
+  unist-util-visit-parents@6.0.1:
     dependencies:
-      '@types/unist': 2.0.11
-      unist-util-is: 5.2.1
+      '@types/unist': 3.0.3
+      unist-util-is: 6.0.0
 
-  unist-util-visit@4.1.2:
+  unist-util-visit@5.0.0:
     dependencies:
-      '@types/unist': 2.0.11
-      unist-util-is: 5.2.1
-      unist-util-visit-parents: 5.1.3
+      '@types/unist': 3.0.3
+      unist-util-is: 6.0.0
+      unist-util-visit-parents: 6.0.1
 
   universal-user-agent@6.0.1: {}
 
@@ -19003,24 +19087,28 @@ snapshots:
 
   urlpattern-polyfill@8.0.2: {}
 
-  use-callback-ref@1.3.2(@types/react@18.3.12)(react@18.3.1):
+  use-callback-ref@1.3.2(@types/react@19.0.1)(react@19.0.0):
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
       tslib: 2.8.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  use-sidecar@1.1.2(@types/react@18.3.12)(react@18.3.1):
+  use-sidecar@1.1.2(@types/react@19.0.1)(react@19.0.0):
     dependencies:
       detect-node-es: 1.1.0
-      react: 18.3.1
+      react: 19.0.0
       tslib: 2.8.0
     optionalDependencies:
-      '@types/react': 18.3.12
+      '@types/react': 19.0.1
 
-  use-sync-external-store@1.2.2(react@18.3.1):
+  use-sync-external-store@1.2.2(react@19.0.0):
     dependencies:
-      react: 18.3.1
+      react: 19.0.0
+
+  use-sync-external-store@1.4.0(react@19.0.0):
+    dependencies:
+      react: 19.0.0
 
   util-deprecate@1.0.2: {}
 
@@ -19028,13 +19116,6 @@ snapshots:
 
   uuid@9.0.1: {}
 
-  uvu@0.5.6:
-    dependencies:
-      dequal: 2.0.3
-      diff: 5.2.0
-      kleur: 4.1.5
-      sade: 1.8.1
-
   v8-compile-cache-lib@3.0.1: {}
 
   validate-npm-package-license@3.0.4:
@@ -19050,17 +19131,15 @@ snapshots:
 
   vary@1.1.2: {}
 
-  vfile-message@3.1.4:
+  vfile-message@4.0.2:
     dependencies:
-      '@types/unist': 2.0.11
-      unist-util-stringify-position: 3.0.3
+      '@types/unist': 3.0.3
+      unist-util-stringify-position: 4.0.0
 
-  vfile@5.3.7:
+  vfile@6.0.3:
     dependencies:
-      '@types/unist': 2.0.11
-      is-buffer: 2.0.5
-      unist-util-stringify-position: 3.0.3
-      vfile-message: 3.1.4
+      '@types/unist': 3.0.3
+      vfile-message: 4.0.2
 
   vite-node@2.1.3(@types/node@20.17.0)(terser@5.36.0):
     dependencies:
@@ -19081,19 +19160,19 @@ snapshots:
 
   vite-plugin-prismjs@0.0.11(prismjs@1.29.0):
     dependencies:
-      '@babel/core': 7.25.9
+      '@babel/core': 7.26.0
       babel-plugin-prismjs: 2.1.0(prismjs@1.29.0)
     transitivePeerDependencies:
       - prismjs
       - supports-color
 
-  vite-plugin-pwa@0.20.5(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))(workbox-build@7.1.1)(workbox-window@7.1.0):
+  vite-plugin-pwa@0.20.5(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.1.0):
     dependencies:
       debug: 4.3.7(supports-color@9.4.0)
       pretty-bytes: 6.1.1
       tinyglobby: 0.2.9
       vite: 5.4.10(@types/node@20.17.0)(terser@5.36.0)
-      workbox-build: 7.1.1
+      workbox-build: 7.1.1(@types/babel__core@7.20.5)
       workbox-window: 7.1.0
     transitivePeerDependencies:
       - supports-color
@@ -19289,13 +19368,13 @@ snapshots:
     dependencies:
       workbox-core: 7.1.0
 
-  workbox-build@7.1.1:
+  workbox-build@7.1.1(@types/babel__core@7.20.5):
     dependencies:
       '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1)
-      '@babel/core': 7.25.9
-      '@babel/preset-env': 7.25.9(@babel/core@7.25.9)
+      '@babel/core': 7.26.0
+      '@babel/preset-env': 7.25.9(@babel/core@7.26.0)
       '@babel/runtime': 7.25.9
-      '@rollup/plugin-babel': 5.3.1(@babel/core@7.25.9)(rollup@2.79.2)
+      '@rollup/plugin-babel': 5.3.1(@babel/core@7.26.0)(@types/babel__core@7.20.5)(rollup@2.79.2)
       '@rollup/plugin-node-resolve': 15.3.0(rollup@2.79.2)
       '@rollup/plugin-replace': 2.4.2(rollup@2.79.2)
       '@rollup/plugin-terser': 0.4.4(rollup@2.79.2)
@@ -19500,13 +19579,17 @@ snapshots:
       compress-commons: 6.0.2
       readable-stream: 4.5.2
 
+  zod-validation-error@3.4.0(zod@3.23.8):
+    dependencies:
+      zod: 3.23.8
+
   zod@3.23.8: {}
 
-  zustand@4.5.5(@types/react@18.3.12)(react@18.3.1):
+  zustand@4.5.5(@types/react@19.0.1)(react@19.0.0):
     dependencies:
-      use-sync-external-store: 1.2.2(react@18.3.1)
+      use-sync-external-store: 1.2.2(react@19.0.0)
     optionalDependencies:
-      '@types/react': 18.3.12
-      react: 18.3.1
+      '@types/react': 19.0.1
+      react: 19.0.0
 
   zwitch@2.0.4: {}
diff --git a/browser/react/package.json b/browser/react/package.json
index 05f7d134d..a9d2ce31c 100644
--- a/browser/react/package.json
+++ b/browser/react/package.json
@@ -12,18 +12,21 @@
     "url": "https://github.com/atomicdata-dev/atomic-server/issues"
   },
   "dependencies": {
-    "@tomic/lib": "workspace:*"
+    "@tomic/lib": "workspace:*",
+    "react": "^19.0.0",
+    "react-dom": "^19.0.0"
   },
   "devDependencies": {
     "@arethetypeswrong/cli": "^0.17.0",
-    "@types/react": "^18.3.12",
-    "@types/react-dom": "^18.3.1",
+    "@types/react": "^19.0.0",
+    "@types/react-dom": "^19.0.0",
     "@types/react-router-dom": "^5.3.3",
     "tsup": "^8.3.5",
     "typescript": "^5.6.3"
   },
   "peerDependencies": {
-    "react": ">18.3.0"
+    "react": ">18.3.0",
+    "react-dom": ">18.3.0"
   },
   "files": [
     "dist",
diff --git a/browser/react/src/hooks.ts b/browser/react/src/hooks.ts
index 28e74538a..6bb8de142 100644
--- a/browser/react/src/hooks.ts
+++ b/browser/react/src/hooks.ts
@@ -3,9 +3,9 @@ import {
   useEffect,
   useCallback,
   useMemo,
-  useRef,
   useContext,
   createContext,
+  useRef,
 } from 'react';
 import {
   Property,
@@ -30,7 +30,6 @@ import {
   core,
   server,
 } from '@tomic/lib';
-import { useDebouncedCallback } from './index.js';
 
 /**
  * Hook for getting a Resource in a React component. Will try to fetch the
@@ -55,6 +54,12 @@ export function useResource<C extends OptionalClass = never>(
     });
   }, [store, subject]);
 
+  useEffect(() => {
+    return resource.on(ResourceEvents.LocalChange, () => {
+      setResource(proxyResource(resource.__internalObject));
+    });
+  }, [store]);
+
   return resource;
 }
 
@@ -211,6 +216,7 @@ export function useValue(
   propertyURL: string,
   opts: useValueOptions = {},
 ): [JSONValue | undefined, SetValue] {
+  const timeoutId = useRef<ReturnType<typeof setTimeout>>(undefined);
   const {
     commit = false,
     validate = true,
@@ -223,17 +229,23 @@ export function useValue(
 
   const store = useStore();
 
-  const [saveResource] = useDebouncedCallback(
-    () => {
-      if (!commit) {
-        return;
-      }
+  const saveResource = useCallback(() => {
+    if (!commit) {
+      return;
+    }
 
-      resource.save().catch(e => store.notifyError(e));
-    },
-    commitDebounce,
-    [resource, store],
-  );
+    if (timeoutId.current !== undefined) {
+      clearTimeout(timeoutId.current);
+    }
+
+    timeoutId.current = setTimeout(async () => {
+      try {
+        await resource.save();
+      } catch (e) {
+        store.notifyError(e);
+      }
+    }, commitDebounce);
+  }, [resource, store, commitDebounce, commit]);
 
   /**
    * Validates the value. If it fails, it calls the function in the second
@@ -406,11 +418,11 @@ export function useArray(
   opts?: useValueOptions,
 ): [string[], SetValue<JSONArray>, (vals: string[]) => void] {
   const [value, set] = useValue(resource, propertyURL, opts);
-  const stableEmptyResourceArray = useRef<JSONArray>([]);
+  const [stableEmptyResourceArray] = useState<JSONArray>([]);
 
   const values = useMemo(() => {
     if (value === undefined) {
-      return stableEmptyResourceArray.current;
+      return stableEmptyResourceArray;
     }
 
     try {
@@ -422,7 +434,7 @@ export function useArray(
 
       // If .toArray() errors, return an empty array. Useful in forms when datatypes haves changed!
       // https://github.com/atomicdata-dev/atomic-data-browser/issues/85
-      return stableEmptyResourceArray.current;
+      return stableEmptyResourceArray;
     }
   }, [value, resource, propertyURL]);
 
@@ -515,26 +527,16 @@ export function useStore(): Store {
 }
 
 /**
- * Checks if the Agent has the appropriate rights to edit this resource. If you
- * don't explicitly pass an Agent URL, it will select the current Agent set by the store.
+ * Checks if the current agent has the appropriate rights to edit this resource.
  */
-export function useCanWrite(
-  resource: Resource,
-  agent?: string,
-): [canWrite: boolean, message: string | undefined] {
+export function useCanWrite(resource: Resource): boolean {
   const store = useStore();
   const [canWrite, setCanWrite] = useState<boolean>(false);
-  const [msg, setMsg] = useState<string | undefined>(undefined);
-  const agentStore = store.getAgent();
+  const agent = store.getAgent();
 
   // If the subject changes, make sure to change the resource!
   useEffect(() => {
-    if (agent === undefined) {
-      agent = agentStore?.subject;
-    }
-
-    if (agent === undefined) {
-      setMsg('No Agent set');
+    if (!agent) {
       setCanWrite(false);
 
       return;
@@ -542,31 +544,16 @@ export function useCanWrite(
 
     if (resource.new) {
       setCanWrite(true);
-      setMsg(undefined);
 
       return;
     }
 
-    setMsg('Checking write rights...');
-
-    async function tryCanWrite() {
-      const [canWriteAsync, canWriteMsg] = await resource.canWrite(agent);
-      setCanWrite(canWriteAsync);
-
-      if (canWriteAsync) {
-        setMsg(undefined);
-      } else {
-        setMsg(
-          ("You don't have write rights in this resource or its parents: " +
-            canWriteMsg) as string,
-        );
-      }
-    }
-
-    tryCanWrite();
-  }, [resource, agent, agentStore?.subject]);
+    resource.canWrite(agent.subject).then(([result]) => {
+      setCanWrite(result);
+    });
+  }, [resource, agent?.subject]);
 
-  return [canWrite, msg];
+  return canWrite;
 }
 
 /**
diff --git a/browser/react/src/index.ts b/browser/react/src/index.ts
index 5b2a6069f..68a03a3b7 100644
--- a/browser/react/src/index.ts
+++ b/browser/react/src/index.ts
@@ -26,7 +26,7 @@ export * from './hooks.js';
 export * from './useServerURL.js';
 export * from './useCurrentAgent.js';
 export * from './useChildren.js';
-export * from './useDebounce.js';
+export { useDebouncedSave } from './useDebounce.js';
 export * from './useMarkdown.js';
 export * from './useServerSearch.js';
 export * from './useCollection.js';
diff --git a/browser/react/src/useDebounce.ts b/browser/react/src/useDebounce.ts
index 1a61b3ebf..1e6dda21d 100644
--- a/browser/react/src/useDebounce.ts
+++ b/browser/react/src/useDebounce.ts
@@ -1,11 +1,6 @@
+import type { Resource } from '@tomic/lib';
 import { useCallback, useEffect, useRef, useState } from 'react';
 
-type Callback =
-  // eslint-disable-next-line @typescript-eslint/no-explicit-any
-  | ((...args: any[]) => void)
-  // eslint-disable-next-line @typescript-eslint/no-explicit-any
-  | ((...args: any[]) => Promise<void>);
-
 // T is a generic type for value parameter, our case this will be string
 export function useDebounce<T>(value: T, delay: number): T {
   // State and setters for debounced value
@@ -31,30 +26,34 @@ export function useDebounce<T>(value: T, delay: number): T {
   return debouncedValue;
 }
 
-export function useDebouncedCallback<F extends Callback>(
-  func: F,
-  time: number,
-  deps: unknown[],
-): [debouncedFunction: (...args: Parameters<F>) => void, isWaiting: boolean] {
-  const timeoutId = useRef<ReturnType<typeof setTimeout>>();
-  const [isWaiting, setIsWaiting] = useState(false);
-
-  const memoizedFunction = useCallback(
-    (...args: Parameters<F>) => {
-      if (timeoutId.current) {
-        clearTimeout(timeoutId.current);
+export function useDebouncedSave(
+  resource: Resource,
+  timeout: number,
+  onError?: (error: Error) => void,
+): [save: () => void, savePending: boolean] {
+  const timeoutId = useRef<ReturnType<typeof setTimeout>>(undefined);
+  const [savePending, setSavePending] = useState(false);
+
+  const save = useCallback(() => {
+    if (timeoutId.current) {
+      clearTimeout(timeoutId.current);
+    }
+
+    timeoutId.current = setTimeout(async () => {
+      try {
+        await resource.save();
+        setSavePending(false);
+      } catch (e) {
+        if (onError) {
+          onError(e);
+        } else {
+          throw e;
+        }
       }
+    }, timeout);
 
-      const id = setTimeout(async () => {
-        await func(...args);
-        timeoutId.current = undefined;
-        setIsWaiting(false);
-      }, time);
-      setIsWaiting(true);
-      timeoutId.current = id;
-    },
-    [...deps, time, timeoutId],
-  );
+    setSavePending(true);
+  }, [resource, timeout, onError]);
 
-  return [memoizedFunction, isWaiting];
+  return [save, savePending];
 }
diff --git a/browser/react/src/useServerSearch.tsx b/browser/react/src/useServerSearch.tsx
index 8de1156a2..4f47927c4 100644
--- a/browser/react/src/useServerSearch.tsx
+++ b/browser/react/src/useServerSearch.tsx
@@ -5,13 +5,8 @@ import {
   urls,
 } from '@tomic/lib';
 import { useEffect, useMemo, useState } from 'react';
-import {
-  useArray,
-  useDebounce,
-  useResource,
-  useServerURL,
-  useStore,
-} from './index.js';
+import { useArray, useResource, useServerURL, useStore } from './index.js';
+import { useDebounce } from './useDebounce.js';
 
 interface SearchResults {
   /** Subject URLs for resources that match the query */
diff --git a/docs/src/react/useCanWrite.md b/docs/src/react/useCanWrite.md
index 0a0c5e24e..dd69deaa0 100644
--- a/docs/src/react/useCanWrite.md
+++ b/docs/src/react/useCanWrite.md
@@ -12,7 +12,7 @@ import { useCanWrite, useResource, useString } from '@tomic/react';
 const ResourceDescription = () => {
   const resource = useResource('https://my-server.com/my-resource');
   const [description, setDescription] = useString(resource, core.properties.description);
-  const [canWrite] = useCanWrite(resource);
+  const canWrite = useCanWrite(resource);
 
   if (canWrite) {
     return (


Test patch:
diff --git a/browser/e2e/tests/documents.spec.ts b/browser/e2e/tests/documents.spec.ts
index 3f7cb6642..667a62e70 100644
--- a/browser/e2e/tests/documents.spec.ts
+++ b/browser/e2e/tests/documents.spec.ts
@@ -26,11 +26,9 @@ test.describe('documents', async () => {
     const title = `Document ${timestamp()}`;
     await editTitle(title, page);
 
-    await page.press(editableTitle, 'Enter');
-
     const teststring = `My test: ${timestamp()}`;
 
-    await page.fill('textarea', teststring);
+    await page.locator('textarea').fill(teststring);
 
     await expect(page.locator(`text=${teststring}`)).toBeVisible();
 
diff --git a/browser/e2e/tests/e2e.spec.ts b/browser/e2e/tests/e2e.spec.ts
index bf6d352bc..25c735a82 100644
--- a/browser/e2e/tests/e2e.spec.ts
+++ b/browser/e2e/tests/e2e.spec.ts
@@ -195,7 +195,7 @@ test.describe('data-browser', async () => {
     await page3.click('button:has-text("Accept")');
     await waiter;
     await page3.reload();
-    await expect(page3.locator(`text=${driveTitle}`).first()).toBeVisible();
+    await expect(page3.getByText(driveTitle).first()).toBeVisible();
   });
 
   test('chatroom', async ({ page, browser }) => {
diff --git a/browser/e2e/tests/global.setup.ts b/browser/e2e/tests/global.setup.ts
index 4a5a52377..649ed3ba4 100644
--- a/browser/e2e/tests/global.setup.ts
+++ b/browser/e2e/tests/global.setup.ts
@@ -15,7 +15,7 @@ setup('delete previous test data', async ({ page }) => {
 
   await before({ page });
   await signIn(page);
-  await page.goto(`${FRONTEND_URL}/prunetests`);
+  await page.goto(`${FRONTEND_URL}/app/prunetests`);
   await expect(page.getByText('Prune Test Data')).toBeVisible();
   await page.getByRole('button', { name: 'Prune' }).click();
 
diff --git a/browser/e2e/tests/tables.spec.ts b/browser/e2e/tests/tables.spec.ts
index ef0a00e3c..8242edc95 100644
--- a/browser/e2e/tests/tables.spec.ts
+++ b/browser/e2e/tests/tables.spec.ts
@@ -6,6 +6,15 @@ import {
   waitForCommit,
   before,
 } from './test-utils';
+
+type Row = {
+  name: string;
+  date: string;
+  number: string;
+  checkbox: boolean;
+  select: string;
+};
+
 test.describe('tables', async () => {
   test.beforeEach(before);
 
@@ -39,7 +48,7 @@ test.describe('tables', async () => {
       await expect(page.getByPlaceholder('filter tags')).not.toBeVisible();
     };
 
-    const fillRow = async (currentRowNumber: number, row) => {
+    const fillRow = async (currentRowNumber: number, row: Row) => {
       const { name, date, number, checkbox, select } = row;
       const rowIndex = currentRowNumber + 1;
       await page.keyboard.press('Enter');
diff --git a/browser/e2e/tests/test-utils.ts b/browser/e2e/tests/test-utils.ts
index f9046e440..86ba75ac1 100644
--- a/browser/e2e/tests/test-utils.ts
+++ b/browser/e2e/tests/test-utils.ts
@@ -296,20 +296,17 @@ export async function changeDrive(subject: string, page: Page) {
 }
 
 export async function editTitle(title: string, page: Page) {
-  await page.locator(`${editableTitle} > h1`);
+  await expect(page.locator(editableTitle)).toHaveRole('heading');
   await page.locator(editableTitle).click();
-  await page.locator(`${editableTitle} > input`);
+  await expect(page.locator(editableTitle)).toHaveRole('textbox');
   await page.fill(editableTitle, title);
-  await page.keyboard.press('Escape');
+  await page.keyboard.press('Enter');
   // Make sure the commit is processed
   // await page.waitForTimeout(300);
 }
 
 export async function clickSidebarItem(text: string, page: Page) {
-  await page
-    .getByTestId('sidebar')
-    .getByRole('button', { name: text })
-    .click({ force: true });
+  await page.getByTestId('sidebar').getByRole('link', { name: text }).click();
 }
 
 /** Click an item from the main, visible context menu */
diff --git a/browser/e2e/tsconfig.json b/browser/e2e/tsconfig.json
index bd7d5119d..67daec5bf 100644
--- a/browser/e2e/tsconfig.json
+++ b/browser/e2e/tsconfig.json
@@ -4,25 +4,9 @@
     "composite": true,
     // We overwrite this so we don't have to use `.js` extensions in imports
     "moduleResolution": "node",
-    "lib": [
-      "ES6",
-      "ES7",
-      "ESNext",
-      "DOM"
-    ],
+    "lib": ["ES6", "ES7", "ESNext", "DOM"],
     "outDir": "./dist",
-    "strictNullChecks": true,
+    "strictNullChecks": true
   },
-  "include": [
-    "./tests",
-    "playwright.config.ts"
-  ],
-  "references": [
-    {
-      "path": "../lib"
-    },
-    {
-      "path": "../react"
-    }
-  ]
+  "include": ["./tests", "playwright.config.ts"]
 }