Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ DISCOGS_API_SECRET=your_discogs_api_secret
SPOTIFY_CLIENT_ID=your_spotify_client_id
SPOTIFY_CLIENT_SECRET=your_spotify_client_secret

### iOS App Configuration (served via GET /config)
POSTHOG_API_KEY=your_posthog_api_key
POSTHOG_HOST=https://us.i.posthog.com
REQUEST_O_MATIC_URL=https://request-o-matic-production.up.railway.app/request
API_BASE_URL=https://api.wxyc.org

### Metadata Cache Configuration
METADATA_ALBUM_CACHE_MAX_SIZE=1000
METADATA_ARTIST_CACHE_MAX_SIZE=500
Expand Down
22 changes: 12 additions & 10 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,18 @@ npm workspaces with four packages:

Express 5 application with these route groups:

| Route | Purpose |
| --------------- | --------------------------------------- |
| `/library` | Music library catalog |
| `/flowsheet` | V1 flowsheet (legacy) |
| `/v2/flowsheet` | V2 flowsheet (uses `@wxyc/shared` DTOs) |
| `/djs` | DJ profiles and management |
| `/request` | Song request line |
| `/schedule` | Schedule management |
| `/events` | SSE for real-time updates |
| `/healthcheck` | Health check |
| Route | Purpose |
| --------------- | ---------------------------------------------- |
| `/config` | Public app bootstrap configuration |
| `/proxy` | iOS proxy endpoints (anonymous auth + rate limit) |
| `/library` | Music library catalog |
| `/flowsheet` | V1 flowsheet (legacy) |
| `/v2/flowsheet` | V2 flowsheet (uses `@wxyc/shared` DTOs) |
| `/djs` | DJ profiles and management |
| `/request` | Song request line |
| `/schedule` | Schedule management |
| `/events` | SSE for real-time updates |
| `/healthcheck` | Health check |

Code is organized as controllers (HTTP handling) -> services (business logic) -> database (Drizzle queries).

Expand Down
8 changes: 8 additions & 0 deletions apps/backend/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { library_route } from './routes/library.route.js';
import { schedule_route } from './routes/schedule.route.js';
import { events_route } from './routes/events.route.js';
import { request_line_route } from './routes/requestLine.route.js';
import { config_route } from './routes/config.route.js';
import { proxy_route } from './routes/proxy.route.js';
import { showMemberMiddleware } from './middleware/checkShowMember.js';
import { activeShow } from './middleware/checkActiveShow.js';
import errorHandler from './middleware/errorHandler.js';
Expand All @@ -35,6 +37,12 @@ app.use(
const swaggerDoc = parse_yaml(swaggerContent);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDoc));

// Public configuration endpoint (unauthenticated)
app.use('/config', config_route);

// Proxy endpoints for iOS app (anonymous auth + rate limiting)
app.use('/proxy', proxy_route);

// Business logic routes
app.use('/library', library_route);

Expand Down
32 changes: 32 additions & 0 deletions apps/backend/controllers/config.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Config controller - serves non-sensitive app configuration.
*
* GET /config is unauthenticated because the app needs it before it can
* authenticate (bootstrap chicken-and-egg).
*/
import { RequestHandler } from 'express';

export interface AppConfig {
posthogApiKey: string;
posthogHost: string;
requestOMaticUrl: string;
apiBaseUrl: string;
}

/**
* GET /config
*
* Returns public, non-sensitive configuration for app bootstrap.
* Cache-Control: public, max-age=3600 (1 hour).
*/
export const getConfig: RequestHandler = (_req, res) => {
const config: AppConfig = {
posthogApiKey: process.env.POSTHOG_API_KEY || '',
posthogHost: process.env.POSTHOG_HOST || 'https://us.i.posthog.com',
requestOMaticUrl: process.env.REQUEST_O_MATIC_URL || '',
apiBaseUrl: process.env.API_BASE_URL || 'https://api.wxyc.org',
};

res.set('Cache-Control', 'public, max-age=3600');
res.status(200).json(config);
};
Loading
Loading