ok
This commit is contained in:
@@ -13,11 +13,20 @@ This starts both the Vite dev server (frontend) and the API server (default port
|
||||
|
||||
Copy `.env.sample` to `.env` and set `VITE_SUPABASE_URL` and `VITE_SUPABASE_ANON_KEY` for the Svelte app and (optionally) the API server.
|
||||
|
||||
## Production
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npm run start
|
||||
```
|
||||
|
||||
This builds the frontend to `dist/` and starts the server. The same process serves both the API and the built SPA at `http://localhost:3001` (or your `PORT`). Without a `dist/` folder (e.g. API-only), the server still runs and serves only the API.
|
||||
|
||||
## API server (REST API for mobile / other clients)
|
||||
|
||||
The Express API uses the same Supabase backend. Optional env: `SUPABASE_URL`, `SUPABASE_ANON_KEY` (default to `VITE_*`), `PORT` (default `3001`).
|
||||
|
||||
- **Run**: `npm run dev:server` or `npm run start:api`
|
||||
- **Run**: `npm run dev:server`, `npm run start`, or `npm run start:api`. When `dist/` exists, the server also serves the frontend.
|
||||
- **Auth**: `POST /api/auth/login`, `POST /api/auth/register`, `GET /api/auth/session`, `GET /api/auth/profile` (Bearer token for protected routes; profile includes `display_name`, `email`, `avatar_url`)
|
||||
- **Decks**: `GET /api/decks/mine`, `GET /api/decks/published`, `GET /api/decks/:id`, `POST /api/decks`, `PATCH /api/decks/:id`, `DELETE /api/decks/:id`, `POST /api/decks/:id/publish`, `POST /api/decks/:id/copy`, `GET /api/decks/:id/update-preview`, `POST /api/decks/:id/apply-update`
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"test:run": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"dev:server": "node server/index.js",
|
||||
"start": "node server/index.js",
|
||||
"start:api": "node server/index.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -1,9 +1,16 @@
|
||||
import 'dotenv/config';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import fs from 'fs';
|
||||
import express from 'express';
|
||||
import cors from 'cors';
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
import * as decksApi from '../src/lib/api/decks-core.js';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const projectRoot = path.resolve(__dirname, '..');
|
||||
const distPath = path.join(projectRoot, 'dist');
|
||||
|
||||
const app = express();
|
||||
app.use(cors({ origin: true, credentials: true }));
|
||||
app.use(express.json());
|
||||
@@ -358,7 +365,21 @@ app.delete('/api/decks/:id', requireAuth, async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// Serve built frontend when dist/ exists (production)
|
||||
if (fs.existsSync(distPath)) {
|
||||
app.use(express.static(distPath));
|
||||
app.get('*', (req, res, next) => {
|
||||
if (req.path.startsWith('/api')) return next();
|
||||
res.sendFile(path.join(distPath, 'index.html'), (err) => {
|
||||
if (err) next(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const PORT = process.env.PORT || 3001;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`API server listening on http://localhost:${PORT}`);
|
||||
if (fs.existsSync(distPath)) {
|
||||
console.log(`Serving frontend from dist/ (open http://localhost:${PORT})`);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user