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:
12
client/index.html
Normal file
12
client/index.html
Normal 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>Budget</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
18
client/package.json
Normal file
18
client/package.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "budget-client",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-router-dom": "^6.23.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-react": "^4.3.0",
|
||||
"vite": "^5.2.11"
|
||||
}
|
||||
}
|
||||
32
client/src/App.jsx
Normal file
32
client/src/App.jsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Routes, Route, NavLink } from 'react-router-dom';
|
||||
import PaycheckView from './pages/PaycheckView.jsx';
|
||||
import Bills from './pages/Bills.jsx';
|
||||
import Settings from './pages/Settings.jsx';
|
||||
import MonthlySummary from './pages/MonthlySummary.jsx';
|
||||
import AnnualOverview from './pages/AnnualOverview.jsx';
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div>
|
||||
<nav style={{ display: 'flex', gap: '1rem', padding: '1rem', borderBottom: '1px solid #ccc' }}>
|
||||
<NavLink to="/">Paycheck</NavLink>
|
||||
<NavLink to="/bills">Bills</NavLink>
|
||||
<NavLink to="/settings">Settings</NavLink>
|
||||
<NavLink to="/summary/monthly">Monthly Summary</NavLink>
|
||||
<NavLink to="/summary/annual">Annual Overview</NavLink>
|
||||
</nav>
|
||||
|
||||
<main style={{ padding: '1rem' }}>
|
||||
<Routes>
|
||||
<Route path="/" element={<PaycheckView />} />
|
||||
<Route path="/bills" element={<Bills />} />
|
||||
<Route path="/settings" element={<Settings />} />
|
||||
<Route path="/summary/monthly" element={<MonthlySummary />} />
|
||||
<Route path="/summary/annual" element={<AnnualOverview />} />
|
||||
</Routes>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
12
client/src/main.jsx
Normal file
12
client/src/main.jsx
Normal file
@@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import App from './App.jsx';
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</React.StrictMode>
|
||||
);
|
||||
5
client/src/pages/AnnualOverview.jsx
Normal file
5
client/src/pages/AnnualOverview.jsx
Normal file
@@ -0,0 +1,5 @@
|
||||
function AnnualOverview() {
|
||||
return <div><h1>Annual Overview</h1><p>Placeholder — coming soon.</p></div>;
|
||||
}
|
||||
|
||||
export default AnnualOverview;
|
||||
5
client/src/pages/Bills.jsx
Normal file
5
client/src/pages/Bills.jsx
Normal file
@@ -0,0 +1,5 @@
|
||||
function Bills() {
|
||||
return <div><h1>Bills</h1><p>Placeholder — coming soon.</p></div>;
|
||||
}
|
||||
|
||||
export default Bills;
|
||||
5
client/src/pages/MonthlySummary.jsx
Normal file
5
client/src/pages/MonthlySummary.jsx
Normal file
@@ -0,0 +1,5 @@
|
||||
function MonthlySummary() {
|
||||
return <div><h1>Monthly Summary</h1><p>Placeholder — coming soon.</p></div>;
|
||||
}
|
||||
|
||||
export default MonthlySummary;
|
||||
5
client/src/pages/PaycheckView.jsx
Normal file
5
client/src/pages/PaycheckView.jsx
Normal file
@@ -0,0 +1,5 @@
|
||||
function PaycheckView() {
|
||||
return <div><h1>Paycheck View</h1><p>Placeholder — coming soon.</p></div>;
|
||||
}
|
||||
|
||||
export default PaycheckView;
|
||||
5
client/src/pages/Settings.jsx
Normal file
5
client/src/pages/Settings.jsx
Normal file
@@ -0,0 +1,5 @@
|
||||
function Settings() {
|
||||
return <div><h1>Settings</h1><p>Placeholder — coming soon.</p></div>;
|
||||
}
|
||||
|
||||
export default Settings;
|
||||
11
client/vite.config.js
Normal file
11
client/vite.config.js
Normal file
@@ -0,0 +1,11 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
server: {
|
||||
proxy: {
|
||||
'/api': 'http://localhost:3001',
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user