diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp
index ca10e7a13d7..b159b070d6c 100644
--- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp
+++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp
@@ -193,56 +193,6 @@ ReanimatedModuleProxy::~ReanimatedModuleProxy() {
 #endif // RCT_NEW_ARCH_ENABLED
 }
 
-void ReanimatedModuleProxy::scheduleOnUI(
-    jsi::Runtime &rt,
-    const jsi::Value &worklet) {
-  auto shareableWorklet = extractShareableOrThrow<ShareableWorklet>(
-      rt, worklet, "[Reanimated] Only worklets can be scheduled to run on UI.");
-  workletsModuleProxy_->getUIScheduler()->scheduleOnUI(COPY_CAPTURE_WITH_THIS {
-#if JS_RUNTIME_HERMES
-    // JSI's scope defined here allows for JSI-objects to be cleared up
-    // after each runtime loop. Within these loops we typically create some
-    // temporary JSI objects and hence it allows for such objects to be
-    // garbage collected much sooner. Apparently the scope API is only
-    // supported on Hermes at the moment.
-    const auto scope = jsi::Scope(
-        workletsModuleProxy_->getUIWorkletRuntime()->getJSIRuntime());
-#endif
-    workletsModuleProxy_->getUIWorkletRuntime()->runGuarded(shareableWorklet);
-  });
-}
-
-jsi::Value ReanimatedModuleProxy::executeOnUIRuntimeSync(
-    jsi::Runtime &rt,
-    const jsi::Value &worklet) {
-  return workletsModuleProxy_->getUIWorkletRuntime()->executeSync(rt, worklet);
-}
-
-jsi::Value ReanimatedModuleProxy::createWorkletRuntime(
-    jsi::Runtime &rt,
-    const jsi::Value &name,
-    const jsi::Value &initializer) {
-  auto workletRuntime = std::make_shared<WorkletRuntime>(
-      rt,
-      workletsModuleProxy_->getJSQueue(),
-      workletsModuleProxy_->getJSScheduler(),
-      name.asString(rt).utf8(rt),
-      false /* supportsLocking */,
-      valueUnpackerCode_);
-  auto initializerShareable = extractShareableOrThrow<ShareableWorklet>(
-      rt, initializer, "[Reanimated] Initializer must be a worklet.");
-  workletRuntime->runGuarded(initializerShareable);
-  return jsi::Object::createFromHostObject(rt, workletRuntime);
-}
-
-jsi::Value ReanimatedModuleProxy::scheduleOnRuntime(
-    jsi::Runtime &rt,
-    const jsi::Value &workletRuntimeValue,
-    const jsi::Value &shareableWorkletValue) {
-  reanimated::scheduleOnRuntime(rt, workletRuntimeValue, shareableWorkletValue);
-  return jsi::Value::undefined();
-}
-
 jsi::Value ReanimatedModuleProxy::registerEventHandler(
     jsi::Runtime &rt,
     const jsi::Value &worklet,
diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h
index 65b3a5f3c65..dd3b6661999 100644
--- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h
+++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h
@@ -42,19 +42,6 @@ class ReanimatedModuleProxy : public ReanimatedModuleProxySpec {
 
   ~ReanimatedModuleProxy();
 
-  void scheduleOnUI(jsi::Runtime &rt, const jsi::Value &worklet) override;
-  jsi::Value executeOnUIRuntimeSync(jsi::Runtime &rt, const jsi::Value &worklet)
-      override;
-
-  jsi::Value createWorkletRuntime(
-      jsi::Runtime &rt,
-      const jsi::Value &name,
-      const jsi::Value &initializer) override;
-  jsi::Value scheduleOnRuntime(
-      jsi::Runtime &rt,
-      const jsi::Value &workletRuntimeValue,
-      const jsi::Value &shareableWorkletValue) override;
-
   jsi::Value registerEventHandler(
       jsi::Runtime &rt,
       const jsi::Value &worklet,
diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp
index d797483bcf1..47ad998e6e4 100644
--- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp
+++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp
@@ -7,45 +7,6 @@
 
 namespace reanimated {
 
-// scheduler
-
-static jsi::Value REANIMATED_SPEC_PREFIX(scheduleOnUI)(
-    jsi::Runtime &rt,
-    TurboModule &turboModule,
-    const jsi::Value *args,
-    size_t) {
-  static_cast<ReanimatedModuleProxySpec *>(&turboModule)
-      ->scheduleOnUI(rt, std::move(args[0]));
-  return jsi::Value::undefined();
-}
-
-static jsi::Value REANIMATED_SPEC_PREFIX(executeOnUIRuntimeSync)(
-    jsi::Runtime &rt,
-    TurboModule &turboModule,
-    const jsi::Value *args,
-    size_t) {
-  return static_cast<ReanimatedModuleProxySpec *>(&turboModule)
-      ->executeOnUIRuntimeSync(rt, std::move(args[0]));
-}
-
-static jsi::Value REANIMATED_SPEC_PREFIX(createWorkletRuntime)(
-    jsi::Runtime &rt,
-    TurboModule &turboModule,
-    const jsi::Value *args,
-    size_t) {
-  return static_cast<ReanimatedModuleProxySpec *>(&turboModule)
-      ->createWorkletRuntime(rt, std::move(args[0]), std::move(args[1]));
-}
-
-static jsi::Value REANIMATED_SPEC_PREFIX(scheduleOnRuntime)(
-    jsi::Runtime &rt,
-    TurboModule &turboModule,
-    const jsi::Value *args,
-    size_t) {
-  return static_cast<ReanimatedModuleProxySpec *>(&turboModule)
-      ->scheduleOnRuntime(rt, std::move(args[0]), std::move(args[1]));
-}
-
 static jsi::Value REANIMATED_SPEC_PREFIX(registerEventHandler)(
     jsi::Runtime &rt,
     TurboModule &turboModule,
@@ -163,15 +124,6 @@ static jsi::Value REANIMATED_SPEC_PREFIX(setShouldAnimateExiting)(
 ReanimatedModuleProxySpec::ReanimatedModuleProxySpec(
     const std::shared_ptr<CallInvoker> &jsInvoker)
     : TurboModule("NativeReanimated", jsInvoker) {
-  methodMap_["scheduleOnUI"] =
-      MethodMetadata{1, REANIMATED_SPEC_PREFIX(scheduleOnUI)};
-  methodMap_["executeOnUIRuntimeSync"] =
-      MethodMetadata{1, REANIMATED_SPEC_PREFIX(executeOnUIRuntimeSync)};
-  methodMap_["createWorkletRuntime"] =
-      MethodMetadata{2, REANIMATED_SPEC_PREFIX(createWorkletRuntime)};
-  methodMap_["scheduleOnRuntime"] =
-      MethodMetadata{2, REANIMATED_SPEC_PREFIX(scheduleOnRuntime)};
-
   methodMap_["registerEventHandler"] =
       MethodMetadata{3, REANIMATED_SPEC_PREFIX(registerEventHandler)};
   methodMap_["unregisterEventHandler"] =
diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h
index 3f82813abff..3321e93d889 100644
--- a/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h
+++ b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h
@@ -18,22 +18,6 @@ class JSI_EXPORT ReanimatedModuleProxySpec : public TurboModule {
       const std::shared_ptr<CallInvoker> &jsInvoker);
 
  public:
-  // Scheduling
-  virtual void scheduleOnUI(jsi::Runtime &rt, const jsi::Value &worklet) = 0;
-  virtual jsi::Value executeOnUIRuntimeSync(
-      jsi::Runtime &rt,
-      const jsi::Value &worklet) = 0;
-
-  // Worklet runtime
-  virtual jsi::Value createWorkletRuntime(
-      jsi::Runtime &rt,
-      const jsi::Value &name,
-      const jsi::Value &initializer) = 0;
-  virtual jsi::Value scheduleOnRuntime(
-      jsi::Runtime &rt,
-      const jsi::Value &workletRuntimeValue,
-      const jsi::Value &shareableWorkletValue) = 0;
-
   // events
   virtual jsi::Value registerEventHandler(
       jsi::Runtime &rt,
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp
index ef488e28c4b..f49d86b9ec5 100644
--- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp
+++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp
@@ -14,6 +14,18 @@
 
 #include <jsi/jsi.h>
 
+// Standard `__cplusplus` macro reference:
+// https://en.cppreference.com/w/cpp/preprocessor/replace#Predefined_macros
+#if REACT_NATIVE_MINOR_VERSION >= 75 || __cplusplus >= 202002L
+// Implicit copy capture of `this` is deprecated in NDK27, which uses C++20.
+#define COPY_CAPTURE_WITH_THIS [ =, this ] // NOLINT (whitespace/braces)
+#else
+// React Native 0.75 is the last one which allows NDK23. NDK23 uses C++17 and
+// explicitly disallows C++20 features, including the syntax above. Therefore we
+// fallback to the deprecated syntax here.
+#define COPY_CAPTURE_WITH_THIS [=] // NOLINT (whitespace/braces)
+#endif // REACT_NATIVE_MINOR_VERSION >= 75 || __cplusplus >= 202002L
+
 using namespace facebook;
 
 namespace worklets {
@@ -53,4 +65,53 @@ jsi::Value WorkletsModuleProxy::makeShareableClone(
       rt, value, shouldRetainRemote, nativeStateSource);
 }
 
+void WorkletsModuleProxy::scheduleOnUI(
+    jsi::Runtime &rt,
+    const jsi::Value &worklet) {
+  auto shareableWorklet = extractShareableOrThrow<ShareableWorklet>(
+      rt, worklet, "[Worklets] Only worklets can be scheduled to run on UI.");
+  uiScheduler_->scheduleOnUI(COPY_CAPTURE_WITH_THIS {
+#if JS_RUNTIME_HERMES
+    // JSI's scope defined here allows for JSI-objects to be cleared up
+    // after each runtime loop. Within these loops we typically create some
+    // temporary JSI objects and hence it allows for such objects to be
+    // garbage collected much sooner. Apparently the scope API is only
+    // supported on Hermes at the moment.
+    const auto scope = jsi::Scope(uiWorkletRuntime_->getJSIRuntime());
+#endif
+    uiWorkletRuntime_->runGuarded(shareableWorklet);
+  });
+}
+
+jsi::Value WorkletsModuleProxy::executeOnUIRuntimeSync(
+    jsi::Runtime &rt,
+    const jsi::Value &worklet) {
+  return uiWorkletRuntime_->executeSync(rt, worklet);
+}
+
+jsi::Value WorkletsModuleProxy::createWorkletRuntime(
+    jsi::Runtime &rt,
+    const jsi::Value &name,
+    const jsi::Value &initializer) {
+  auto workletRuntime = std::make_shared<WorkletRuntime>(
+      rt,
+      jsQueue_,
+      jsScheduler_,
+      name.asString(rt).utf8(rt),
+      false /* supportsLocking */,
+      valueUnpackerCode_);
+  auto initializerShareable = extractShareableOrThrow<ShareableWorklet>(
+      rt, initializer, "[Reanimated] Initializer must be a worklet.");
+  workletRuntime->runGuarded(initializerShareable);
+  return jsi::Object::createFromHostObject(rt, workletRuntime);
+}
+
+jsi::Value WorkletsModuleProxy::scheduleOnRuntime(
+    jsi::Runtime &rt,
+    const jsi::Value &workletRuntimeValue,
+    const jsi::Value &shareableWorkletValue) {
+  worklets::scheduleOnRuntime(rt, workletRuntimeValue, shareableWorkletValue);
+  return jsi::Value::undefined();
+}
+
 } // namespace worklets
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h
index 90fc31b4cd4..b2f4203a954 100644
--- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h
+++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h
@@ -29,6 +29,21 @@ class WorkletsModuleProxy : public WorkletsModuleProxySpec {
       const jsi::Value &shouldRetainRemote,
       const jsi::Value &nativeStateSource) override;
 
+  void scheduleOnUI(jsi::Runtime &rt, const jsi::Value &worklet) override;
+
+  jsi::Value executeOnUIRuntimeSync(jsi::Runtime &rt, const jsi::Value &worklet)
+      override;
+
+  jsi::Value createWorkletRuntime(
+      jsi::Runtime &rt,
+      const jsi::Value &name,
+      const jsi::Value &initializer) override;
+
+  jsi::Value scheduleOnRuntime(
+      jsi::Runtime &rt,
+      const jsi::Value &workletRuntimeValue,
+      const jsi::Value &shareableWorkletValue) override;
+
   [[nodiscard]] inline std::string getValueUnpackerCode() const {
     return valueUnpackerCode_;
   }
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp
index 624c42ee224..973dcf333af 100644
--- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp
+++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp
@@ -17,11 +17,56 @@ static jsi::Value WORKLETS_SPEC_PREFIX(makeShareableClone)(
           rt, std::move(args[0]), std::move(args[1]), std::move(args[2]));
 }
 
+static jsi::Value WORKLETS_SPEC_PREFIX(scheduleOnUI)(
+    jsi::Runtime &rt,
+    TurboModule &turboModule,
+    const jsi::Value *args,
+    size_t) {
+  static_cast<WorkletsModuleProxySpec *>(&turboModule)
+      ->scheduleOnUI(rt, std::move(args[0]));
+  return jsi::Value::undefined();
+}
+
+static jsi::Value WORKLETS_SPEC_PREFIX(executeOnUIRuntimeSync)(
+    jsi::Runtime &rt,
+    TurboModule &turboModule,
+    const jsi::Value *args,
+    size_t) {
+  return static_cast<WorkletsModuleProxySpec *>(&turboModule)
+      ->executeOnUIRuntimeSync(rt, std::move(args[0]));
+}
+
+static jsi::Value WORKLETS_SPEC_PREFIX(createWorkletRuntime)(
+    jsi::Runtime &rt,
+    TurboModule &turboModule,
+    const jsi::Value *args,
+    size_t) {
+  return static_cast<WorkletsModuleProxySpec *>(&turboModule)
+      ->createWorkletRuntime(rt, std::move(args[0]), std::move(args[1]));
+}
+
+static jsi::Value WORKLETS_SPEC_PREFIX(scheduleOnRuntime)(
+    jsi::Runtime &rt,
+    TurboModule &turboModule,
+    const jsi::Value *args,
+    size_t) {
+  return static_cast<WorkletsModuleProxySpec *>(&turboModule)
+      ->scheduleOnRuntime(rt, std::move(args[0]), std::move(args[1]));
+}
+
 WorkletsModuleProxySpec::WorkletsModuleProxySpec(
     const std::shared_ptr<CallInvoker> jsInvoker)
     : TurboModule("NativeWorklets", jsInvoker) {
   methodMap_["makeShareableClone"] =
       MethodMetadata{2, WORKLETS_SPEC_PREFIX(makeShareableClone)};
+  methodMap_["scheduleOnUI"] =
+      MethodMetadata{1, WORKLETS_SPEC_PREFIX(scheduleOnUI)};
+  methodMap_["executeOnUIRuntimeSync"] =
+      MethodMetadata{1, WORKLETS_SPEC_PREFIX(executeOnUIRuntimeSync)};
+  methodMap_["createWorkletRuntime"] =
+      MethodMetadata{2, WORKLETS_SPEC_PREFIX(createWorkletRuntime)};
+  methodMap_["scheduleOnRuntime"] =
+      MethodMetadata{2, WORKLETS_SPEC_PREFIX(scheduleOnRuntime)};
 }
 
 } // namespace worklets
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h
index c79a86b908f..5d3573c969a 100644
--- a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h
+++ b/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h
@@ -15,11 +15,30 @@ class JSI_EXPORT WorkletsModuleProxySpec : public TurboModule {
       const std::shared_ptr<CallInvoker> jsInvoker);
 
  public:
+  // Shareables
   virtual jsi::Value makeShareableClone(
       jsi::Runtime &rt,
       const jsi::Value &value,
       const jsi::Value &shouldRetainRemote,
       const jsi::Value &nativeStateSource) = 0;
+
+  // Scheduling
+  virtual void scheduleOnUI(jsi::Runtime &rt, const jsi::Value &worklet) = 0;
+
+  virtual jsi::Value executeOnUIRuntimeSync(
+      jsi::Runtime &rt,
+      const jsi::Value &worklet) = 0;
+
+  // Worklet runtime
+  virtual jsi::Value createWorkletRuntime(
+      jsi::Runtime &rt,
+      const jsi::Value &name,
+      const jsi::Value &initializer) = 0;
+
+  virtual jsi::Value scheduleOnRuntime(
+      jsi::Runtime &rt,
+      const jsi::Value &workletRuntimeValue,
+      const jsi::Value &shareableWorkletValue) = 0;
 };
 
 } // namespace worklets
diff --git a/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts b/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts
index 3ff0ef98727..40fb1b7f33b 100644
--- a/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts
+++ b/packages/react-native-reanimated/src/ReanimatedModule/NativeReanimated.ts
@@ -10,7 +10,6 @@ import type {
 } from '../commonTypes';
 import { checkCppVersion } from '../platform-specific/checkCppVersion';
 import { jsVersion } from '../platform-specific/jsVersion';
-import type { WorkletRuntime } from '../runtimes';
 import { isFabric } from '../PlatformChecker';
 import type React from 'react';
 import { getShadowNodeWrapperFromRef } from '../fabricUtils';
@@ -65,28 +64,6 @@ See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooti
     this.#reanimatedModuleProxy = global.__reanimatedModuleProxy;
   }
 
-  scheduleOnUI<T>(shareable: ShareableRef<T>) {
-    return this.#reanimatedModuleProxy.scheduleOnUI(shareable);
-  }
-
-  executeOnUIRuntimeSync<T, R>(shareable: ShareableRef<T>): R {
-    return this.#reanimatedModuleProxy.executeOnUIRuntimeSync(shareable);
-  }
-
-  createWorkletRuntime(name: string, initializer: ShareableRef<() => void>) {
-    return this.#reanimatedModuleProxy.createWorkletRuntime(name, initializer);
-  }
-
-  scheduleOnRuntime<T>(
-    workletRuntime: WorkletRuntime,
-    shareableWorklet: ShareableRef<T>
-  ) {
-    return this.#reanimatedModuleProxy.scheduleOnRuntime(
-      workletRuntime,
-      shareableWorklet
-    );
-  }
-
   registerSensor(
     sensorType: number,
     interval: number,
diff --git a/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts b/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts
index e4fa3b8a008..8b071cb4d95 100644
--- a/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts
+++ b/packages/react-native-reanimated/src/ReanimatedModule/js-reanimated/JSReanimated.ts
@@ -15,8 +15,6 @@ import type {
   WorkletFunction,
 } from '../../commonTypes';
 import type { WebSensor } from './WebSensor';
-import { mockedRequestAnimationFrame } from '../../mockedRequestAnimationFrame';
-import type { WorkletRuntime } from '../../runtimes';
 import { logger } from '../../logger';
 import { ReanimatedError } from '../../errors';
 import { WorkletsModule } from '../../worklets';
@@ -25,14 +23,6 @@ export function createJSReanimatedModule(): IReanimatedModule {
   return new JSReanimated();
 }
 
-// In Node.js environments (like when static rendering with Expo Router)
-// requestAnimationFrame is unavailable, so we use our mock.
-// It also has to be mocked for Jest purposes (see `initializeUIRuntime`).
-const requestAnimationFrameImpl =
-  isJest() || !globalThis.requestAnimationFrame
-    ? mockedRequestAnimationFrame
-    : globalThis.requestAnimationFrame;
-
 class JSReanimated implements IReanimatedModule {
   /**
    * We keep the instance of `WorkletsModule` here to keep correct coupling of
@@ -43,26 +33,6 @@ class JSReanimated implements IReanimatedModule {
   sensors = new Map<number, WebSensor>();
   platform?: Platform = undefined;
 
-  scheduleOnUI<T>(worklet: ShareableRef<T>) {
-    // @ts-ignore web implementation has still not been updated after the rewrite, this will be addressed once the web implementation updates are ready
-    requestAnimationFrameImpl(worklet);
-  }
-
-  createWorkletRuntime(
-    _name: string,
-    _initializer: ShareableRef<() => void>
-  ): WorkletRuntime {
-    throw new ReanimatedError(
-      'createWorkletRuntime is not available in JSReanimated.'
-    );
-  }
-
-  scheduleOnRuntime() {
-    throw new ReanimatedError(
-      'scheduleOnRuntime is not available in JSReanimated.'
-    );
-  }
-
   registerEventHandler<T>(
     _eventHandler: ShareableRef<T>,
     _eventName: string,
@@ -293,12 +263,6 @@ class JSReanimated implements IReanimatedModule {
       'configureProps is not available in JSReanimated.'
     );
   }
-
-  executeOnUIRuntimeSync<T, R>(_shareable: ShareableRef<T>): R {
-    throw new ReanimatedError(
-      '`executeOnUIRuntimeSync` is not available in JSReanimated.'
-    );
-  }
 }
 
 // Lack of this export breaks TypeScript generation since
diff --git a/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts b/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts
index 5d334fb9897..a2380bfee86 100644
--- a/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts
+++ b/packages/react-native-reanimated/src/ReanimatedModule/reanimatedModuleProxy.ts
@@ -8,24 +8,9 @@ import type {
   LayoutAnimationBatchItem,
   WorkletFunction,
 } from '../commonTypes';
-import type { WorkletRuntime } from '../runtimes';
 
 /** Type of `__reanimatedModuleProxy` injected with JSI. */
 export interface ReanimatedModuleProxy {
-  scheduleOnUI<T>(shareable: ShareableRef<T>): void;
-
-  executeOnUIRuntimeSync<T, R>(shareable: ShareableRef<T>): R;
-
-  createWorkletRuntime(
-    name: string,
-    initializer: ShareableRef<() => void>
-  ): WorkletRuntime;
-
-  scheduleOnRuntime<T>(
-    workletRuntime: WorkletRuntime,
-    worklet: ShareableRef<T>
-  ): void;
-
   registerEventHandler<T>(
     eventHandler: ShareableRef<T>,
     eventName: string,
diff --git a/packages/react-native-reanimated/src/commonTypes.ts b/packages/react-native-reanimated/src/commonTypes.ts
index 725436df1d8..68bdc7888c5 100644
--- a/packages/react-native-reanimated/src/commonTypes.ts
+++ b/packages/react-native-reanimated/src/commonTypes.ts
@@ -8,10 +8,14 @@ import type {
 import type { WorkletsModuleProxy } from './worklets';
 import type { ReanimatedModuleProxy } from './ReanimatedModule';
 
-export interface IWorkletsModule extends WorkletsModuleProxy {}
+type DisallowKeysOf<TInterface> = {
+  [TKey in keyof TInterface]?: never;
+};
 
+export interface IWorkletsModule extends WorkletsModuleProxy {}
 export interface IReanimatedModule
-  extends Omit<ReanimatedModuleProxy, 'getViewProp'> {
+  extends Omit<ReanimatedModuleProxy, 'getViewProp'>,
+    DisallowKeysOf<IWorkletsModule> {
   getViewProp<TValue>(
     viewTag: number,
     propName: string,
diff --git a/packages/react-native-reanimated/src/runtimes.ts b/packages/react-native-reanimated/src/runtimes.ts
index 448d0d2a70b..3237acc0e67 100644
--- a/packages/react-native-reanimated/src/runtimes.ts
+++ b/packages/react-native-reanimated/src/runtimes.ts
@@ -4,12 +4,12 @@ import type { WorkletFunction } from './commonTypes';
 import { ReanimatedError, registerReanimatedError } from './errors';
 import { setupCallGuard, setupConsole } from './initializers';
 import { registerLoggerConfig } from './logger';
-import { ReanimatedModule } from './ReanimatedModule';
 import { shouldBeUseWeb } from './PlatformChecker';
 import {
   makeShareableCloneOnUIRecursive,
   makeShareableCloneRecursive,
 } from './shareables';
+import { WorkletsModule } from './worklets';
 
 const SHOULD_BE_USE_WEB = shouldBeUseWeb();
 
@@ -43,7 +43,7 @@ export function createWorkletRuntime(
   // Assign to a different variable as __reanimatedLoggerConfig is not a captured
   // identifier in the Worklet runtime.
   const config = __reanimatedLoggerConfig;
-  return ReanimatedModule.createWorkletRuntime(
+  return WorkletsModule.createWorkletRuntime(
     name,
     makeShareableCloneRecursive(() => {
       'worklet';
@@ -86,7 +86,7 @@ export function runOnRuntime<Args extends unknown[], ReturnValue>(
       );
   }
   return (...args) =>
-    ReanimatedModule.scheduleOnRuntime(
+    WorkletsModule.scheduleOnRuntime(
       workletRuntime,
       makeShareableCloneRecursive(() => {
         'worklet';
diff --git a/packages/react-native-reanimated/src/threads.ts b/packages/react-native-reanimated/src/threads.ts
index 02b46d687c2..291798b82de 100644
--- a/packages/react-native-reanimated/src/threads.ts
+++ b/packages/react-native-reanimated/src/threads.ts
@@ -7,7 +7,7 @@ import {
 } from './shareables';
 import { isWorkletFunction } from './commonTypes';
 import { ReanimatedError } from './errors';
-import { ReanimatedModule } from './ReanimatedModule';
+import { WorkletsModule } from './worklets';
 
 const IS_JEST = isJest();
 const SHOULD_BE_USE_WEB = shouldBeUseWeb();
@@ -101,7 +101,7 @@ export function runOnUI<Args extends unknown[], ReturnValue>(
       // that's not possible, and hence in Jest environment instead of using scheduling
       // mechanism we just schedule the work ommiting the queue. This is ok for the
       // uses that we currently have but may not be ok for future tests that we write.
-      ReanimatedModule.scheduleOnUI(
+      WorkletsModule.scheduleOnUI(
         makeShareableCloneRecursive(() => {
           'worklet';
           worklet(...args);
@@ -123,7 +123,7 @@ export function runOnUI<Args extends unknown[], ReturnValue>(
       queueMicrotask(() => {
         const queue = _runOnUIQueue;
         _runOnUIQueue = [];
-        ReanimatedModule.scheduleOnUI(
+        WorkletsModule.scheduleOnUI(
           makeShareableCloneRecursive(() => {
             'worklet';
             // eslint-disable-next-line @typescript-eslint/no-shadow
@@ -147,7 +147,7 @@ export function executeOnUIRuntimeSync<Args extends unknown[], ReturnValue>(
   worklet: WorkletFunction<Args, ReturnValue>
 ): (...args: Args) => ReturnValue {
   return (...args) => {
-    return ReanimatedModule.executeOnUIRuntimeSync(
+    return WorkletsModule.executeOnUIRuntimeSync(
       makeShareableCloneRecursive(() => {
         'worklet';
         const result = worklet(...args);
@@ -177,7 +177,7 @@ export function runOnUIImmediately<Args extends unknown[], ReturnValue>(
     );
   }
   return (...args) => {
-    ReanimatedModule.scheduleOnUI(
+    WorkletsModule.scheduleOnUI(
       makeShareableCloneRecursive(() => {
         'worklet';
         worklet(...args);
diff --git a/packages/react-native-reanimated/src/worklets/WorkletsModule/JSWorklets.ts b/packages/react-native-reanimated/src/worklets/WorkletsModule/JSWorklets.ts
index 2cc7cfa714c..3b535f81286 100644
--- a/packages/react-native-reanimated/src/worklets/WorkletsModule/JSWorklets.ts
+++ b/packages/react-native-reanimated/src/worklets/WorkletsModule/JSWorklets.ts
@@ -2,15 +2,53 @@
 
 import type { IWorkletsModule, ShareableRef } from '../../commonTypes';
 import { ReanimatedError } from '../../errors';
+import { mockedRequestAnimationFrame } from '../../mockedRequestAnimationFrame';
+import { isJest } from '../../PlatformChecker';
+import type { WorkletRuntime } from '../../runtimes';
 
 export function createJSWorkletsModule(): IWorkletsModule {
   return new JSWorklets();
 }
 
+// In Node.js environments (like when static rendering with Expo Router)
+// requestAnimationFrame is unavailable, so we use our mock.
+// It also has to be mocked for Jest purposes (see `initializeUIRuntime`).
+const requestAnimationFrameImpl =
+  isJest() || !globalThis.requestAnimationFrame
+    ? mockedRequestAnimationFrame
+    : globalThis.requestAnimationFrame;
+
 class JSWorklets implements IWorkletsModule {
-  makeShareableClone<T>(): ShareableRef<T> {
+  makeShareableClone<TValue>(): ShareableRef<TValue> {
     throw new ReanimatedError(
       'makeShareableClone should never be called in JSWorklets.'
     );
   }
+
+  scheduleOnUI<TValue>(worklet: ShareableRef<TValue>) {
+    // @ts-ignore web implementation has still not been updated after the rewrite,
+    // this will be addressed once the web implementation updates are ready
+    requestAnimationFrameImpl(worklet);
+  }
+
+  executeOnUIRuntimeSync<T, R>(_shareable: ShareableRef<T>): R {
+    throw new ReanimatedError(
+      '`executeOnUIRuntimeSync` is not available in JSReanimated.'
+    );
+  }
+
+  createWorkletRuntime(
+    _name: string,
+    _initializer: ShareableRef<() => void>
+  ): WorkletRuntime {
+    throw new ReanimatedError(
+      'createWorkletRuntime is not available in JSReanimated.'
+    );
+  }
+
+  scheduleOnRuntime() {
+    throw new ReanimatedError(
+      'scheduleOnRuntime is not available in JSReanimated.'
+    );
+  }
 }
diff --git a/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts b/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts
index e305d6f164d..16243cefe2e 100644
--- a/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts
+++ b/packages/react-native-reanimated/src/worklets/WorkletsModule/NativeWorklets.ts
@@ -2,8 +2,9 @@
 import { getValueUnpackerCode } from '../valueUnpacker';
 import { WorkletsTurboModule } from '../../specs';
 import { ReanimatedError } from '../../errors';
-import type { IWorkletsModule } from '../../commonTypes';
+import type { IWorkletsModule, ShareableRef } from '../../commonTypes';
 import type { WorkletsModuleProxy } from './workletsModuleProxy';
+import type { WorkletRuntime } from '../../runtimes';
 
 export function createNativeWorkletsModule(): IWorkletsModule {
   return new NativeWorklets();
@@ -26,8 +27,8 @@ See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooti
     this.#workletsModuleProxy = global.__workletsModuleProxy;
   }
 
-  makeShareableClone<T>(
-    value: T,
+  makeShareableClone<TValue>(
+    value: TValue,
     shouldPersistRemote: boolean,
     nativeStateSource?: object
   ) {
@@ -37,4 +38,28 @@ See https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshooti
       nativeStateSource
     );
   }
+
+  scheduleOnUI<TValue>(shareable: ShareableRef<TValue>) {
+    return this.#workletsModuleProxy.scheduleOnUI(shareable);
+  }
+
+  executeOnUIRuntimeSync<TValue, TReturn>(
+    shareable: ShareableRef<TValue>
+  ): TReturn {
+    return this.#workletsModuleProxy.executeOnUIRuntimeSync(shareable);
+  }
+
+  createWorkletRuntime(name: string, initializer: ShareableRef<() => void>) {
+    return this.#workletsModuleProxy.createWorkletRuntime(name, initializer);
+  }
+
+  scheduleOnRuntime<T>(
+    workletRuntime: WorkletRuntime,
+    shareableWorklet: ShareableRef<T>
+  ) {
+    return this.#workletsModuleProxy.scheduleOnRuntime(
+      workletRuntime,
+      shareableWorklet
+    );
+  }
 }
diff --git a/packages/react-native-reanimated/src/worklets/WorkletsModule/workletsModuleProxy.ts b/packages/react-native-reanimated/src/worklets/WorkletsModule/workletsModuleProxy.ts
index 537e5556502..df96918633a 100644
--- a/packages/react-native-reanimated/src/worklets/WorkletsModule/workletsModuleProxy.ts
+++ b/packages/react-native-reanimated/src/worklets/WorkletsModule/workletsModuleProxy.ts
@@ -1,6 +1,7 @@
 'use strict';
 
 import type { ShareableRef } from '../../commonTypes';
+import type { WorkletRuntime } from '../../runtimes';
 
 /** Type of `__workletsModuleProxy` injected with JSI. */
 export interface WorkletsModuleProxy {
@@ -9,4 +10,20 @@ export interface WorkletsModuleProxy {
     shouldPersistRemote: boolean,
     nativeStateSource?: object
   ): ShareableRef<TValue>;
+
+  scheduleOnUI<TValue>(shareable: ShareableRef<TValue>): void;
+
+  executeOnUIRuntimeSync<TValue, TReturn>(
+    shareable: ShareableRef<TValue>
+  ): TReturn;
+
+  createWorkletRuntime(
+    name: string,
+    initializer: ShareableRef<() => void>
+  ): WorkletRuntime;
+
+  scheduleOnRuntime<TValue>(
+    workletRuntime: WorkletRuntime,
+    worklet: ShareableRef<TValue>
+  ): void;
 }