diff --git a/examples/with-nest/README.md b/examples/with-nest/README.md
new file mode 100644
index 0000000..9e5b652
--- /dev/null
+++ b/examples/with-nest/README.md
@@ -0,0 +1,79 @@
+
+
+
+
+[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
+[circleci-url]: https://circleci.com/gh/nestjs/nest
+
+ A progressive Node.js framework for building efficient and scalable server-side applications.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Description
+
+[Nest](https://github.com/nestjs/nest) framework with Reactus and React.
+
+## Project setup
+
+```bash
+$ yarn
+```
+
+## Compile and run the project
+
+```bash
+# development
+$ yarn start
+
+# watch mode (nest start --watch)
+$ yarn start:dev
+
+# production mode
+$ yarn start:prod
+```
+
+## Run tests
+
+```bash
+# unit tests
+$ yarn test
+```
+
+## Resources
+
+Check out a few resources that may come in handy when working with NestJS:
+
+- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework.
+- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy).
+- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/).
+- Deploy your application to AWS with the help of [NestJS Mau](https://mau.nestjs.com) in just a few clicks.
+- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com).
+- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com).
+- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs).
+- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com).
+
+## Support
+
+Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
+
+## Stay in touch
+
+- Author - [Kamil MyĆliwiec](https://twitter.com/kammysliwiec)
+- Website - [https://nestjs.com](https://nestjs.com/)
+- Twitter - [@nestframework](https://twitter.com/nestframework)
+
+## License
+
+Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
diff --git a/examples/with-nest/components/Edit.tsx b/examples/with-nest/components/Edit.tsx
new file mode 100644
index 0000000..5a0c205
--- /dev/null
+++ b/examples/with-nest/components/Edit.tsx
@@ -0,0 +1,9 @@
+import React from 'react'
+
+export default function Edit({ name }: { name: string }) {
+ return (
+
+ Edit pages/{name}.tsx and save to test HMR
+
+ )
+ }
\ No newline at end of file
diff --git a/examples/with-nest/jest.config.mjs b/examples/with-nest/jest.config.mjs
new file mode 100644
index 0000000..bca8be1
--- /dev/null
+++ b/examples/with-nest/jest.config.mjs
@@ -0,0 +1,11 @@
+export default {
+ preset: 'ts-jest/presets/default-esm',
+ testEnvironment: 'node',
+ extensionsToTreatAsEsm: ['.ts'],
+ transform: {
+ '^.+\\.ts$': ['ts-jest', { useESM: true }]
+ },
+ moduleNameMapper: {
+ '^(\\.{1,2}/.*)\\.js$': '$1'
+ }
+};
diff --git a/examples/with-nest/nest-cli.json b/examples/with-nest/nest-cli.json
new file mode 100644
index 0000000..f9aa683
--- /dev/null
+++ b/examples/with-nest/nest-cli.json
@@ -0,0 +1,8 @@
+{
+ "$schema": "https://json.schemastore.org/nest-cli",
+ "collection": "@nestjs/schematics",
+ "sourceRoot": "src",
+ "compilerOptions": {
+ "deleteOutDir": true
+ }
+}
diff --git a/examples/with-nest/package.json b/examples/with-nest/package.json
new file mode 100644
index 0000000..9934a3a
--- /dev/null
+++ b/examples/with-nest/package.json
@@ -0,0 +1,71 @@
+{
+ "name": "reactus-with-nest",
+ "version": "1.0.0",
+ "private": true,
+ "license": "UNLICENSED",
+ "type": "module",
+ "scripts": {
+ "build": "tsx scripts/build.ts",
+ "start": "nest start",
+ "start:dev": "nest start --watch",
+ "start:debug": "nest start --debug --watch",
+ "start:prod": "NODE_ENV=production nest start --prod",
+ "test": "jest --config jest.config.mjs",
+ "test:watch": "jest --watch",
+ "test:cov": "jest --coverage",
+ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
+ "test:e2e": "jest --config ./test/jest-e2e.json"
+ },
+ "dependencies": {
+ "@nestjs/common": "^11.0.1",
+ "@nestjs/core": "^11.0.1",
+ "@nestjs/platform-express": "^11.0.1",
+ "react": "^19.1.0",
+ "react-dom": "^19.1.0",
+ "reactus": "^0.2.10",
+ "reflect-metadata": "^0.2.2",
+ "rxjs": "^7.8.1"
+ },
+ "devDependencies": {
+ "@nestjs/cli": "^11.0.0",
+ "@nestjs/schematics": "^11.0.0",
+ "@nestjs/testing": "^11.0.1",
+ "@swc/cli": "^0.6.0",
+ "@swc/core": "^1.10.7",
+ "@types/express": "^5.0.0",
+ "@types/jest": "^29.5.14",
+ "@types/node": "^22.15.3",
+ "@types/react": "^19.1.2",
+ "@types/react-dom": "^19.1.3",
+ "@types/supertest": "^6.0.2",
+ "@vitejs/plugin-react": "^4.4.1",
+ "globals": "^16.0.0",
+ "jest": "^29.7.0",
+ "source-map-support": "^0.5.21",
+ "supertest": "^7.0.0",
+ "ts-jest": "^29.2.5",
+ "ts-loader": "^9.5.2",
+ "ts-node": "^10.9.2",
+ "tsconfig-paths": "^4.2.0",
+ "tsx": "^4.19.4",
+ "typescript": "^5.8.3",
+ "vite": "^6.3.4"
+ },
+ "jest": {
+ "moduleFileExtensions": [
+ "js",
+ "json",
+ "ts"
+ ],
+ "rootDir": "src",
+ "testRegex": ".*\\.spec\\.ts$",
+ "transform": {
+ "^.+\\.(t|j)s$": "ts-jest"
+ },
+ "collectCoverageFrom": [
+ "**/*.(t|j)s"
+ ],
+ "coverageDirectory": "../coverage",
+ "testEnvironment": "node"
+ }
+}
diff --git a/examples/with-nest/pages/about.tsx b/examples/with-nest/pages/about.tsx
new file mode 100644
index 0000000..f7aecb8
--- /dev/null
+++ b/examples/with-nest/pages/about.tsx
@@ -0,0 +1,29 @@
+import './page.css';
+import React from 'react';
+import Edit from '../components/Edit.js';
+
+export function Head({ styles = [] }: { styles?: string[] }) {
+ return (
+ <>
+ About Reactus
+
+
+
+ {styles.map((href, index) => (
+
+ ))}
+ >
+ )
+}
+
+export default function AboutPage() {
+ return (
+ <>
+ About Reactus
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/examples/with-nest/pages/home.tsx b/examples/with-nest/pages/home.tsx
new file mode 100644
index 0000000..9708233
--- /dev/null
+++ b/examples/with-nest/pages/home.tsx
@@ -0,0 +1,34 @@
+import './page.css';
+import React, { useState } from 'react';
+import Edit from '../components/Edit.js';
+
+export function Head({ styles = [] }: { styles?: string[] }) {
+ return (
+ <>
+ Reactus
+
+
+
+ {styles.map((href, index) => (
+
+ ))}
+ >
+ )
+}
+
+export default function HomePage() {
+ const [count, setCount] = useState(0)
+
+ return (
+ <>
+ React + Reactus with NestJS!
+
+
setCount((count) => count + 1)}>
+ count is {count}
+
+
+
About Reactus
+
+ >
+ )
+}
\ No newline at end of file
diff --git a/examples/with-nest/pages/page.css b/examples/with-nest/pages/page.css
new file mode 100644
index 0000000..30e8b0c
--- /dev/null
+++ b/examples/with-nest/pages/page.css
@@ -0,0 +1,7 @@
+:root { display: initial; }
+#root {
+ max-width: 1280px;
+ margin: 0 auto;
+ padding: 2rem;
+ text-align: center;
+}
\ No newline at end of file
diff --git a/examples/with-nest/public/global.css b/examples/with-nest/public/global.css
new file mode 100644
index 0000000..bcf1636
--- /dev/null
+++ b/examples/with-nest/public/global.css
@@ -0,0 +1,70 @@
+:root {
+ display: none;
+ font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+ font-weight: 400;
+
+ color-scheme: light dark;
+ color: rgba(255, 255, 255, 0.87);
+ background-color: #242424;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ -webkit-text-size-adjust: 100%;
+}
+
+a {
+ font-weight: 500;
+ color: #646cff;
+ text-decoration: inherit;
+}
+a:hover {
+ color: #535bf2;
+}
+
+body {
+ margin: 0;
+ display: flex;
+ place-items: center;
+ min-width: 320px;
+ min-height: 100vh;
+}
+
+h1 {
+ font-size: 3.2em;
+ line-height: 1.1;
+}
+
+button {
+ border-radius: 8px;
+ border: 1px solid transparent;
+ padding: 0.6em 1.2em;
+ font-size: 1em;
+ font-weight: 500;
+ font-family: inherit;
+ background-color: #1a1a1a;
+ cursor: pointer;
+ transition: border-color 0.25s;
+}
+button:hover {
+ border-color: #646cff;
+}
+button:focus,
+button:focus-visible {
+ outline: 4px auto -webkit-focus-ring-color;
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ color: #213547;
+ background-color: #ffffff;
+ }
+ a:hover {
+ color: #747bff;
+ }
+ button {
+ background-color: #f9f9f9;
+ }
+}
\ No newline at end of file
diff --git a/examples/with-nest/scripts/build.ts b/examples/with-nest/scripts/build.ts
new file mode 100644
index 0000000..aa109d4
--- /dev/null
+++ b/examples/with-nest/scripts/build.ts
@@ -0,0 +1,41 @@
+//node
+import path from 'node:path';
+//reactus
+import { build } from 'reactus';
+
+async function builder() {
+ const cwd = process.cwd();
+ const engine = build({
+ cwd,
+ //path where to save assets (css, images, etc)
+ assetPath: path.join(cwd, 'public/assets'),
+ //path where to save and load (live) the client scripts (js)
+ clientPath: path.join(cwd, 'public/client'),
+ //path where to save and load (live) the server script (js)
+ pagePath: path.join(cwd, '.build/pages')
+ });
+
+ await engine.set('@/pages/home');
+ await engine.set('@/pages/about');
+
+ const responses = [
+ ...await engine.buildAllClients(),
+ ...await engine.buildAllAssets(),
+ ...await engine.buildAllPages()
+ ].map(response => {
+ const results = response.results;
+ if (typeof results?.contents === 'string') {
+ results.contents = results.contents.substring(0, 100) + ' ...';
+ }
+ return results;
+ });
+
+ //console.log(responses);
+ //fix for unused variable :)
+ if (responses.length) return;
+}
+
+builder().catch(e => {
+ console.error(e);
+ process.exit(1);
+});
\ No newline at end of file
diff --git a/examples/with-nest/src/app.controller.spec.ts b/examples/with-nest/src/app.controller.spec.ts
new file mode 100644
index 0000000..676cc6c
--- /dev/null
+++ b/examples/with-nest/src/app.controller.spec.ts
@@ -0,0 +1,59 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { AppController } from './app.controller.js';
+import { AppService } from './app.service.js';
+import { ReactusService } from './reactus/reactus.service.js';
+import { Response } from 'express'
+
+describe('AppController', () => {
+ let appController: AppController;
+ let reactusServiceMock: Partial;
+
+ beforeEach(async () => {
+ reactusServiceMock = {
+ render: jest.fn().mockResolvedValue('Mocked Page'),
+ };
+
+ const app: TestingModule = await Test.createTestingModule({
+ controllers: [AppController],
+ providers: [
+ AppService,
+ {
+ provide: ReactusService,
+ useValue: reactusServiceMock,
+ },
+ ],
+ }).compile();
+
+ appController = app.get(AppController);
+ });
+
+ it('should be defined', () => {
+ expect(appController).toBeDefined();
+ });
+
+ it('should render the home page', async () => {
+ const res = {
+ setHeader: jest.fn(),
+ end: jest.fn(),
+ } as unknown as Response;
+
+ await appController.home(res);
+
+ expect(reactusServiceMock.render).toHaveBeenCalledWith('@/pages/home', { title: 'Home' });
+ expect(res.setHeader).toHaveBeenCalledWith('Content-Type', 'text/html');
+ expect(res.end).toHaveBeenCalledWith('Mocked Page');
+ });
+
+ it('should render the about page', async () => {
+ const res = {
+ setHeader: jest.fn(),
+ end: jest.fn(),
+ } as unknown as Response;
+
+ await appController.about(res);
+
+ expect(reactusServiceMock.render).toHaveBeenCalledWith('@/pages/about', { title: 'About' });
+ expect(res.setHeader).toHaveBeenCalledWith('Content-Type', 'text/html');
+ expect(res.end).toHaveBeenCalledWith('Mocked Page');
+ });
+});
diff --git a/examples/with-nest/src/app.controller.ts b/examples/with-nest/src/app.controller.ts
new file mode 100644
index 0000000..bf2535d
--- /dev/null
+++ b/examples/with-nest/src/app.controller.ts
@@ -0,0 +1,25 @@
+import { Controller, Get, Res } from '@nestjs/common';
+import { ReactusService } from './reactus/reactus.service.js';
+import { Response } from 'express';
+
+@Controller()
+export class AppController {
+ constructor(private readonly reactusService: ReactusService) {}
+
+ @Get('/')
+ async home(@Res() res: Response) {
+ res.setHeader('Content-Type', 'text/html');
+ const html = await this.reactusService.render('@/pages/home', {
+ title: 'Home',
+ });
+ res.end(html);
+ }
+ @Get('/about')
+ async about(@Res() res: Response) {
+ res.setHeader('Content-Type', 'text/html');
+ const html = await this.reactusService.render('@/pages/about', {
+ title: 'About',
+ });
+ res.end(html);
+ }
+}
diff --git a/examples/with-nest/src/app.module.ts b/examples/with-nest/src/app.module.ts
new file mode 100644
index 0000000..e218222
--- /dev/null
+++ b/examples/with-nest/src/app.module.ts
@@ -0,0 +1,11 @@
+import { Module } from '@nestjs/common';
+import { AppController } from './app.controller.js';
+import { AppService } from './app.service.js';
+import { ReactusService } from './reactus/reactus.service.js';
+
+@Module({
+ imports: [],
+ controllers: [AppController],
+ providers: [AppService, ReactusService],
+})
+export class AppModule {}
diff --git a/examples/with-nest/src/app.service.ts b/examples/with-nest/src/app.service.ts
new file mode 100644
index 0000000..927d7cc
--- /dev/null
+++ b/examples/with-nest/src/app.service.ts
@@ -0,0 +1,8 @@
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class AppService {
+ getHello(): string {
+ return 'Hello World!';
+ }
+}
diff --git a/examples/with-nest/src/main.ts b/examples/with-nest/src/main.ts
new file mode 100644
index 0000000..9980097
--- /dev/null
+++ b/examples/with-nest/src/main.ts
@@ -0,0 +1,47 @@
+import { NestFactory } from '@nestjs/core';
+import { AppModule } from './app.module.js';
+import { NestExpressApplication } from '@nestjs/platform-express';
+import { ReactusService } from './reactus/reactus.service.js';
+import { join } from 'path';
+import sirv from 'sirv';
+
+async function bootstrap() {
+ const app = await NestFactory.create(AppModule);
+ const express = app.getHttpAdapter().getInstance();
+ const cwd = process.cwd();
+
+ const reactusService = app.get(ReactusService);
+
+ // Serve static assets in production
+ if (process.env.NODE_ENV === 'production') {
+ express.use(
+ '/client',
+ sirv(join(cwd, 'public/client'), { maxAge: 31536000, immutable: true })
+ );
+ express.use(
+ '/assets',
+ sirv(join(cwd, 'public/assets'), { maxAge: 31536000, immutable: true })
+ );
+ express.use(
+ '/public',
+ sirv(join(cwd, 'public'), { maxAge: 31536000, immutable: true })
+ );
+ }
+
+ // In dev mode, use the Reactus service for rendering and asset handling
+ express.use(async (req, res, next) => {
+ if (process.env.NODE_ENV !== 'production') {
+ // Handle assets and rendering in dev mode
+ await reactusService.handleAssets(req, res);
+ }
+ if (!res.headersSent) next();
+ });
+
+ await app.listen(process.env.PORT ?? 3000);
+ console.log(`Server is listening at http://localhost:${process.env.PORT ?? 3000}`);
+}
+
+bootstrap().catch((e) => {
+ console.error(e);
+ process.exit(1);
+});
diff --git a/examples/with-nest/src/reactus/reactus.service.spec.ts b/examples/with-nest/src/reactus/reactus.service.spec.ts
new file mode 100644
index 0000000..74f40b1
--- /dev/null
+++ b/examples/with-nest/src/reactus/reactus.service.spec.ts
@@ -0,0 +1,18 @@
+import { Test, TestingModule } from '@nestjs/testing';
+import { ReactusService } from './reactus.service.js';
+
+describe('ReactusService', () => {
+ let service: ReactusService;
+
+ beforeEach(async () => {
+ const module: TestingModule = await Test.createTestingModule({
+ providers: [ReactusService],
+ }).compile();
+
+ service = module.get(ReactusService);
+ });
+
+ it('should be defined', () => {
+ expect(service).toBeDefined();
+ });
+});
diff --git a/examples/with-nest/src/reactus/reactus.service.ts b/examples/with-nest/src/reactus/reactus.service.ts
new file mode 100644
index 0000000..0966eff
--- /dev/null
+++ b/examples/with-nest/src/reactus/reactus.service.ts
@@ -0,0 +1,39 @@
+import { Injectable } from '@nestjs/common';
+import { IncomingMessage } from 'http';
+import { dev, serve } from 'reactus';
+import { SR } from 'reactus/types';
+import path from 'path';
+
+@Injectable()
+export class ReactusService {
+ private readonly engine:
+ | ReturnType
+ | ReturnType;
+
+ private readonly isDev = process.env.NODE_ENV !== 'production';
+
+ constructor() {
+ const cwd = process.cwd();
+
+ if (this.isDev) {
+ this.engine = dev({ cwd });
+ } else {
+ this.engine = serve({
+ cwd,
+ clientRoute: '/client',
+ pagePath: path.join(cwd, '.build/pages'),
+ cssRoute: '/assets',
+ });
+ }
+ }
+
+ async render(path: string, props: Record = {}): Promise {
+ return this.engine.render(path, props);
+ }
+
+ async handleAssets(req: IncomingMessage, res: SR) {
+ if (this.isDev && 'http' in this.engine) {
+ await this.engine.http(req, res);
+ }
+ }
+}
diff --git a/examples/with-nest/tsconfig.build.json b/examples/with-nest/tsconfig.build.json
new file mode 100644
index 0000000..64f86c6
--- /dev/null
+++ b/examples/with-nest/tsconfig.build.json
@@ -0,0 +1,4 @@
+{
+ "extends": "./tsconfig.json",
+ "exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
+}
diff --git a/examples/with-nest/tsconfig.json b/examples/with-nest/tsconfig.json
new file mode 100644
index 0000000..a55bde1
--- /dev/null
+++ b/examples/with-nest/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "jsx": "react",
+ "module": "nodenext",
+ "moduleResolution": "nodenext",
+ "declaration": true,
+ "removeComments": true,
+ "emitDecoratorMetadata": true,
+ "experimentalDecorators": true,
+ "allowSyntheticDefaultImports": true,
+ "target": "ES2023",
+ "sourceMap": true,
+ "outDir": "./dist",
+ "baseUrl": "./",
+ "incremental": true,
+ "skipLibCheck": true,
+ "strictNullChecks": true,
+ "forceConsistentCasingInFileNames": true,
+ "noImplicitAny": false,
+ "strictBindCallApply": false,
+ "noFallthroughCasesInSwitch": false
+ }
+ }
+
\ No newline at end of file
diff --git a/package.json b/package.json
index 6479e14..618c0b7 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"fastify": "yarn --cwd examples/with-fastify",
"hapi": "yarn --cwd examples/with-hapi",
"http": "yarn --cwd examples/with-http",
+ "nest": "yarn --cwd examples/with-nest",
"restify": "yarn --cwd examples/with-restify",
"tailwind": "yarn --cwd examples/with-tailwind",
"unocss": "yarn --cwd examples/with-unocss",