Add Docker Compose project scaffold
Sets up the full monorepo structure with: - Multi-stage Dockerfile (client-build + production stages) - docker-compose.yml for production, docker-compose.dev.yml overlay for development - Express server (port 3000) with pg pool, health route, and SPA static file serving - React 18 + Vite client with react-router-dom v6, nav bar, and placeholder page components - .env.example with PostgreSQL and app config - Empty db/migrations/ directory for future migrations - CLAUDE.md updated with development workflow commands Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
18
server/package.json
Normal file
18
server/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "budget-server",
|
||||
"version": "1.0.0",
|
||||
"main": "src/index.js",
|
||||
"scripts": {
|
||||
"start": "node src/index.js",
|
||||
"dev": "nodemon src/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.19.2",
|
||||
"pg": "^8.11.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^3.1.0"
|
||||
}
|
||||
}
|
||||
7
server/src/db.js
Normal file
7
server/src/db.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const { Pool } = require('pg');
|
||||
|
||||
const pool = new Pool({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
});
|
||||
|
||||
module.exports = pool;
|
||||
27
server/src/index.js
Normal file
27
server/src/index.js
Normal file
@@ -0,0 +1,27 @@
|
||||
require('dotenv').config();
|
||||
const express = require('express');
|
||||
const cors = require('cors');
|
||||
const path = require('path');
|
||||
const healthRouter = require('./routes/health');
|
||||
|
||||
const app = express();
|
||||
const PORT = process.env.PORT || 3000;
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.json());
|
||||
|
||||
// API routes
|
||||
app.use('/api', healthRouter);
|
||||
|
||||
// Serve static client files in production
|
||||
const clientDist = path.join(__dirname, '../../client/dist');
|
||||
app.use(express.static(clientDist));
|
||||
|
||||
// SPA fallback — send index.html for any unmatched route
|
||||
app.get('*', (req, res) => {
|
||||
res.sendFile(path.join(clientDist, 'index.html'));
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
});
|
||||
8
server/src/routes/health.js
Normal file
8
server/src/routes/health.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/health', (req, res) => {
|
||||
res.status(200).json({ status: 'ok' });
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
Reference in New Issue
Block a user