diff --git a/backend/src/index.ts b/backend/src/index.ts index bcc92a9..78d9134 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -2,6 +2,8 @@ import express from 'express'; import cookieParser from 'cookie-parser'; import cors from 'cors'; import { createServer } from 'http'; +import path from 'path'; +import { fileURLToPath } from 'url'; import { validateEnv, env } from './config/env.js'; import { runMigrations } from './db/migrate.js'; import { createInitialAdmin } from './setup/initialSetup.js'; @@ -18,6 +20,9 @@ import { errorHandler } from './middleware/errorHandler.js'; import { apiLimiter } from './middleware/rateLimiter.js'; import { createWebSocketServer } from './services/websocket.service.js'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + async function startServer() { try { console.log('🚀 Starting Kiddos Backend...\n'); @@ -39,8 +44,20 @@ async function startServer() { origin: env.corsOrigin, credentials: true })); - app.use(express.json()); + app.use(express.json({ limit: '10mb' })); + app.use(express.urlencoded({ extended: true, limit: '10mb' })); app.use(cookieParser()); + + // Serve uploaded files statically (use absolute path) + const uploadsPath = path.join(__dirname, '../uploads'); + app.use('/uploads', (req, res, next) => { + // Set CORS headers for image files to allow pixel data reading + // Use * for static files since they don't need credentials + res.header('Access-Control-Allow-Origin', '*'); + res.header('Access-Control-Allow-Methods', 'GET'); + next(); + }, express.static(uploadsPath)); + app.use('/api', apiLimiter); // Health check (for DigitalOcean) diff --git a/frontend/src/pages/AdminPage.tsx b/frontend/src/pages/AdminPage.tsx index f662714..c05da80 100644 --- a/frontend/src/pages/AdminPage.tsx +++ b/frontend/src/pages/AdminPage.tsx @@ -106,6 +106,7 @@ export function AdminPage() { Create magic codes for child settings

+ ); diff --git a/frontend/src/services/apiClient.ts b/frontend/src/services/apiClient.ts index 276c8e9..ddd1c72 100644 --- a/frontend/src/services/apiClient.ts +++ b/frontend/src/services/apiClient.ts @@ -6,6 +6,15 @@ const api = axios.create({ headers: { 'Content-Type': 'application/json' } }); +// Helper to create API instance without default JSON header (for FormData) +const createFormDataApi = () => { + return axios.create({ + baseURL: import.meta.env.VITE_API_URL || 'http://localhost:8080/api', + withCredentials: true + // No default Content-Type - let axios set it automatically for FormData + }); +}; + let isRefreshing = false; let failedQueue: any[] = []; @@ -200,4 +209,3 @@ export const magicCodeApi = { export const speechSoundsApi = { clearPronunciationsCache: () => api.delete('/speech-sounds/cache') }; -