diff --git a/packages/background-only/README.md b/packages/background-only/README.md
new file mode 100644
index 0000000000..960dd8190f
--- /dev/null
+++ b/packages/background-only/README.md
@@ -0,0 +1,60 @@
+# background-only
+
+This package serves as a mark package to enforce and mark modules that should only be used in the Background Thread context. It provides type definitions and runtime checks to ensure proper usage.
+
+## Example Usages
+
+Say we have a `Logger` module that has side effects calling into Native Modules or other APIs that are only available in the "Background" environment:
+
+```tsx
+// Logger.js
+import "background-only";
+
+export function log(msg) {
+ // Notice how we are calling into NativeModules here.
+ NativeModules.hybridMonitor.reportJSError(...);
+}
+```
+
+By adding `import "background-only"` to poison this module, we are now declaring that this module is only safe to be bundled in a "Background" environment, protecting this module from being accidentally bundled into a "Main thread" environment by throwing an error at runtime.
+
+For example, if we use `log` in a desirable position from a React component, such as in `useEffect` or an event handler, the `log` will work as expected:
+
+```tsx
+// App.jsx
+import { log } from "./Logger";
+
+function App() {
+ useEffect() {
+ log();
+ }
+ return
+}
+```
+
+However, if we use `log` in a undesirable position from a React component, such as in the body of the rendering function, it will throw an error at runtime time:
+
+```tsx
+// App.jsx
+import { log } from './Logger';
+
+function App() {
+ // throw!
+ log();
+ return ;
+}
+```
+
+## Development Note
+
+This package is already in its final form and does not require build or test steps. The files are simple enough to be used as-is.
+
+The package consists of three files in their final form:
+
+- `error.js` - Throws an error when imported in the wrong context
+- `empty.js` - An empty module for the default export
+- `index.d.ts` - TypeScript type definitions (empty)
+
+## Credits
+
+This is inspired by the [`server-only`](https://www.npmjs.com/package/server-only?activeTab=readme) package of React.
diff --git a/packages/background-only/empty.js b/packages/background-only/empty.js
new file mode 100644
index 0000000000..fce7161576
--- /dev/null
+++ b/packages/background-only/empty.js
@@ -0,0 +1,3 @@
+// Copyright 2024 The Lynx Authors. All rights reserved.
+// Licensed under the Apache License Version 2.0 that can be found in the
+// LICENSE file in the root directory of this source tree.
diff --git a/packages/background-only/error.js b/packages/background-only/error.js
new file mode 100644
index 0000000000..e5aab846f0
--- /dev/null
+++ b/packages/background-only/error.js
@@ -0,0 +1,7 @@
+// Copyright 2024 The Lynx Authors. All rights reserved.
+// Licensed under the Apache License Version 2.0 that can be found in the
+// LICENSE file in the root directory of this source tree.
+throw new Error(
+ 'This module cannot be imported from a Main Thread module. '
+ + 'It should only be used from a Background Thread.',
+);
diff --git a/packages/background-only/index.d.ts b/packages/background-only/index.d.ts
new file mode 100644
index 0000000000..b8b9548e32
--- /dev/null
+++ b/packages/background-only/index.d.ts
@@ -0,0 +1,4 @@
+// Copyright 2024 The Lynx Authors. All rights reserved.
+// Licensed under the Apache License Version 2.0 that can be found in the
+// LICENSE file in the root directory of this source tree.
+export {};
diff --git a/packages/background-only/package.json b/packages/background-only/package.json
new file mode 100644
index 0000000000..a4d2d7fc9b
--- /dev/null
+++ b/packages/background-only/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "background-only",
+ "version": "0.0.1",
+ "description": "This is a marker package to indicate that a module can only be used in the Background Thread.",
+ "keywords": [
+ "react",
+ "lynx"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/lynx-family/lynx-stack.git",
+ "directory": "packages/background-only"
+ },
+ "license": "MIT",
+ "type": "module",
+ "exports": {
+ ".": {
+ "lepus": {
+ "types": "./index.d.ts",
+ "default": "./error.js"
+ },
+ "default": {
+ "types": "./index.d.ts",
+ "default": "./empty.js"
+ }
+ }
+ },
+ "main": "empty.js",
+ "types": "index.d.ts",
+ "files": [
+ "error.js",
+ "empty.js",
+ "index.d.ts"
+ ]
+}
diff --git a/packages/background-only/tsconfig.json b/packages/background-only/tsconfig.json
new file mode 100644
index 0000000000..513e2b12f8
--- /dev/null
+++ b/packages/background-only/tsconfig.json
@@ -0,0 +1,12 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./dist",
+ "rootDir": ".",
+ "composite": true,
+ },
+ "include": [
+ "*.ts",
+ "*.d.ts",
+ ],
+}
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index c48861104d..edc3dad9fb 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -14,6 +14,7 @@ packages:
- packages/third-party/*
- packages/testing-library/*
- packages/testing-library/examples/*
+ - packages/background-only
- "!packages/testing-library/examples"
- website
diff --git a/tsconfig.json b/tsconfig.json
index b1ed85ed15..02fbf24466 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -124,7 +124,7 @@
},
{
"path": "./packages/third-party"
- },
+ }
],
"include": []
}