From b0589978892345b67e3a3950e87cb86ba7eb7c0d Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Sat, 21 Mar 2026 19:52:57 +0100 Subject: [PATCH] refactor: restructure to monorepo with npm workspaces (Phase 0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move frontend to packages/client/, server to packages/server/. Root package.json uses npm workspaces to orchestrate both. Structure: reaktor/ packages/client/ (React + Vite + Tone.js frontend) packages/server/ (static file server, future API) dist/ (built output, shared) docker-compose.yml (app + PostgreSQL for future backend) - npm run dev → runs Vite dev server from client workspace - npm run build → builds client, outputs to root dist/ - npm run start → runs server.js serving dist/ - Dockerfile updated for multi-stage monorepo build - docker-compose.yml added with PostgreSQL service (ready for Phase 1) - All imports and paths preserved, zero functionality change Co-Authored-By: Claude Opus 4.6 (1M context) --- Dockerfile | 10 +++-- docker-compose.yml | 24 ++++++++++ package-lock.json | 42 +++++++++++++----- package.json | 21 +++------ index.html => packages/client/index.html | 0 packages/client/package.json | 20 +++++++++ .../client/public}/favicon.svg | 0 .../client/public}/icon-192.png | Bin .../client/public}/icon-512.png | Bin .../client/public}/manifest.json | 0 {public => packages/client/public}/sw.js | 0 {src => packages/client/src}/App.jsx | 0 .../client/src}/components/BottomSheet.jsx | 0 .../client/src}/components/DrumPadWidget.jsx | 0 .../client/src}/components/KeyboardWidget.jsx | 0 .../client/src}/components/Knob.jsx | 0 .../client/src}/components/MobileTabBar.jsx | 0 .../client/src}/components/ModuleNode.jsx | 0 .../client/src}/components/ModulePalette.jsx | 0 .../src}/components/PianoRollWidget.jsx | 0 .../client/src}/components/PresetModal.jsx | 0 .../client/src}/components/ScopeDisplay.jsx | 0 .../src}/components/SequencerWidget.jsx | 0 .../client/src}/components/WireLayer.jsx | 0 .../client/src}/engine/audioEngine.js | 0 .../client/src}/engine/moduleRegistry.js | 0 .../client/src}/engine/presets.js | 0 {src => packages/client/src}/engine/state.js | 0 .../client/src}/engine/uiSounds.js | 0 .../client/src}/game/AdminPanel.jsx | 0 {src => packages/client/src}/game/GameApp.jsx | 0 .../client/src}/game/LevelComplete.jsx | 0 .../client/src}/game/PuzzleView.jsx | 0 .../client/src}/game/WorldMap.jsx | 0 .../client/src}/game/autoSolver.js | 0 .../client/src}/game/gameState.js | 0 .../client/src}/game/levels/world1.js | 0 .../client/src}/game/levels/world10.js | 0 .../client/src}/game/levels/world11.js | 0 .../client/src}/game/levels/world12.js | 0 .../client/src}/game/levels/world2.js | 0 .../client/src}/game/levels/world3.js | 0 .../client/src}/game/levels/world4.js | 0 .../client/src}/game/levels/world5.js | 0 .../client/src}/game/levels/world6.js | 0 .../client/src}/game/levels/world7.js | 0 .../client/src}/game/levels/world8.js | 0 .../client/src}/game/levels/world9.js | 0 .../client/src}/game/targetAudio.js | 0 .../client/src}/hooks/useIsMobile.js | 0 .../client/src}/hooks/usePinchZoom.js | 0 {src => packages/client/src}/index.css | 0 {src => packages/client/src}/main.jsx | 0 .../client/src}/presets/chiptune.js | 0 {src => packages/client/src}/utils/bezier.js | 0 .../client/src}/utils/midiParser.js | 0 .../client/vite.config.js | 2 +- packages/server/package.json | 8 ++++ server.js => packages/server/server.js | 2 +- 59 files changed, 96 insertions(+), 33 deletions(-) create mode 100644 docker-compose.yml rename index.html => packages/client/index.html (100%) create mode 100644 packages/client/package.json rename {public => packages/client/public}/favicon.svg (100%) rename {public => packages/client/public}/icon-192.png (100%) rename {public => packages/client/public}/icon-512.png (100%) rename {public => packages/client/public}/manifest.json (100%) rename {public => packages/client/public}/sw.js (100%) rename {src => packages/client/src}/App.jsx (100%) rename {src => packages/client/src}/components/BottomSheet.jsx (100%) rename {src => packages/client/src}/components/DrumPadWidget.jsx (100%) rename {src => packages/client/src}/components/KeyboardWidget.jsx (100%) rename {src => packages/client/src}/components/Knob.jsx (100%) rename {src => packages/client/src}/components/MobileTabBar.jsx (100%) rename {src => packages/client/src}/components/ModuleNode.jsx (100%) rename {src => packages/client/src}/components/ModulePalette.jsx (100%) rename {src => packages/client/src}/components/PianoRollWidget.jsx (100%) rename {src => packages/client/src}/components/PresetModal.jsx (100%) rename {src => packages/client/src}/components/ScopeDisplay.jsx (100%) rename {src => packages/client/src}/components/SequencerWidget.jsx (100%) rename {src => packages/client/src}/components/WireLayer.jsx (100%) rename {src => packages/client/src}/engine/audioEngine.js (100%) rename {src => packages/client/src}/engine/moduleRegistry.js (100%) rename {src => packages/client/src}/engine/presets.js (100%) rename {src => packages/client/src}/engine/state.js (100%) rename {src => packages/client/src}/engine/uiSounds.js (100%) rename {src => packages/client/src}/game/AdminPanel.jsx (100%) rename {src => packages/client/src}/game/GameApp.jsx (100%) rename {src => packages/client/src}/game/LevelComplete.jsx (100%) rename {src => packages/client/src}/game/PuzzleView.jsx (100%) rename {src => packages/client/src}/game/WorldMap.jsx (100%) rename {src => packages/client/src}/game/autoSolver.js (100%) rename {src => packages/client/src}/game/gameState.js (100%) rename {src => packages/client/src}/game/levels/world1.js (100%) rename {src => packages/client/src}/game/levels/world10.js (100%) rename {src => packages/client/src}/game/levels/world11.js (100%) rename {src => packages/client/src}/game/levels/world12.js (100%) rename {src => packages/client/src}/game/levels/world2.js (100%) rename {src => packages/client/src}/game/levels/world3.js (100%) rename {src => packages/client/src}/game/levels/world4.js (100%) rename {src => packages/client/src}/game/levels/world5.js (100%) rename {src => packages/client/src}/game/levels/world6.js (100%) rename {src => packages/client/src}/game/levels/world7.js (100%) rename {src => packages/client/src}/game/levels/world8.js (100%) rename {src => packages/client/src}/game/levels/world9.js (100%) rename {src => packages/client/src}/game/targetAudio.js (100%) rename {src => packages/client/src}/hooks/useIsMobile.js (100%) rename {src => packages/client/src}/hooks/usePinchZoom.js (100%) rename {src => packages/client/src}/index.css (100%) rename {src => packages/client/src}/main.jsx (100%) rename {src => packages/client/src}/presets/chiptune.js (100%) rename {src => packages/client/src}/utils/bezier.js (100%) rename {src => packages/client/src}/utils/midiParser.js (100%) rename vite.config.js => packages/client/vite.config.js (75%) create mode 100644 packages/server/package.json rename server.js => packages/server/server.js (96%) diff --git a/Dockerfile b/Dockerfile index 112bd6e..6c4afd8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,17 @@ FROM node:20-alpine AS build WORKDIR /app COPY package.json package-lock.json* ./ +COPY packages/client/package.json packages/client/ +COPY packages/server/package.json packages/server/ RUN npm install -COPY . . +COPY packages/client packages/client RUN npm run build FROM node:20-alpine WORKDIR /app COPY --from=build /app/dist ./dist -COPY server.js . +COPY packages/server/server.js ./packages/server/server.js +COPY packages/server/package.json ./packages/server/package.json +COPY package.json ./ EXPOSE 80 -CMD ["node", "server.js"] +CMD ["node", "packages/server/server.js"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..aa9a845 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +services: + app: + build: . + ports: + - "80:80" + depends_on: + db: + condition: service_healthy + + db: + image: postgres:16-alpine + environment: + POSTGRES_USER: reaktor + POSTGRES_PASSWORD: reaktor_dev + POSTGRES_DB: reaktor + volumes: + - pgdata:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U reaktor"] + interval: 5s + retries: 5 + +volumes: + pgdata: diff --git a/package-lock.json b/package-lock.json index 72e8582..806ac9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,21 +1,14 @@ { - "name": "reaktor-montlab", + "name": "reaktor", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "reaktor-montlab", - "version": "1.0.0", - "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0", - "tone": "^14.8.49" - }, - "devDependencies": { - "@vitejs/plugin-react": "^4.2.0", - "vite": "^5.4.0" - } + "name": "reaktor", + "workspaces": [ + "packages/*" + ] }, "node_modules/@babel/code-frame": { "version": "7.29.0", @@ -749,6 +742,14 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@reaktor/client": { + "resolved": "packages/client", + "link": true + }, + "node_modules/@reaktor/server": { + "resolved": "packages/server", + "link": true + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -1722,6 +1723,23 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" + }, + "packages/client": { + "name": "@reaktor/client", + "version": "1.0.0", + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "tone": "^14.8.49" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.2.0", + "vite": "^5.4.0" + } + }, + "packages/server": { + "name": "@reaktor/server", + "version": "1.0.0" } } } diff --git a/package.json b/package.json index 6d85af9..9a2dd34 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,10 @@ { - "name": "reaktor-montlab", - "version": "1.0.0", + "name": "reaktor", "private": true, - "type": "module", + "workspaces": ["packages/*"], "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview", - "start": "node server.js" - }, - "dependencies": { - "react": "^18.2.0", - "react-dom": "^18.2.0", - "tone": "^14.8.49" - }, - "devDependencies": { - "@vitejs/plugin-react": "^4.2.0", - "vite": "^5.4.0" + "dev": "npm run dev -w packages/client", + "build": "npm run build -w packages/client", + "start": "node packages/server/server.js" } } diff --git a/index.html b/packages/client/index.html similarity index 100% rename from index.html rename to packages/client/index.html diff --git a/packages/client/package.json b/packages/client/package.json new file mode 100644 index 0000000..d1bb1a9 --- /dev/null +++ b/packages/client/package.json @@ -0,0 +1,20 @@ +{ + "name": "@reaktor/client", + "version": "1.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0", + "tone": "^14.8.49" + }, + "devDependencies": { + "@vitejs/plugin-react": "^4.2.0", + "vite": "^5.4.0" + } +} diff --git a/public/favicon.svg b/packages/client/public/favicon.svg similarity index 100% rename from public/favicon.svg rename to packages/client/public/favicon.svg diff --git a/public/icon-192.png b/packages/client/public/icon-192.png similarity index 100% rename from public/icon-192.png rename to packages/client/public/icon-192.png diff --git a/public/icon-512.png b/packages/client/public/icon-512.png similarity index 100% rename from public/icon-512.png rename to packages/client/public/icon-512.png diff --git a/public/manifest.json b/packages/client/public/manifest.json similarity index 100% rename from public/manifest.json rename to packages/client/public/manifest.json diff --git a/public/sw.js b/packages/client/public/sw.js similarity index 100% rename from public/sw.js rename to packages/client/public/sw.js diff --git a/src/App.jsx b/packages/client/src/App.jsx similarity index 100% rename from src/App.jsx rename to packages/client/src/App.jsx diff --git a/src/components/BottomSheet.jsx b/packages/client/src/components/BottomSheet.jsx similarity index 100% rename from src/components/BottomSheet.jsx rename to packages/client/src/components/BottomSheet.jsx diff --git a/src/components/DrumPadWidget.jsx b/packages/client/src/components/DrumPadWidget.jsx similarity index 100% rename from src/components/DrumPadWidget.jsx rename to packages/client/src/components/DrumPadWidget.jsx diff --git a/src/components/KeyboardWidget.jsx b/packages/client/src/components/KeyboardWidget.jsx similarity index 100% rename from src/components/KeyboardWidget.jsx rename to packages/client/src/components/KeyboardWidget.jsx diff --git a/src/components/Knob.jsx b/packages/client/src/components/Knob.jsx similarity index 100% rename from src/components/Knob.jsx rename to packages/client/src/components/Knob.jsx diff --git a/src/components/MobileTabBar.jsx b/packages/client/src/components/MobileTabBar.jsx similarity index 100% rename from src/components/MobileTabBar.jsx rename to packages/client/src/components/MobileTabBar.jsx diff --git a/src/components/ModuleNode.jsx b/packages/client/src/components/ModuleNode.jsx similarity index 100% rename from src/components/ModuleNode.jsx rename to packages/client/src/components/ModuleNode.jsx diff --git a/src/components/ModulePalette.jsx b/packages/client/src/components/ModulePalette.jsx similarity index 100% rename from src/components/ModulePalette.jsx rename to packages/client/src/components/ModulePalette.jsx diff --git a/src/components/PianoRollWidget.jsx b/packages/client/src/components/PianoRollWidget.jsx similarity index 100% rename from src/components/PianoRollWidget.jsx rename to packages/client/src/components/PianoRollWidget.jsx diff --git a/src/components/PresetModal.jsx b/packages/client/src/components/PresetModal.jsx similarity index 100% rename from src/components/PresetModal.jsx rename to packages/client/src/components/PresetModal.jsx diff --git a/src/components/ScopeDisplay.jsx b/packages/client/src/components/ScopeDisplay.jsx similarity index 100% rename from src/components/ScopeDisplay.jsx rename to packages/client/src/components/ScopeDisplay.jsx diff --git a/src/components/SequencerWidget.jsx b/packages/client/src/components/SequencerWidget.jsx similarity index 100% rename from src/components/SequencerWidget.jsx rename to packages/client/src/components/SequencerWidget.jsx diff --git a/src/components/WireLayer.jsx b/packages/client/src/components/WireLayer.jsx similarity index 100% rename from src/components/WireLayer.jsx rename to packages/client/src/components/WireLayer.jsx diff --git a/src/engine/audioEngine.js b/packages/client/src/engine/audioEngine.js similarity index 100% rename from src/engine/audioEngine.js rename to packages/client/src/engine/audioEngine.js diff --git a/src/engine/moduleRegistry.js b/packages/client/src/engine/moduleRegistry.js similarity index 100% rename from src/engine/moduleRegistry.js rename to packages/client/src/engine/moduleRegistry.js diff --git a/src/engine/presets.js b/packages/client/src/engine/presets.js similarity index 100% rename from src/engine/presets.js rename to packages/client/src/engine/presets.js diff --git a/src/engine/state.js b/packages/client/src/engine/state.js similarity index 100% rename from src/engine/state.js rename to packages/client/src/engine/state.js diff --git a/src/engine/uiSounds.js b/packages/client/src/engine/uiSounds.js similarity index 100% rename from src/engine/uiSounds.js rename to packages/client/src/engine/uiSounds.js diff --git a/src/game/AdminPanel.jsx b/packages/client/src/game/AdminPanel.jsx similarity index 100% rename from src/game/AdminPanel.jsx rename to packages/client/src/game/AdminPanel.jsx diff --git a/src/game/GameApp.jsx b/packages/client/src/game/GameApp.jsx similarity index 100% rename from src/game/GameApp.jsx rename to packages/client/src/game/GameApp.jsx diff --git a/src/game/LevelComplete.jsx b/packages/client/src/game/LevelComplete.jsx similarity index 100% rename from src/game/LevelComplete.jsx rename to packages/client/src/game/LevelComplete.jsx diff --git a/src/game/PuzzleView.jsx b/packages/client/src/game/PuzzleView.jsx similarity index 100% rename from src/game/PuzzleView.jsx rename to packages/client/src/game/PuzzleView.jsx diff --git a/src/game/WorldMap.jsx b/packages/client/src/game/WorldMap.jsx similarity index 100% rename from src/game/WorldMap.jsx rename to packages/client/src/game/WorldMap.jsx diff --git a/src/game/autoSolver.js b/packages/client/src/game/autoSolver.js similarity index 100% rename from src/game/autoSolver.js rename to packages/client/src/game/autoSolver.js diff --git a/src/game/gameState.js b/packages/client/src/game/gameState.js similarity index 100% rename from src/game/gameState.js rename to packages/client/src/game/gameState.js diff --git a/src/game/levels/world1.js b/packages/client/src/game/levels/world1.js similarity index 100% rename from src/game/levels/world1.js rename to packages/client/src/game/levels/world1.js diff --git a/src/game/levels/world10.js b/packages/client/src/game/levels/world10.js similarity index 100% rename from src/game/levels/world10.js rename to packages/client/src/game/levels/world10.js diff --git a/src/game/levels/world11.js b/packages/client/src/game/levels/world11.js similarity index 100% rename from src/game/levels/world11.js rename to packages/client/src/game/levels/world11.js diff --git a/src/game/levels/world12.js b/packages/client/src/game/levels/world12.js similarity index 100% rename from src/game/levels/world12.js rename to packages/client/src/game/levels/world12.js diff --git a/src/game/levels/world2.js b/packages/client/src/game/levels/world2.js similarity index 100% rename from src/game/levels/world2.js rename to packages/client/src/game/levels/world2.js diff --git a/src/game/levels/world3.js b/packages/client/src/game/levels/world3.js similarity index 100% rename from src/game/levels/world3.js rename to packages/client/src/game/levels/world3.js diff --git a/src/game/levels/world4.js b/packages/client/src/game/levels/world4.js similarity index 100% rename from src/game/levels/world4.js rename to packages/client/src/game/levels/world4.js diff --git a/src/game/levels/world5.js b/packages/client/src/game/levels/world5.js similarity index 100% rename from src/game/levels/world5.js rename to packages/client/src/game/levels/world5.js diff --git a/src/game/levels/world6.js b/packages/client/src/game/levels/world6.js similarity index 100% rename from src/game/levels/world6.js rename to packages/client/src/game/levels/world6.js diff --git a/src/game/levels/world7.js b/packages/client/src/game/levels/world7.js similarity index 100% rename from src/game/levels/world7.js rename to packages/client/src/game/levels/world7.js diff --git a/src/game/levels/world8.js b/packages/client/src/game/levels/world8.js similarity index 100% rename from src/game/levels/world8.js rename to packages/client/src/game/levels/world8.js diff --git a/src/game/levels/world9.js b/packages/client/src/game/levels/world9.js similarity index 100% rename from src/game/levels/world9.js rename to packages/client/src/game/levels/world9.js diff --git a/src/game/targetAudio.js b/packages/client/src/game/targetAudio.js similarity index 100% rename from src/game/targetAudio.js rename to packages/client/src/game/targetAudio.js diff --git a/src/hooks/useIsMobile.js b/packages/client/src/hooks/useIsMobile.js similarity index 100% rename from src/hooks/useIsMobile.js rename to packages/client/src/hooks/useIsMobile.js diff --git a/src/hooks/usePinchZoom.js b/packages/client/src/hooks/usePinchZoom.js similarity index 100% rename from src/hooks/usePinchZoom.js rename to packages/client/src/hooks/usePinchZoom.js diff --git a/src/index.css b/packages/client/src/index.css similarity index 100% rename from src/index.css rename to packages/client/src/index.css diff --git a/src/main.jsx b/packages/client/src/main.jsx similarity index 100% rename from src/main.jsx rename to packages/client/src/main.jsx diff --git a/src/presets/chiptune.js b/packages/client/src/presets/chiptune.js similarity index 100% rename from src/presets/chiptune.js rename to packages/client/src/presets/chiptune.js diff --git a/src/utils/bezier.js b/packages/client/src/utils/bezier.js similarity index 100% rename from src/utils/bezier.js rename to packages/client/src/utils/bezier.js diff --git a/src/utils/midiParser.js b/packages/client/src/utils/midiParser.js similarity index 100% rename from src/utils/midiParser.js rename to packages/client/src/utils/midiParser.js diff --git a/vite.config.js b/packages/client/vite.config.js similarity index 75% rename from vite.config.js rename to packages/client/vite.config.js index 1a1b84f..b156502 100644 --- a/vite.config.js +++ b/packages/client/vite.config.js @@ -4,5 +4,5 @@ import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [react()], server: { port: 3000 }, - build: { outDir: 'dist' } + build: { outDir: '../../dist', emptyOutDir: true } }); diff --git a/packages/server/package.json b/packages/server/package.json new file mode 100644 index 0000000..84454ce --- /dev/null +++ b/packages/server/package.json @@ -0,0 +1,8 @@ +{ + "name": "@reaktor/server", + "version": "1.0.0", + "private": true, + "scripts": { + "start": "node server.js" + } +} diff --git a/server.js b/packages/server/server.js similarity index 96% rename from server.js rename to packages/server/server.js index 0bece0f..b3abe23 100644 --- a/server.js +++ b/packages/server/server.js @@ -4,7 +4,7 @@ const fs = require('fs'); const path = require('path'); const PORT = process.env.PORT || 80; -const STATIC_DIR = path.join(__dirname, 'dist'); +const STATIC_DIR = path.join(__dirname, '..', '..', 'dist'); const MIME = { '.html': 'text/html', '.css': 'text/css', '.js': 'application/javascript',