From 1c66e51523bed41cc9f23a18d0fbeacc455002d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tomasz=20=C5=BBelawski?=
 <40713406+tjzel@users.noreply.github.com>
Date: Wed, 29 Jan 2025 14:42:28 +0100
Subject: [PATCH] feat: duplicate worklets code the smart way (#6827)

## Summary

In the transitional period of `react-native-worklets` coming as a
separate package, Reanimated should work with or without
`react-native-worklets` installed. This requires the code of Worklets to
be present both in `react-native-reanimated` and
`react-native-worklets`.

This PR moves Worklets' files that were in Reanimated to
`react-native-worklets` package and adds a script that makes hard links
to these files. The linking happens during the `yarn build` step of
`react-native-reanimated` - this guarantees that
`react-native-reanimated` would still work without
`react-native-worklets` and that its' npm package would still contain
all the necessary files.

For Android some files had to be duplicated. This is because of codegen
conflicts and namespace generation. However, that code is relatively
small and put into respective source sets `externalWorklets/with` and
`externalWorklets/without`.

Also:
- I moved `ReanimatedVersion.cpp/h` files back to Reanimated. We'll
implement version checking for Worklets when we actually need it.
- I adjusted the CI to always do `yarn build` in Reanimated when
necessary.
- Enabled detection of `react-native-worklets` in
`react-native-reanimated`.
- I improved the detection mechanism of `react-native-worklets` for iOS.
- Renamed `NativeWorkletsModuleSpec.ts` to
`NativeReaWorkletsModuleSpec.ts` to avoid codegen conflicts.
- Removed `DummyWorkletsModule` from `react-native-worklets` since now
it has `WorkletsModule`.



## Test plan

Run an Example with these changes.

Then do `yarn add react-native-worklets` in `common-app` (it will use
workspace version by default) in the example directory and run it again.
---
 .../workflows/example-android-build-check.yml |  9 ++
 .github/workflows/example-ios-build-check.yml |  4 +
 .../workflows/example-macos-build-check.yml   |  9 ++
 .../workflows/example-tvos-build-check.yml    | 15 +--
 .../reanimated-android-validation.yml         |  7 +-
 .../workflows/reanimated-apple-validation.yml |  7 +-
 .../reanimated-common-validation.yml          | 11 ++-
 packages/react-native-reanimated/.gitignore   |  6 ++
 .../RuntimeDecorators/RNRuntimeDecorator.cpp  |  2 +-
 .../Tools/ReanimatedVersion.cpp               |  8 +-
 .../Tools/ReanimatedVersion.h                 |  8 +-
 .../RNReanimated.podspec                      | 10 +-
 .../android/build.gradle                      | 12 ++-
 .../reanimated/ReanimatedPackage.java         | 97 +++++++++++++++++++
 .../reanimated/ReanimatedPackage.java         |  8 +-
 .../swmansion/worklets/WorkletsModule.java    |  8 +-
 .../cpp/reanimated/android/NativeProxy.cpp    |  2 +-
 .../src/main/cpp/worklets/CMakeLists.txt      | 85 ----------------
 packages/react-native-reanimated/package.json |  2 +-
 .../scripts/duplicate-worklets-code.sh        | 34 +++++++
 .../scripts/reanimated_utils.rb               | 12 +++
 ...tsModule.ts => NativeReaWorkletsModule.ts} |  0
 .../src/specs/index.ts                        |  2 +-
 .../NativeModules/WorkletsModuleProxy.cpp     |  0
 .../NativeModules/WorkletsModuleProxy.h       |  0
 .../NativeModules/WorkletsModuleProxySpec.cpp |  0
 .../NativeModules/WorkletsModuleProxySpec.h   |  0
 .../Registries/EventHandlerRegistry.cpp       |  0
 .../Registries/EventHandlerRegistry.h         |  0
 .../Registries/WorkletRuntimeRegistry.cpp     |  0
 .../Registries/WorkletRuntimeRegistry.h       |  0
 .../cpp/worklets/SharedItems/Shareables.cpp   |  0
 .../cpp/worklets/SharedItems/Shareables.h     |  0
 .../Common/cpp/worklets/Tools/AsyncQueue.cpp  |  0
 .../Common/cpp/worklets/Tools/AsyncQueue.h    |  0
 .../Common/cpp/worklets/Tools/Defs.h          |  0
 .../cpp/worklets/Tools/JSISerializer.cpp      |  0
 .../Common/cpp/worklets/Tools/JSISerializer.h |  0
 .../Common/cpp/worklets/Tools/JSLogger.cpp    |  0
 .../Common/cpp/worklets/Tools/JSLogger.h      |  0
 .../Common/cpp/worklets/Tools/JSScheduler.cpp |  0
 .../Common/cpp/worklets/Tools/JSScheduler.h   |  0
 .../cpp/worklets/Tools/PlatformLogger.h       |  0
 .../cpp/worklets/Tools/ReanimatedJSIUtils.cpp |  0
 .../cpp/worklets/Tools/ReanimatedJSIUtils.h   |  0
 .../worklets/Tools/SingleInstanceChecker.h    |  0
 .../cpp/worklets/Tools/ThreadSafeQueue.h      |  0
 .../Common/cpp/worklets/Tools/UIScheduler.cpp |  0
 .../Common/cpp/worklets/Tools/UIScheduler.h   |  0
 .../worklets/Tools/WorkletEventHandler.cpp    |  0
 .../cpp/worklets/Tools/WorkletEventHandler.h  |  0
 .../RNRuntimeWorkletDecorator.cpp             |  0
 .../RNRuntimeWorkletDecorator.h               |  0
 .../ReanimatedHermesRuntime.cpp               |  0
 .../WorkletRuntime/ReanimatedHermesRuntime.h  |  0
 .../WorkletRuntime/ReanimatedRuntime.cpp      |  0
 .../WorkletRuntime/ReanimatedRuntime.h        |  0
 .../WorkletRuntime/RuntimeInitialization.md   |  0
 .../WorkletRuntime/WorkletRuntime.cpp         |  0
 .../worklets/WorkletRuntime/WorkletRuntime.h  |  0
 .../WorkletRuntime/WorkletRuntimeCollector.h  |  0
 .../WorkletRuntimeDecorator.cpp               |  0
 .../WorkletRuntime/WorkletRuntimeDecorator.h  |  0
 .../android/CMakeLists.txt                    |  3 +-
 .../android/build.gradle                      | 12 +++
 .../src/main/cpp/worklets/CMakeLists.txt      |  2 +-
 .../worklets/android/AndroidUIScheduler.cpp   |  0
 .../cpp/worklets/android/AndroidUIScheduler.h |  0
 .../cpp/worklets/android/PlatformLogger.cpp   |  0
 .../cpp/worklets/android/WorkletsModule.cpp   |  0
 .../cpp/worklets/android/WorkletsModule.h     |  0
 .../cpp/worklets/android/WorkletsOnLoad.cpp   |  0
 .../worklets/DummyWorkletsModule.java         | 18 ----
 .../swmansion/worklets/WorkletsModule.java    | 80 +++++++++++++++
 .../swmansion/worklets/WorkletsPackage.java   |  6 +-
 .../worklets/AndroidUIScheduler.java          |  0
 .../worklets/JSCallInvokerResolver.java       |  0
 .../worklets/WorkletsMessageQueueThread.java  |  0
 .../WorkletsMessageQueueThreadBase.java       |  0
 .../worklets/NativeWorkletsModuleSpec.java    | 26 +++++
 .../worklets/apple/DummyWorkletsModule.h      |  5 -
 .../worklets/apple/DummyWorkletsModule.mm     | 19 ----
 .../apple/worklets/apple/IOSUIScheduler.h     |  0
 .../apple/worklets/apple/IOSUIScheduler.mm    |  0
 .../apple/worklets/apple/PlatformLogger.mm    |  0
 .../worklets/apple/WorkletsMessageThread.h    |  0
 .../worklets/apple/WorkletsMessageThread.mm   |  0
 .../apple/worklets/apple/WorkletsModule.h     |  0
 .../apple/worklets/apple/WorkletsModule.mm    |  0
 packages/react-native-worklets/package.json   |  2 +-
 packages/react-native-worklets/src/index.ts   |  2 +-
 ...mmyWorklets.ts => NativeWorkletsModule.ts} |  4 +-
 .../react-native-worklets/src/specs/index.ts  |  4 +-
 93 files changed, 361 insertions(+), 180 deletions(-)
 rename packages/react-native-reanimated/Common/cpp/{worklets => reanimated}/Tools/ReanimatedVersion.cpp (94%)
 rename packages/react-native-reanimated/Common/cpp/{worklets => reanimated}/Tools/ReanimatedVersion.h (67%)
 create mode 100644 packages/react-native-reanimated/android/src/externalWorklets/with/com/swmansion/reanimated/ReanimatedPackage.java
 rename packages/react-native-reanimated/android/src/{main/java => externalWorklets/without}/com/swmansion/reanimated/ReanimatedPackage.java (91%)
 delete mode 100644 packages/react-native-reanimated/android/src/main/cpp/worklets/CMakeLists.txt
 create mode 100755 packages/react-native-reanimated/scripts/duplicate-worklets-code.sh
 rename packages/react-native-reanimated/src/specs/{NativeWorkletsModule.ts => NativeReaWorkletsModule.ts} (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Registries/EventHandlerRegistry.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/SharedItems/Shareables.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/SharedItems/Shareables.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/AsyncQueue.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/AsyncQueue.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/Defs.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/JSISerializer.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/JSISerializer.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/JSLogger.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/JSLogger.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/JSScheduler.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/JSScheduler.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/PlatformLogger.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/ReanimatedJSIUtils.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/ReanimatedJSIUtils.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/SingleInstanceChecker.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/ThreadSafeQueue.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/UIScheduler.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/UIScheduler.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/WorkletEventHandler.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/Tools/WorkletEventHandler.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/main/cpp/worklets/android/AndroidUIScheduler.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/main/cpp/worklets/android/PlatformLogger.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/main/cpp/worklets/android/WorkletsModule.cpp (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/main/cpp/worklets/android/WorkletsModule.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/main/cpp/worklets/android/WorkletsOnLoad.cpp (100%)
 delete mode 100644 packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/DummyWorkletsModule.java
 create mode 100644 packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsModule.java
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/worklets/main/com/swmansion/worklets/AndroidUIScheduler.java (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/worklets/main/com/swmansion/worklets/JSCallInvokerResolver.java (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThread.java (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java (100%)
 create mode 100644 packages/react-native-worklets/android/src/worklets/paper/com/swmansion/worklets/NativeWorkletsModuleSpec.java
 delete mode 100644 packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.h
 delete mode 100644 packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.mm
 rename packages/{react-native-reanimated => react-native-worklets}/apple/worklets/apple/IOSUIScheduler.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/apple/worklets/apple/IOSUIScheduler.mm (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/apple/worklets/apple/PlatformLogger.mm (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/apple/worklets/apple/WorkletsMessageThread.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/apple/worklets/apple/WorkletsMessageThread.mm (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/apple/worklets/apple/WorkletsModule.h (100%)
 rename packages/{react-native-reanimated => react-native-worklets}/apple/worklets/apple/WorkletsModule.mm (100%)
 rename packages/react-native-worklets/src/specs/{NativeDummyWorklets.ts => NativeWorkletsModule.ts} (55%)

diff --git a/.github/workflows/example-android-build-check.yml b/.github/workflows/example-android-build-check.yml
index ff190292ab1..4896439e3f6 100644
--- a/.github/workflows/example-android-build-check.yml
+++ b/.github/workflows/example-android-build-check.yml
@@ -43,6 +43,7 @@ jobs:
     env:
       WORKING_DIRECTORY: apps/fabric-example
       COMMON_APP_DIR: apps/common-app
+      REANIMATED_DIR: packages/react-native-reanimated
     concurrency:
       group: android-${{ github.ref }}-${{ inputs.use-external-worklets }}
       cancel-in-progress: true
@@ -59,6 +60,14 @@ jobs:
       # TODO: Add caching for node_modules and artifacts that will work with monorepo setup.
       - name: Install monorepo node dependencies
         run: yarn install --immutable
+      - name: Build Reanimated package
+        working-directory: ${{ env.REANIMATED_DIR }}
+        run: yarn build
+
+      - name: Use external worklets
+        if: ${{ inputs.use-external-worklets == 'true' }}
+        working-directory: ${{ env.COMMON_APP_DIR }}
+        run: yarn add react-native-worklets@workspace:"*"
 
       - name: Use external worklets
         if: ${{ inputs.use-external-worklets == 'true' }}
diff --git a/.github/workflows/example-ios-build-check.yml b/.github/workflows/example-ios-build-check.yml
index 8fd9829d59e..a262953d3a0 100644
--- a/.github/workflows/example-ios-build-check.yml
+++ b/.github/workflows/example-ios-build-check.yml
@@ -47,6 +47,7 @@ jobs:
     env:
       WORKING_DIRECTORY: apps/fabric-example
       COMMON_APP_DIR: apps/common-app
+      REANIMATED_DIR: packages/react-native-reanimated
     concurrency:
       group: ios-${{ github.ref }}-${{ inputs.use-external-worklets }}
       cancel-in-progress: true
@@ -60,6 +61,9 @@ jobs:
 
       - name: Install monorepo node dependencies
         run: yarn install --immutable
+      - name: Build Reanimated package
+        working-directory: ${{ env.REANIMATED_DIR }}
+        run: yarn build
 
       - name: Use external worklets
         if: ${{ inputs.use-external-worklets == 'true' }}
diff --git a/.github/workflows/example-macos-build-check.yml b/.github/workflows/example-macos-build-check.yml
index df1bb910ee7..f21c2b32499 100644
--- a/.github/workflows/example-macos-build-check.yml
+++ b/.github/workflows/example-macos-build-check.yml
@@ -49,6 +49,7 @@ jobs:
     env:
       WORKING_DIRECTORY: apps/macos-example
       COMMON_APP_DIR: apps/common-app
+      REANIMATED_DIR: packages/react-native-reanimated
     concurrency:
       group: macos-${{ github.ref }}-${{ inputs.use-external-worklets }}
       cancel-in-progress: true
@@ -63,6 +64,14 @@ jobs:
       # TODO: Add caching for node_modules and artifacts that will work with monorepo setup.
       - name: Install monorepo node dependencies
         run: yarn install --immutable
+      - name: Build Reanimated package
+        working-directory: ${{ env.REANIMATED_DIR }}
+        run: yarn build
+
+      - name: Use external worklets
+        if: ${{ inputs.use-external-worklets == 'true' }}
+        working-directory: ${{ env.COMMON_APP_DIR }}
+        run: yarn add react-native-worklets@workspace:"*"
 
       - name: Use external worklets
         if: ${{ inputs.use-external-worklets == 'true' }}
diff --git a/.github/workflows/example-tvos-build-check.yml b/.github/workflows/example-tvos-build-check.yml
index e3e0323cb48..3e2e42082b6 100644
--- a/.github/workflows/example-tvos-build-check.yml
+++ b/.github/workflows/example-tvos-build-check.yml
@@ -43,6 +43,7 @@ jobs:
     env:
       WORKING_DIRECTORY: apps/tvos-example
       COMMON_APP_DIR: apps/common-app
+      REANIMATED_DIR: packages/react-native-reanimated
     concurrency:
       group: tvos-${{ github.ref }}-${{ inputs.use-external-worklets }}
       cancel-in-progress: true
@@ -56,14 +57,14 @@ jobs:
 
       - name: Install monorepo node dependencies
         run: yarn install --immutable
-      # TODO: Add caching for node_modules and artifacts that will work with monorepo setup.
-      - name: Install Reanimated node_modules
-        working-directory: packages/react-native-reanimated
-        run: yarn install --immutable
+      - name: Build Reanimated package
+        working-directory: ${{ env.REANIMATED_DIR }}
+        run: yarn build
 
-      - name: Install app node_modules
-        working-directory: ${{ env.WORKING_DIRECTORY }}
-        run: yarn install --immutable
+      - name: Use external worklets
+        if: ${{ inputs.use-external-worklets == 'true' }}
+        working-directory: ${{ env.COMMON_APP_DIR }}
+        run: yarn add react-native-worklets@workspace:"*"
 
       - name: Use external worklets
         if: ${{ inputs.use-external-worklets == 'true' }}
diff --git a/.github/workflows/reanimated-android-validation.yml b/.github/workflows/reanimated-android-validation.yml
index ca1e55c4b50..acd9875d296 100644
--- a/.github/workflows/reanimated-android-validation.yml
+++ b/.github/workflows/reanimated-android-validation.yml
@@ -34,6 +34,8 @@ jobs:
     concurrency:
       group: validate-java-${{ github.ref }}
       cancel-in-progress: true
+    env:
+      REANIMATED_DIR: packages/react-native-reanimated
     steps:
       - name: checkout
         uses: actions/checkout@v4
@@ -62,7 +64,10 @@ jobs:
 
       - name: Install monorepo node dependencies
         run: yarn install --immutable
+      - name: Build Reanimated package
+        working-directory: ${{ env.REANIMATED_DIR }}
+        run: yarn build
 
       - name: Lint Android
-        working-directory: packages/react-native-reanimated
+        working-directory: ${{ env.REANIMATED_DIR }}
         run: yarn lint:android
diff --git a/.github/workflows/reanimated-apple-validation.yml b/.github/workflows/reanimated-apple-validation.yml
index b94907d6ceb..869a979c7f9 100644
--- a/.github/workflows/reanimated-apple-validation.yml
+++ b/.github/workflows/reanimated-apple-validation.yml
@@ -29,13 +29,18 @@ on:
 jobs:
   check:
     if: github.repository == 'software-mansion/react-native-reanimated'
+    env:
+      REANIMATED_DIR: packages/react-native-reanimated
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
 
       - name: Install monorepo node dependencies
         run: yarn install --immutable
+      - name: Build Reanimated package
+        working-directory: ${{ env.REANIMATED_DIR }}
+        run: yarn build
 
       - name: Lint apple
-        working-directory: packages/react-native-reanimated
+        working-directory: ${{ env.REANIMATED_DIR }}
         run: yarn lint:apple
diff --git a/.github/workflows/reanimated-common-validation.yml b/.github/workflows/reanimated-common-validation.yml
index 25c4063f448..38b0d894651 100644
--- a/.github/workflows/reanimated-common-validation.yml
+++ b/.github/workflows/reanimated-common-validation.yml
@@ -28,7 +28,8 @@ jobs:
     strategy:
       matrix:
         python-version: [3.13]
-
+    env:
+      REANIMATED_DIR: packages/react-native-reanimated
     steps:
       - uses: actions/checkout@v4
 
@@ -42,11 +43,15 @@ jobs:
           pip install cpplint==1.6.1
       - name: Install monorepo node dependencies
         run: yarn install --immutable
+      - name: Build Reanimated
+        working-directory: ${{ env.REANIMATED_DIR }}
+        run: yarn build
 
       - name: Lint Common
-        working-directory: packages/react-native-reanimated
+        working-directory: ${{ env.REANIMATED_DIR }}
         run: yarn lint:common
 
       - name: Disallow DEBUG macros
+        working-directory: ${{ env.REANIMATED_DIR }}
         run: |
-          ! egrep -r '(#if DEBUG|#ifdef DEBUG)' packages/react-native-reanimated/Common/cpp/ packages/react-native-reanimated/apple/ packages/react-native-reanimated/android/src/main/cpp/
+          ! egrep -r '(#if DEBUG|#ifdef DEBUG)' Common/cpp/ apple/ android/src/main/cpp/
diff --git a/packages/react-native-reanimated/.gitignore b/packages/react-native-reanimated/.gitignore
index fb2d9a6b12a..9e966e6e209 100644
--- a/packages/react-native-reanimated/.gitignore
+++ b/packages/react-native-reanimated/.gitignore
@@ -71,3 +71,9 @@ plugin/types
 
 # library bundle
 *.tgz
+
+# Worklets code (duplicated)
+apple/worklets
+Common/cpp/worklets
+android/src/worklets
+android/src/main/cpp/worklets
diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp
index 59ff85f6505..a20b0f5dcbf 100644
--- a/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp
+++ b/packages/react-native-reanimated/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp
@@ -1,5 +1,5 @@
 #include <reanimated/RuntimeDecorators/RNRuntimeDecorator.h>
-#include <worklets/Tools/ReanimatedVersion.h>
+#include <reanimated/Tools/ReanimatedVersion.h>
 
 namespace reanimated {
 
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedVersion.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReanimatedVersion.cpp
similarity index 94%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedVersion.cpp
rename to packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReanimatedVersion.cpp
index 0f982afebca..9d86d84b68c 100644
--- a/packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedVersion.cpp
+++ b/packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReanimatedVersion.cpp
@@ -1,5 +1,5 @@
+#include <reanimated/Tools/ReanimatedVersion.h>
 #include <worklets/Tools/JSLogger.h>
-#include <worklets/Tools/ReanimatedVersion.h>
 
 #include <memory>
 #include <regex>
@@ -13,7 +13,7 @@
 
 using namespace facebook;
 
-namespace worklets {
+namespace reanimated {
 
 std::string getReanimatedCppVersion() {
   return std::string(REANIMATED_VERSION_STRING);
@@ -54,7 +54,7 @@ bool matchVersion(const std::string &version1, const std::string &version2) {
 
 void checkJSVersion(
     jsi::Runtime &rnRuntime,
-    const std::shared_ptr<JSLogger> &jsLogger) {
+    const std::shared_ptr<worklets::JSLogger> &jsLogger) {
   auto cppVersion = getReanimatedCppVersion();
 
   auto maybeJSVersion =
@@ -92,4 +92,4 @@ bool matchVersion(const std::string &version1, const std::string &version2) {
 }
 #endif // NDEBUG
 
-}; // namespace worklets
+}; // namespace reanimated
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedVersion.h b/packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReanimatedVersion.h
similarity index 67%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedVersion.h
rename to packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReanimatedVersion.h
index 80dfa75971e..07f63a62e2c 100644
--- a/packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedVersion.h
+++ b/packages/react-native-reanimated/Common/cpp/reanimated/Tools/ReanimatedVersion.h
@@ -9,11 +9,13 @@
 
 using namespace facebook;
 
-namespace worklets {
+namespace reanimated {
 
 std::string getReanimatedCppVersion();
 void injectReanimatedCppVersion(jsi::Runtime &);
 bool matchVersion(const std::string &, const std::string &);
-void checkJSVersion(jsi::Runtime &, const std::shared_ptr<JSLogger> &);
+void checkJSVersion(
+    jsi::Runtime &,
+    const std::shared_ptr<worklets::JSLogger> &);
 
-}; // namespace worklets
+}; // namespace reanimated
diff --git a/packages/react-native-reanimated/RNReanimated.podspec b/packages/react-native-reanimated/RNReanimated.podspec
index 9d2832d2f1d..fc5e59cd911 100644
--- a/packages/react-native-reanimated/RNReanimated.podspec
+++ b/packages/react-native-reanimated/RNReanimated.podspec
@@ -77,11 +77,9 @@ Pod::Spec.new do |s|
   s.platforms    = { :ios => ios_min_version, :tvos => "9.0", :osx => "10.14", :visionos => "1.0" }
   s.source       = { :git => "https://github.com/software-mansion/react-native-reanimated.git", :tag => "#{s.version}" }
 
-  # TODO: Uncomment me when dynamic worklets linking is ready
-  # if File.directory?(File.join(__dir__, "../react-native-worklets"))
-  #   # This condition is really naïve...
-  #   s.dependency "RNWorklets"
-  # else
+  if $config[:has_external_worklets]
+    s.dependency "RNWorklets"
+  else
     s.subspec "worklets" do |ss|
       ss.source_files = "Common/cpp/worklets/**/*.{cpp,h}"
       ss.header_dir = "worklets"
@@ -94,7 +92,7 @@ Pod::Spec.new do |s|
         sss.source_files = "apple/worklets/**/*.{mm,h,m}"
         sss.header_dir = "worklets"
         sss.header_mappings_dir = "apple/worklets"
-      # end
+      end
     end
   end
 
diff --git a/packages/react-native-reanimated/android/build.gradle b/packages/react-native-reanimated/android/build.gradle
index dd3d483c41c..c33c8434e32 100644
--- a/packages/react-native-reanimated/android/build.gradle
+++ b/packages/react-native-reanimated/android/build.gradle
@@ -141,9 +141,7 @@ def thirdPartyNdkDir = new File("$buildDir/third-party-ndk")
 def reactNativeThirdParty = new File("$reactNativeRootDir/ReactAndroid/src/main/jni/third-party")
 def reactNativeAndroidDownloadDir = new File("$reactNativeRootDir/ReactAndroid/build/downloads")
 
-// TODO: Uncomment me when when dynamic worklets linking is ready
-// def hasExternalWorklets = rootProject.subprojects.find { it.name == 'react-native-worklets' } != null
-def hasExternalWorklets = false
+def hasExternalWorklets = rootProject.subprojects.find { it.name == 'react-native-worklets' } != null
 
 def workletsPrefabHeadersDir = project.file("$buildDir/prefab-headers/worklets")
 def reanimatedPrefabHeadersDir = project.file("$buildDir/prefab-headers/reanimated")
@@ -260,7 +258,11 @@ android {
                         "-DREANIMATED_VERSION=${REANIMATED_VERSION}",
                         "-DHAS_EXTERNAL_WORKLETS=${hasExternalWorklets}"
                 abiFilters (*reactNativeArchitectures())
-                targets("reanimated", "worklets")
+                if(hasExternalWorklets){
+                    targets("reanimated")
+                } else {
+                    targets("reanimated", "worklets")
+                }
             }
         }
 
@@ -343,7 +345,7 @@ android {
     sourceSets.main {
         java {
             if(hasExternalWorklets){
-                // Nothing for now.
+                srcDirs += "src/externalWorklets/with"
             } else {
                 srcDirs += "src/worklets/main"
                 srcDirs += "src/externalWorklets/without"
diff --git a/packages/react-native-reanimated/android/src/externalWorklets/with/com/swmansion/reanimated/ReanimatedPackage.java b/packages/react-native-reanimated/android/src/externalWorklets/with/com/swmansion/reanimated/ReanimatedPackage.java
new file mode 100644
index 00000000000..e7b5d32ef4f
--- /dev/null
+++ b/packages/react-native-reanimated/android/src/externalWorklets/with/com/swmansion/reanimated/ReanimatedPackage.java
@@ -0,0 +1,97 @@
+package com.swmansion.reanimated;
+
+import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_END;
+import static com.facebook.react.bridge.ReactMarkerConstants.CREATE_UI_MANAGER_MODULE_START;
+
+import androidx.annotation.NonNull;
+import com.facebook.react.BaseReactPackage;
+import com.facebook.react.ReactApplication;
+import com.facebook.react.ReactInstanceManager;
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactMarker;
+import com.facebook.react.module.annotations.ReactModule;
+import com.facebook.react.module.annotations.ReactModuleList;
+import com.facebook.react.module.model.ReactModuleInfo;
+import com.facebook.react.module.model.ReactModuleInfoProvider;
+import com.facebook.react.uimanager.ReanimatedUIManager;
+import com.facebook.react.uimanager.UIManagerModule;
+import com.facebook.react.uimanager.ViewManager;
+import com.facebook.systrace.Systrace;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+@ReactModuleList(
+    nativeModules = {
+      ReanimatedModule.class,
+      ReanimatedUIManager.class,
+    })
+public class ReanimatedPackage extends BaseReactPackage implements ReactPackage {
+  @Override
+  public NativeModule getModule(
+      @NonNull String name, @NonNull ReactApplicationContext reactContext) {
+    return switch (name) {
+      case ReanimatedModule.NAME -> new ReanimatedModule(reactContext);
+      case ReanimatedUIManager.NAME -> createUIManager(reactContext);
+      default -> null;
+    };
+  }
+
+  @Override
+  public ReactModuleInfoProvider getReactModuleInfoProvider() {
+    Class<? extends NativeModule>[] moduleList =
+        new Class[] {
+          ReanimatedModule.class, ReanimatedUIManager.class,
+        };
+
+    final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
+    for (Class<? extends NativeModule> moduleClass : moduleList) {
+      ReactModule reactModule =
+          Objects.requireNonNull(moduleClass.getAnnotation(ReactModule.class));
+
+      reactModuleInfoMap.put(
+          reactModule.name(),
+          new ReactModuleInfo(
+              reactModule.name(),
+              moduleClass.getName(),
+              true, // override UIManagerModule
+              reactModule.needsEagerInit(),
+              reactModule.isCxxModule(),
+              BuildConfig.IS_NEW_ARCHITECTURE_ENABLED));
+    }
+
+    return () -> reactModuleInfoMap;
+  }
+
+  private UIManagerModule createUIManager(final ReactApplicationContext reactContext) {
+    ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_START);
+    Systrace.beginSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE, "createUIManagerModule");
+    final ReactInstanceManager reactInstanceManager = getReactInstanceManager(reactContext);
+    List<ViewManager> viewManagers = reactInstanceManager.getOrCreateViewManagers(reactContext);
+    int minTimeLeftInFrameForNonBatchedOperationMs = -1;
+    try {
+      return ReanimatedUIManagerFactory.create(
+          reactContext, viewManagers, minTimeLeftInFrameForNonBatchedOperationMs);
+    } finally {
+      Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
+      ReactMarker.logMarker(CREATE_UI_MANAGER_MODULE_END);
+    }
+  }
+
+  /**
+   * Get the {@link ReactInstanceManager} used by this app. By default, assumes {@link
+   * ReactApplicationContext#getApplicationContext()} is an instance of {@link ReactApplication} and
+   * calls {@link ReactApplication#getReactNativeHost().getReactInstanceManager()}. Override this
+   * method if your application class does not implement {@code ReactApplication} or you simply have
+   * a different mechanism for storing a {@code ReactInstanceManager}, e.g. as a static field
+   * somewhere.
+   */
+  public ReactInstanceManager getReactInstanceManager(ReactApplicationContext reactContext) {
+    return ((ReactApplication) reactContext.getApplicationContext())
+        .getReactNativeHost()
+        .getReactInstanceManager();
+  }
+}
diff --git a/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedPackage.java b/packages/react-native-reanimated/android/src/externalWorklets/without/com/swmansion/reanimated/ReanimatedPackage.java
similarity index 91%
rename from packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedPackage.java
rename to packages/react-native-reanimated/android/src/externalWorklets/without/com/swmansion/reanimated/ReanimatedPackage.java
index ca640a7c98f..027961f046a 100644
--- a/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/ReanimatedPackage.java
+++ b/packages/react-native-reanimated/android/src/externalWorklets/without/com/swmansion/reanimated/ReanimatedPackage.java
@@ -25,11 +25,9 @@
 import java.util.Map;
 import java.util.Objects;
 
-// `WorkletsModule` should be included from a separate Java package, called `WorkletsPackage`.
-// However, it's not possible with the current state of the Gradle Tools provided by
-// RNC CLI - all packages besides the first found are ignored.
-// Therefore, until we extract `react-native-worklets` to a separate package,
-// we will host this module in Reanimated's package.
+// `WorkletsPackage` must be registered within `ReanimatedPackage` when
+// `react-native-worklets` isn't installed . Extra `...Package` files
+// are ignored by React Native tools.
 @ReactModuleList(
     nativeModules = {
       WorkletsModule.class,
diff --git a/packages/react-native-reanimated/android/src/externalWorklets/without/com/swmansion/worklets/WorkletsModule.java b/packages/react-native-reanimated/android/src/externalWorklets/without/com/swmansion/worklets/WorkletsModule.java
index d5249f8050b..ee1351b6325 100644
--- a/packages/react-native-reanimated/android/src/externalWorklets/without/com/swmansion/worklets/WorkletsModule.java
+++ b/packages/react-native-reanimated/android/src/externalWorklets/without/com/swmansion/worklets/WorkletsModule.java
@@ -1,5 +1,9 @@
 package com.swmansion.worklets;
 
+// In Reanimated the codegen will generate `NativeReaWorkletsModuleSpec`.
+// Therefore we must override this file in Reanimated when
+// `react-native-worklets` isn't installed.
+
 import androidx.annotation.OptIn;
 import com.facebook.jni.HybridData;
 import com.facebook.proguard.annotations.DoNotStrip;
@@ -10,14 +14,14 @@
 import com.facebook.react.module.annotations.ReactModule;
 import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
 import com.facebook.soloader.SoLoader;
-import com.swmansion.reanimated.NativeWorkletsModuleSpec;
+import com.swmansion.reanimated.NativeReaWorkletsModuleSpec;
 import java.util.Objects;
 
 /**
  * @noinspection JavaJniMissingFunction
  */
 @ReactModule(name = WorkletsModule.NAME)
-public class WorkletsModule extends NativeWorkletsModuleSpec {
+public class WorkletsModule extends NativeReaWorkletsModuleSpec {
   static {
     SoLoader.loadLibrary("worklets");
   }
diff --git a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp
index 4a860f77741..2967858efd1 100644
--- a/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp
+++ b/packages/react-native-reanimated/android/src/main/cpp/reanimated/android/NativeProxy.cpp
@@ -1,10 +1,10 @@
 #include <reanimated/LayoutAnimations/LayoutAnimationsManager.h>
 #include <reanimated/RuntimeDecorators/RNRuntimeDecorator.h>
 #include <reanimated/Tools/PlatformDepMethodsHolder.h>
+#include <reanimated/Tools/ReanimatedVersion.h>
 #include <reanimated/android/NativeProxy.h>
 
 #include <worklets/Tools/ReanimatedJSIUtils.h>
-#include <worklets/Tools/ReanimatedVersion.h>
 #include <worklets/WorkletRuntime/ReanimatedRuntime.h>
 #include <worklets/WorkletRuntime/WorkletRuntime.h>
 #include <worklets/WorkletRuntime/WorkletRuntimeCollector.h>
diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/CMakeLists.txt b/packages/react-native-reanimated/android/src/main/cpp/worklets/CMakeLists.txt
deleted file mode 100644
index ce128cf1894..00000000000
--- a/packages/react-native-reanimated/android/src/main/cpp/worklets/CMakeLists.txt
+++ /dev/null
@@ -1,85 +0,0 @@
-cmake_minimum_required(VERSION 3.8)
-
-file(GLOB_RECURSE WORKLETS_COMMON_CPP_SOURCES CONFIGURE_DEPENDS
-     "${COMMON_CPP_DIR}/worklets/*.cpp")
-file(GLOB_RECURSE WORKLETS_ANDROID_CPP_SOURCES CONFIGURE_DEPENDS
-     "${ANDROID_CPP_DIR}/worklets/*.cpp")
-
-# Consume shared libraries and headers from prefabs
-find_package(fbjni REQUIRED CONFIG)
-find_package(ReactAndroid REQUIRED CONFIG)
-
-if(${JS_RUNTIME} STREQUAL "hermes")
-  find_package(hermes-engine REQUIRED CONFIG)
-endif()
-
-add_library(worklets SHARED ${WORKLETS_COMMON_CPP_SOURCES}
-                            ${WORKLETS_ANDROID_CPP_SOURCES})
-
-# includes
-target_include_directories(worklets PUBLIC "${COMMON_CPP_DIR}"
-                                           "${ANDROID_CPP_DIR}")
-
-target_include_directories(
-  worklets
-  PRIVATE "${REACT_NATIVE_DIR}/ReactCommon"
-          "${REACT_NATIVE_DIR}/ReactAndroid/src/main/jni/react/turbomodule"
-          "${REACT_NATIVE_DIR}/ReactCommon/react/nativemodule/core/ReactCommon"
-          "${REACT_NATIVE_DIR}/ReactCommon/callinvoker"
-          "${REACT_NATIVE_DIR}/ReactCommon/runtimeexecutor")
-
-if(${IS_NEW_ARCHITECTURE_ENABLED})
-  target_include_directories(
-    worklets
-    PRIVATE
-      "${REACT_NATIVE_DIR}/ReactCommon/yoga"
-      "${REACT_NATIVE_DIR}/ReactCommon/react/renderer/graphics/platform/cxx")
-
-  if(ReactAndroid_VERSION_MINOR LESS 76)
-    target_link_libraries(
-      worklets ReactAndroid::fabricjni ReactAndroid::react_debug
-      ReactAndroid::react_render_core
-      ReactAndroid::react_render_componentregistry ReactAndroid::rrc_view)
-  endif()
-endif()
-
-# build shared lib
-set_target_properties(worklets PROPERTIES LINKER_LANGUAGE CXX)
-
-target_link_libraries(worklets log ReactAndroid::jsi fbjni::fbjni)
-
-if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
-  target_link_libraries(worklets ReactAndroid::reactnative)
-else()
-  target_link_libraries(
-    worklets ReactAndroid::react_nativemodule_core ReactAndroid::folly_runtime
-    ReactAndroid::glog ReactAndroid::reactnativejni)
-endif()
-
-if(${JS_RUNTIME} STREQUAL "hermes")
-  target_link_libraries(worklets hermes-engine::libhermes)
-
-  if(${HERMES_ENABLE_DEBUGGER})
-    if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
-      target_link_libraries(worklets ReactAndroid::hermestooling)
-    else()
-      target_link_libraries(worklets ReactAndroid::hermes_executor)
-    endif()
-  endif()
-elseif(${JS_RUNTIME} STREQUAL "jsc")
-  if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 76)
-    target_link_libraries(worklets ReactAndroid::jsctooling)
-  else()
-    target_link_libraries(worklets ReactAndroid::jscexecutor)
-  endif()
-elseif(${JS_RUNTIME} STREQUAL "v8")
-  # TODO: Refactor this when adding support for newest V8
-  target_include_directories(worklets PRIVATE "${JS_RUNTIME_DIR}/src")
-  file(GLOB V8_SO_DIR "${JS_RUNTIME_DIR}/android/build/intermediates/\
-    library_jni/**/jni/${ANDROID_ABI}")
-  find_library(
-    V8EXECUTOR_LIB v8executor
-    PATHS ${V8_SO_DIR}
-    NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
-  target_link_libraries(worklets ${V8EXECUTOR_LIB})
-endif()
diff --git a/packages/react-native-reanimated/package.json b/packages/react-native-reanimated/package.json
index 739d4ab3072..93c67385a2c 100644
--- a/packages/react-native-reanimated/package.json
+++ b/packages/react-native-reanimated/package.json
@@ -25,7 +25,7 @@
     "type:check:plugin": "cd plugin && yarn type:check:src",
     "type:check:app": "yarn workspace common-app type:check",
     "type:check:tests:common": "./scripts/test-ts.sh __typetests__/common",
-    "build": "yarn build:plugin && bob build",
+    "build": "./scripts/duplicate-worklets-code.sh && yarn build:plugin && bob build",
     "build:plugin": "cd plugin && yarn build",
     "circular-dependency-check": "yarn madge --extensions js,jsx,ts,tsx --circular src lib",
     "use-strict-check": "node ./scripts/validate-use-strict.js",
diff --git a/packages/react-native-reanimated/scripts/duplicate-worklets-code.sh b/packages/react-native-reanimated/scripts/duplicate-worklets-code.sh
new file mode 100755
index 00000000000..198e46c78ea
--- /dev/null
+++ b/packages/react-native-reanimated/scripts/duplicate-worklets-code.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+echo "Duplicating Worklets in Reanimated"
+
+copy_files_recursively() {
+  local dest_dir=$1
+  local src_dir=$2
+
+  mkdir -p "$dest_dir"
+
+  for file in "$src_dir"/*; do
+    if [ -d "$file" ]; then
+      copy_files_recursively "$dest_dir/$(basename "$file")" "$file"
+    else
+      echo "    Linking $(basename "$file") in Reanimated"
+      ln -f "$file" "$dest_dir/$(basename "$file")"
+    fi
+  done
+}
+
+# Worklets iOS files
+copy_files_recursively "apple/worklets" "../react-native-worklets/apple/worklets"
+
+# Worklets Android files
+# Note that we don't duplicate "android/src/main"
+copy_files_recursively "android/src/worklets" "../react-native-worklets/android/src/worklets"
+
+# Worklets Android-specific cpp files
+copy_files_recursively "android/src/main/cpp/worklets" "../react-native-worklets/android/src/main/cpp/worklets"
+
+# Worklets Common cpp files
+copy_files_recursively "Common/cpp/worklets" "../react-native-worklets/Common/cpp/worklets"
+
+echo "Done duplicating Worklets in Reanimated"
diff --git a/packages/react-native-reanimated/scripts/reanimated_utils.rb b/packages/react-native-reanimated/scripts/reanimated_utils.rb
index aff6bbb3ffe..3ab7ffd4471 100644
--- a/packages/react-native-reanimated/scripts/reanimated_utils.rb
+++ b/packages/react-native-reanimated/scripts/reanimated_utils.rb
@@ -6,6 +6,15 @@ def try_to_parse_react_native_package_json(node_modules_dir)
   return JSON.parse(File.read(react_native_package_json_path))
 end
 
+def has_external_worklets()
+  project_package_json_path = Pod::Config.instance.installation_root + '../package.json'
+  if !File.exist?(project_package_json_path)
+    return false
+  end
+  project_package_json = JSON.parse(File.read(project_package_json_path))
+  return project_package_json['dependencies']['react-native-worklets'] != nil || project_package_json['devDependencies']['react-native-worklets'] != nil
+end
+
 def find_config()
   result = {
     :is_reanimated_example_app => nil,
@@ -15,8 +24,11 @@ def find_config()
     :react_native_node_modules_dir => nil,
     :react_native_common_dir => nil,
     :react_native_reanimated_dir_from_pods_root => nil,
+    :has_external_worklets => nil
   }
 
+  result[:has_external_worklets] = has_external_worklets()
+
   react_native_node_modules_dir = File.join(File.dirname(`cd "#{Pod::Config.instance.installation_root.to_s}" && node --print "require.resolve('react-native/package.json')"`), '..')
   react_native_json = try_to_parse_react_native_package_json(react_native_node_modules_dir)
 
diff --git a/packages/react-native-reanimated/src/specs/NativeWorkletsModule.ts b/packages/react-native-reanimated/src/specs/NativeReaWorkletsModule.ts
similarity index 100%
rename from packages/react-native-reanimated/src/specs/NativeWorkletsModule.ts
rename to packages/react-native-reanimated/src/specs/NativeReaWorkletsModule.ts
diff --git a/packages/react-native-reanimated/src/specs/index.ts b/packages/react-native-reanimated/src/specs/index.ts
index 66b304030fa..0c193348d99 100644
--- a/packages/react-native-reanimated/src/specs/index.ts
+++ b/packages/react-native-reanimated/src/specs/index.ts
@@ -1,6 +1,6 @@
 'use strict';
 
-import WorkletsTurboModule from './NativeWorkletsModule';
+import WorkletsTurboModule from './NativeReaWorkletsModule';
 import ReanimatedTurboModule from './NativeReanimatedModule';
 
 export { WorkletsTurboModule, ReanimatedTurboModule };
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp b/packages/react-native-worklets/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h b/packages/react-native-worklets/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h
rename to packages/react-native-worklets/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp b/packages/react-native-worklets/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h b/packages/react-native-worklets/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h
rename to packages/react-native-worklets/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp b/packages/react-native-worklets/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Registries/EventHandlerRegistry.h b/packages/react-native-worklets/Common/cpp/worklets/Registries/EventHandlerRegistry.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Registries/EventHandlerRegistry.h
rename to packages/react-native-worklets/Common/cpp/worklets/Registries/EventHandlerRegistry.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp b/packages/react-native-worklets/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h b/packages/react-native-worklets/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h
rename to packages/react-native-worklets/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp b/packages/react-native-worklets/Common/cpp/worklets/SharedItems/Shareables.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/SharedItems/Shareables.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h b/packages/react-native-worklets/Common/cpp/worklets/SharedItems/Shareables.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/SharedItems/Shareables.h
rename to packages/react-native-worklets/Common/cpp/worklets/SharedItems/Shareables.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/AsyncQueue.cpp b/packages/react-native-worklets/Common/cpp/worklets/Tools/AsyncQueue.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/AsyncQueue.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/AsyncQueue.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/AsyncQueue.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/AsyncQueue.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/AsyncQueue.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/AsyncQueue.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/Defs.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/Defs.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/Defs.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/Defs.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/JSISerializer.cpp b/packages/react-native-worklets/Common/cpp/worklets/Tools/JSISerializer.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/JSISerializer.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/JSISerializer.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/JSISerializer.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/JSISerializer.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/JSISerializer.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/JSISerializer.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/JSLogger.cpp b/packages/react-native-worklets/Common/cpp/worklets/Tools/JSLogger.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/JSLogger.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/JSLogger.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/JSLogger.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/JSLogger.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/JSLogger.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/JSLogger.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/JSScheduler.cpp b/packages/react-native-worklets/Common/cpp/worklets/Tools/JSScheduler.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/JSScheduler.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/JSScheduler.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/JSScheduler.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/JSScheduler.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/JSScheduler.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/JSScheduler.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/PlatformLogger.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/PlatformLogger.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/PlatformLogger.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/PlatformLogger.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedJSIUtils.cpp b/packages/react-native-worklets/Common/cpp/worklets/Tools/ReanimatedJSIUtils.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedJSIUtils.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/ReanimatedJSIUtils.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedJSIUtils.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/ReanimatedJSIUtils.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/ReanimatedJSIUtils.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/ReanimatedJSIUtils.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/SingleInstanceChecker.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/SingleInstanceChecker.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/SingleInstanceChecker.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/SingleInstanceChecker.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/ThreadSafeQueue.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/ThreadSafeQueue.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/ThreadSafeQueue.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/ThreadSafeQueue.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/UIScheduler.cpp b/packages/react-native-worklets/Common/cpp/worklets/Tools/UIScheduler.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/UIScheduler.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/UIScheduler.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/UIScheduler.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/UIScheduler.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/UIScheduler.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/UIScheduler.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/WorkletEventHandler.cpp b/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletEventHandler.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/WorkletEventHandler.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletEventHandler.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/Tools/WorkletEventHandler.h b/packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletEventHandler.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/Tools/WorkletEventHandler.h
rename to packages/react-native-worklets/Common/cpp/worklets/Tools/WorkletEventHandler.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.cpp b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.h b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.h
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.cpp b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.h b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.h
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp
diff --git a/packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h b/packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h
similarity index 100%
rename from packages/react-native-reanimated/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h
rename to packages/react-native-worklets/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h
diff --git a/packages/react-native-worklets/android/CMakeLists.txt b/packages/react-native-worklets/android/CMakeLists.txt
index 050525a418e..905f2c5030b 100644
--- a/packages/react-native-worklets/android/CMakeLists.txt
+++ b/packages/react-native-worklets/android/CMakeLists.txt
@@ -53,5 +53,4 @@ set(BUILD_DIR "${CMAKE_SOURCE_DIR}/build")
 set(ANDROID_CPP_DIR "${CMAKE_SOURCE_DIR}/src/main/cpp")
 set(COMMON_CPP_DIR "${CMAKE_SOURCE_DIR}/../Common/cpp")
 
-# TODO: Uncomment me when worklets get some sources
-# add_subdirectory("${ANDROID_CPP_DIR}/worklets")
+add_subdirectory("${ANDROID_CPP_DIR}/worklets")
diff --git a/packages/react-native-worklets/android/build.gradle b/packages/react-native-worklets/android/build.gradle
index 4c532e21201..9f42bb82e51 100644
--- a/packages/react-native-worklets/android/build.gradle
+++ b/packages/react-native-worklets/android/build.gradle
@@ -251,6 +251,7 @@ android {
                         "-DIS_NEW_ARCHITECTURE_ENABLED=${IS_NEW_ARCHITECTURE_ENABLED}",
                         "-DIS_REANIMATED_EXAMPLE_APP=${isReanimatedExampleApp()}"
                 abiFilters (*reactNativeArchitectures())
+                targets("worklets")
             }
         }
 
@@ -330,6 +331,17 @@ android {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
     }
+    sourceSets {
+        main {
+            java {
+                srcDirs += "src/worklets/main"
+
+                if (!IS_NEW_ARCHITECTURE_ENABLED) {
+                    srcDirs += "src/worklets/paper"
+                }
+            }
+        }
+    }
 }
 
 def assertMinimalReactNativeVersion = task assertMinimalReactNativeVersionTask {
diff --git a/packages/react-native-worklets/android/src/main/cpp/worklets/CMakeLists.txt b/packages/react-native-worklets/android/src/main/cpp/worklets/CMakeLists.txt
index d441c5ff11c..ce128cf1894 100644
--- a/packages/react-native-worklets/android/src/main/cpp/worklets/CMakeLists.txt
+++ b/packages/react-native-worklets/android/src/main/cpp/worklets/CMakeLists.txt
@@ -76,7 +76,7 @@ elseif(${JS_RUNTIME} STREQUAL "v8")
   # TODO: Refactor this when adding support for newest V8
   target_include_directories(worklets PRIVATE "${JS_RUNTIME_DIR}/src")
   file(GLOB V8_SO_DIR "${JS_RUNTIME_DIR}/android/build/intermediates/\
-    library_jni/*/jni/${ANDROID_ABI}")
+    library_jni/**/jni/${ANDROID_ABI}")
   find_library(
     V8EXECUTOR_LIB v8executor
     PATHS ${V8_SO_DIR}
diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp b/packages/react-native-worklets/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp
similarity index 100%
rename from packages/react-native-reanimated/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp
rename to packages/react-native-worklets/android/src/main/cpp/worklets/android/AndroidUIScheduler.cpp
diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/AndroidUIScheduler.h b/packages/react-native-worklets/android/src/main/cpp/worklets/android/AndroidUIScheduler.h
similarity index 100%
rename from packages/react-native-reanimated/android/src/main/cpp/worklets/android/AndroidUIScheduler.h
rename to packages/react-native-worklets/android/src/main/cpp/worklets/android/AndroidUIScheduler.h
diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/PlatformLogger.cpp b/packages/react-native-worklets/android/src/main/cpp/worklets/android/PlatformLogger.cpp
similarity index 100%
rename from packages/react-native-reanimated/android/src/main/cpp/worklets/android/PlatformLogger.cpp
rename to packages/react-native-worklets/android/src/main/cpp/worklets/android/PlatformLogger.cpp
diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp b/packages/react-native-worklets/android/src/main/cpp/worklets/android/WorkletsModule.cpp
similarity index 100%
rename from packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.cpp
rename to packages/react-native-worklets/android/src/main/cpp/worklets/android/WorkletsModule.cpp
diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h b/packages/react-native-worklets/android/src/main/cpp/worklets/android/WorkletsModule.h
similarity index 100%
rename from packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsModule.h
rename to packages/react-native-worklets/android/src/main/cpp/worklets/android/WorkletsModule.h
diff --git a/packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsOnLoad.cpp b/packages/react-native-worklets/android/src/main/cpp/worklets/android/WorkletsOnLoad.cpp
similarity index 100%
rename from packages/react-native-reanimated/android/src/main/cpp/worklets/android/WorkletsOnLoad.cpp
rename to packages/react-native-worklets/android/src/main/cpp/worklets/android/WorkletsOnLoad.cpp
diff --git a/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/DummyWorkletsModule.java b/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/DummyWorkletsModule.java
deleted file mode 100644
index c2c8821ef85..00000000000
--- a/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/DummyWorkletsModule.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.swmansion.worklets;
-
-import com.facebook.react.bridge.ReactApplicationContext;
-import com.facebook.react.module.annotations.ReactModule;
-
-@ReactModule(name = DummyWorkletsModule.NAME)
-public class DummyWorkletsModule extends
-        NativeDummyWorkletsSpec {
-
-  public DummyWorkletsModule(ReactApplicationContext reactContext) {
-    super(reactContext);
-  }
-
-  @Override
-  public boolean installTurboModule() {
-    return true;
-  }
-}
diff --git a/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsModule.java b/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsModule.java
new file mode 100644
index 00000000000..925efe86749
--- /dev/null
+++ b/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsModule.java
@@ -0,0 +1,80 @@
+package com.swmansion.worklets;
+
+import androidx.annotation.OptIn;
+import com.facebook.jni.HybridData;
+import com.facebook.proguard.annotations.DoNotStrip;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactMethod;
+import com.facebook.react.bridge.queue.MessageQueueThread;
+import com.facebook.react.common.annotations.FrameworkAPI;
+import com.facebook.react.module.annotations.ReactModule;
+import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
+import com.facebook.soloader.SoLoader;
+import java.util.Objects;
+
+/**
+ * @noinspection JavaJniMissingFunction
+ */
+@ReactModule(name = WorkletsModule.NAME)
+public class WorkletsModule extends NativeWorkletsModuleSpec {
+  static {
+    SoLoader.loadLibrary("worklets");
+  }
+
+  @DoNotStrip
+  @SuppressWarnings("unused")
+  private HybridData mHybridData;
+
+  @SuppressWarnings("unused")
+  protected HybridData getHybridData() {
+    return mHybridData;
+  }
+
+  private final WorkletsMessageQueueThread mMessageQueueThread = new WorkletsMessageQueueThread();
+  private final AndroidUIScheduler mAndroidUIScheduler;
+
+  public AndroidUIScheduler getAndroidUIScheduler() {
+    return mAndroidUIScheduler;
+  }
+
+  @OptIn(markerClass = FrameworkAPI.class)
+  private native HybridData initHybrid(
+      long jsContext,
+      String valueUnpackerCode,
+      MessageQueueThread messageQueueThread,
+      CallInvokerHolderImpl jsCallInvokerHolder,
+      AndroidUIScheduler androidUIScheduler);
+
+  public WorkletsModule(ReactApplicationContext reactContext) {
+    super(reactContext);
+    mAndroidUIScheduler = new AndroidUIScheduler(reactContext);
+  }
+
+  @OptIn(markerClass = FrameworkAPI.class)
+  @ReactMethod(isBlockingSynchronousMethod = true)
+  public boolean installTurboModule(String valueUnpackerCode) {
+    var context = getReactApplicationContext();
+    var jsContext = Objects.requireNonNull(context.getJavaScriptContextHolder()).get();
+    var jsCallInvokerHolder = JSCallInvokerResolver.getJSCallInvokerHolder(context);
+
+    mHybridData =
+        initHybrid(
+            jsContext,
+            valueUnpackerCode,
+            mMessageQueueThread,
+            jsCallInvokerHolder,
+            mAndroidUIScheduler);
+    return true;
+  }
+
+  public void invalidate() {
+    // We have to destroy extra runtimes when invalidate is called. If we clean
+    // it up later instead there's a chance the runtime will retain references
+    // to invalidated memory and will crash on its destruction.
+    invalidateCpp();
+
+    mAndroidUIScheduler.deactivate();
+  }
+
+  private native void invalidateCpp();
+}
diff --git a/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java b/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java
index 23066283cbe..6f0f992e4a0 100644
--- a/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java
+++ b/packages/react-native-worklets/android/src/main/java/com/swmansion/worklets/WorkletsPackage.java
@@ -16,14 +16,14 @@
 
 @ReactModuleList(
         nativeModules = {
-          DummyWorkletsModule.class
+          WorkletsModule.class
         })
 public class WorkletsPackage extends BaseReactPackage implements ReactPackage {
   @Override
   public NativeModule getModule(
           @NonNull String name, @NonNull ReactApplicationContext reactContext) {
     return switch (name) {
-      case DummyWorkletsModule.NAME -> new DummyWorkletsModule(reactContext);
+      case WorkletsModule.NAME -> new WorkletsModule(reactContext);
       default -> null;
     };
   }
@@ -32,7 +32,7 @@ public NativeModule getModule(
   public ReactModuleInfoProvider getReactModuleInfoProvider() {
     Class<? extends NativeModule>[] moduleList =
             new Class[] {
-                    DummyWorkletsModule.class
+                    WorkletsModule.class
             };
 
     final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
diff --git a/packages/react-native-reanimated/android/src/worklets/main/com/swmansion/worklets/AndroidUIScheduler.java b/packages/react-native-worklets/android/src/worklets/main/com/swmansion/worklets/AndroidUIScheduler.java
similarity index 100%
rename from packages/react-native-reanimated/android/src/worklets/main/com/swmansion/worklets/AndroidUIScheduler.java
rename to packages/react-native-worklets/android/src/worklets/main/com/swmansion/worklets/AndroidUIScheduler.java
diff --git a/packages/react-native-reanimated/android/src/worklets/main/com/swmansion/worklets/JSCallInvokerResolver.java b/packages/react-native-worklets/android/src/worklets/main/com/swmansion/worklets/JSCallInvokerResolver.java
similarity index 100%
rename from packages/react-native-reanimated/android/src/worklets/main/com/swmansion/worklets/JSCallInvokerResolver.java
rename to packages/react-native-worklets/android/src/worklets/main/com/swmansion/worklets/JSCallInvokerResolver.java
diff --git a/packages/react-native-reanimated/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThread.java b/packages/react-native-worklets/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThread.java
similarity index 100%
rename from packages/react-native-reanimated/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThread.java
rename to packages/react-native-worklets/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThread.java
diff --git a/packages/react-native-reanimated/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java b/packages/react-native-worklets/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java
similarity index 100%
rename from packages/react-native-reanimated/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java
rename to packages/react-native-worklets/android/src/worklets/main/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java
diff --git a/packages/react-native-worklets/android/src/worklets/paper/com/swmansion/worklets/NativeWorkletsModuleSpec.java b/packages/react-native-worklets/android/src/worklets/paper/com/swmansion/worklets/NativeWorkletsModuleSpec.java
new file mode 100644
index 00000000000..fb8be04bbcd
--- /dev/null
+++ b/packages/react-native-worklets/android/src/worklets/paper/com/swmansion/worklets/NativeWorkletsModuleSpec.java
@@ -0,0 +1,26 @@
+package com.swmansion.worklets;
+
+import com.facebook.proguard.annotations.DoNotStrip;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+import com.facebook.react.turbomodule.core.interfaces.TurboModule;
+import javax.annotation.Nonnull;
+
+public abstract class NativeWorkletsModuleSpec extends ReactContextBaseJavaModule
+    implements TurboModule {
+  public static final String NAME = "WorkletsModule";
+
+  public NativeWorkletsModuleSpec(ReactApplicationContext reactContext) {
+    super(reactContext);
+  }
+
+  @Override
+  public @Nonnull String getName() {
+    return NAME;
+  }
+
+  @ReactMethod(isBlockingSynchronousMethod = true)
+  @DoNotStrip
+  public abstract boolean installTurboModule(String valueUnpackerCode);
+}
diff --git a/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.h b/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.h
deleted file mode 100644
index c2a6b079ec7..00000000000
--- a/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#import <rnworklets/rnworklets.h>
-
-@interface DummyWorkletsModule : NSObject <NativeDummyWorkletsSpec>
-
-@end
diff --git a/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.mm b/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.mm
deleted file mode 100644
index 2ba55e07e77..00000000000
--- a/packages/react-native-worklets/apple/worklets/apple/DummyWorkletsModule.mm
+++ /dev/null
@@ -1,19 +0,0 @@
-#import <DummyWorkletsModule.h>
-
-@implementation DummyWorkletsModule{
-  std::string valueUnpackerCode_;
-}
-RCT_EXPORT_MODULE()
-
-- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule :
-    (const facebook::react::ObjCTurboModule::InitParams &)params
-{
-    return std::make_shared<facebook::react::NativeDummyWorkletsSpecJSI>(params);
-}
-
-RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(installTurboModule)
-{
-  return @YES;
-}
-
-@end
diff --git a/packages/react-native-reanimated/apple/worklets/apple/IOSUIScheduler.h b/packages/react-native-worklets/apple/worklets/apple/IOSUIScheduler.h
similarity index 100%
rename from packages/react-native-reanimated/apple/worklets/apple/IOSUIScheduler.h
rename to packages/react-native-worklets/apple/worklets/apple/IOSUIScheduler.h
diff --git a/packages/react-native-reanimated/apple/worklets/apple/IOSUIScheduler.mm b/packages/react-native-worklets/apple/worklets/apple/IOSUIScheduler.mm
similarity index 100%
rename from packages/react-native-reanimated/apple/worklets/apple/IOSUIScheduler.mm
rename to packages/react-native-worklets/apple/worklets/apple/IOSUIScheduler.mm
diff --git a/packages/react-native-reanimated/apple/worklets/apple/PlatformLogger.mm b/packages/react-native-worklets/apple/worklets/apple/PlatformLogger.mm
similarity index 100%
rename from packages/react-native-reanimated/apple/worklets/apple/PlatformLogger.mm
rename to packages/react-native-worklets/apple/worklets/apple/PlatformLogger.mm
diff --git a/packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.h b/packages/react-native-worklets/apple/worklets/apple/WorkletsMessageThread.h
similarity index 100%
rename from packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.h
rename to packages/react-native-worklets/apple/worklets/apple/WorkletsMessageThread.h
diff --git a/packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.mm b/packages/react-native-worklets/apple/worklets/apple/WorkletsMessageThread.mm
similarity index 100%
rename from packages/react-native-reanimated/apple/worklets/apple/WorkletsMessageThread.mm
rename to packages/react-native-worklets/apple/worklets/apple/WorkletsMessageThread.mm
diff --git a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.h b/packages/react-native-worklets/apple/worklets/apple/WorkletsModule.h
similarity index 100%
rename from packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.h
rename to packages/react-native-worklets/apple/worklets/apple/WorkletsModule.h
diff --git a/packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm b/packages/react-native-worklets/apple/worklets/apple/WorkletsModule.mm
similarity index 100%
rename from packages/react-native-reanimated/apple/worklets/apple/WorkletsModule.mm
rename to packages/react-native-worklets/apple/worklets/apple/WorkletsModule.mm
diff --git a/packages/react-native-worklets/package.json b/packages/react-native-worklets/package.json
index 7b84f2f1763..fe84f8eb1ad 100644
--- a/packages/react-native-worklets/package.json
+++ b/packages/react-native-worklets/package.json
@@ -1,7 +1,7 @@
 {
   "name": "react-native-worklets",
   "version": "0.0.1",
-  "description": "🚀",
+  "description": "The React Native multithreading library",
   "scripts": {
     "build": "bob build",
     "format": "yarn format:js",
diff --git a/packages/react-native-worklets/src/index.ts b/packages/react-native-worklets/src/index.ts
index ba2a736031d..f0c2f62f3c9 100644
--- a/packages/react-native-worklets/src/index.ts
+++ b/packages/react-native-worklets/src/index.ts
@@ -1,3 +1,3 @@
 'use strict';
 
-export { DummyWorkletsTurboModule } from './specs';
+export { WorkletsTurboModule } from './specs';
diff --git a/packages/react-native-worklets/src/specs/NativeDummyWorklets.ts b/packages/react-native-worklets/src/specs/NativeWorkletsModule.ts
similarity index 55%
rename from packages/react-native-worklets/src/specs/NativeDummyWorklets.ts
rename to packages/react-native-worklets/src/specs/NativeWorkletsModule.ts
index f59202c88c0..81c6d6906d7 100644
--- a/packages/react-native-worklets/src/specs/NativeDummyWorklets.ts
+++ b/packages/react-native-worklets/src/specs/NativeWorkletsModule.ts
@@ -3,7 +3,7 @@ import type { TurboModule } from 'react-native';
 import { TurboModuleRegistry } from 'react-native';
 
 interface Spec extends TurboModule {
-  installTurboModule: () => boolean;
+  installTurboModule: (valueUnpackerCode: string) => boolean;
 }
 
-export default TurboModuleRegistry.get<Spec>('DummyWorklets');
+export default TurboModuleRegistry.get<Spec>('WorkletsModule');
diff --git a/packages/react-native-worklets/src/specs/index.ts b/packages/react-native-worklets/src/specs/index.ts
index 5b294afa510..2ea1fb2d2e6 100644
--- a/packages/react-native-worklets/src/specs/index.ts
+++ b/packages/react-native-worklets/src/specs/index.ts
@@ -1,5 +1,5 @@
 'use strict';
 
-import DummyWorkletsTurboModule from './NativeDummyWorklets';
+import WorkletsTurboModule from './NativeWorkletsModule';
 
-export { DummyWorkletsTurboModule };
+export { WorkletsTurboModule };