chore(repo): restructure as monorepo with server and client workspaces

- move NestJS app into server/ subdirectory
- add client/ React+TypeScript (Vite) app with Hello World
- update docker-compose to build and run both services
- add root package.json declaring npm workspaces
- update .gitignore to cover node_modules and dist at all depths
This commit is contained in:
2026-04-08 21:28:01 +03:00
parent afc4627353
commit 5cc16725fb
88 changed files with 12637 additions and 405 deletions
+10 -3
View File
@@ -1,6 +1,13 @@
# runtime / secrets
/keys
/node_modules
/dist
/data
.env
/*.log
*.log
# dependencies
node_modules/
# build outputs
/dist
server/dist
client/dist
+8
View File
@@ -0,0 +1,8 @@
node_modules
client/node_modules
client/dist
server
data
keys
.env
*.log
+19
View File
@@ -0,0 +1,19 @@
# ── Build stage ───────────────────────────────────────────────────────────────
FROM node:22-slim AS builder
WORKDIR /app
# Copy root lockfile + workspace manifests so npm ci can resolve the full graph
COPY package*.json ./
COPY client/package.json ./client/
RUN npm ci -w client
COPY client ./client
RUN npm run -w client build
# ── Runtime stage ─────────────────────────────────────────────────────────────
FROM nginx:alpine AS runtime
COPY --from=builder /app/client/dist /usr/share/nginx/html
EXPOSE 80
+12
View File
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Liquio QA Bot</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
+22
View File
@@ -0,0 +1,22 @@
{
"name": "liquio-qa-bot-client",
"version": "0.0.1",
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"preview": "vite preview"
},
"dependencies": {
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
"devDependencies": {
"@types/react": "^19.1.2",
"@types/react-dom": "^19.1.2",
"@vitejs/plugin-react": "^4.4.1",
"typescript": "~5.8.3",
"vite": "^6.3.1"
}
}
+3
View File
@@ -0,0 +1,3 @@
export default function App() {
return <h1>Hello World</h1>
}
+9
View File
@@ -0,0 +1,9 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)
+17
View File
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
"strict": true
},
"include": ["src"]
}
+1
View File
@@ -0,0 +1 @@
{"root":["./src/App.tsx","./src/main.tsx"],"version":"5.8.3"}
+6
View File
@@ -0,0 +1,6 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
})
+10 -2
View File
@@ -1,7 +1,7 @@
services:
app:
server:
build:
context: .
context: ./server
dockerfile: Dockerfile
ports:
- "13000:3000"
@@ -13,3 +13,11 @@ services:
# mount key files into the container
- ./keys:/app/keys
restart: unless-stopped
client:
build:
context: .
dockerfile: client/Dockerfile
ports:
- "13001:80"
restart: unless-stopped
+1210 -338
View File
File diff suppressed because it is too large Load Diff
+6 -62
View File
@@ -1,65 +1,9 @@
{
"name": "liquio-qa-bot",
"version": "1.2.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "nest build",
"start": "nest start",
"start:dev": "nest start --watch",
"start:prod": "node dist/main",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
"lint:fix": "eslint --fix \"src/**/*.ts\" \"test/**/*.ts\"",
"test": "jest",
"test:debug": "DEBUG=test jest",
"test:watch": "jest --watch"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.29.0",
"@mozilla/readability": "^0.6.0",
"@nestjs/common": "^11.1.18",
"@nestjs/config": "^4.0.3",
"@nestjs/core": "^11.1.18",
"@nestjs/platform-express": "^11.1.18",
"@nestjs/schedule": "^6.1.1",
"@nestjs/swagger": "^11.2.6",
"@nestjs/typeorm": "^11.0.1",
"acorn": "^8.16.0",
"better-sqlite3": "^12.8.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.4",
"jsdom": "^29.0.2",
"playwright": "^1.59.1",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.2",
"swagger-ui-express": "^5.0.1",
"typeorm": "^0.3.28",
"zod": "^4.3.6"
},
"devDependencies": {
"@nestjs/cli": "^11.0.17",
"@nestjs/testing": "^11.1.18",
"@types/acorn": "^4.0.6",
"@types/better-sqlite3": "^7.6.13",
"@types/debug": "^4.1.13",
"@types/express": "^5.0.6",
"@types/jest": "^30.0.0",
"@types/jsdom": "^28.0.1",
"@types/mozilla__readability": "^0.4.2",
"@types/node": "^25.5.2",
"@types/supertest": "^7.2.0",
"debug": "^4.4.3",
"eslint": "^10.2.0",
"eslint-config-prettier": "^10.1.8",
"jest": "^30.3.0",
"prettier": "^3.8.1",
"supertest": "^7.2.2",
"ts-jest": "^29.4.9",
"typescript": "^6.0.2",
"typescript-eslint": "^8.58.1"
}
"version": "1.0.0",
"private": true,
"workspaces": [
"server",
"client"
]
}
View File
+11239
View File
File diff suppressed because it is too large Load Diff
+65
View File
@@ -0,0 +1,65 @@
{
"name": "liquio-qa-bot",
"version": "1.2.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "nest build",
"start": "nest start",
"start:dev": "nest start --watch",
"start:prod": "node dist/main",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
"lint:fix": "eslint --fix \"src/**/*.ts\" \"test/**/*.ts\"",
"test": "jest",
"test:debug": "DEBUG=test jest",
"test:watch": "jest --watch"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.29.0",
"@mozilla/readability": "^0.6.0",
"@nestjs/common": "^11.1.18",
"@nestjs/config": "^4.0.3",
"@nestjs/core": "^11.1.18",
"@nestjs/platform-express": "^11.1.18",
"@nestjs/schedule": "^6.1.1",
"@nestjs/swagger": "^11.2.6",
"@nestjs/typeorm": "^11.0.1",
"acorn": "^8.16.0",
"better-sqlite3": "^12.8.0",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.4",
"jsdom": "^29.0.2",
"playwright": "^1.59.1",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.2",
"swagger-ui-express": "^5.0.1",
"typeorm": "^0.3.28",
"zod": "^4.3.6"
},
"devDependencies": {
"@nestjs/cli": "^11.0.17",
"@nestjs/testing": "^11.1.18",
"@types/acorn": "^4.0.6",
"@types/better-sqlite3": "^7.6.13",
"@types/debug": "^4.1.13",
"@types/express": "^5.0.6",
"@types/jest": "^30.0.0",
"@types/jsdom": "^28.0.1",
"@types/mozilla__readability": "^0.4.2",
"@types/node": "^25.5.2",
"@types/supertest": "^7.2.0",
"debug": "^4.4.3",
"eslint": "^10.2.0",
"eslint-config-prettier": "^10.1.8",
"jest": "^30.3.0",
"prettier": "^3.8.1",
"supertest": "^7.2.2",
"ts-jest": "^29.4.9",
"typescript": "^6.0.2",
"typescript-eslint": "^8.58.1"
}
}
View File