New design v0.2

New design and framework
This commit is contained in:
Oussama Douhou
2026-01-13 10:49:47 +01:00
parent 21161c6554
commit 8977a6fdee
29 changed files with 2434 additions and 58 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 2.8 MiB

View File

@@ -451,63 +451,64 @@ app.delete('/api/stack/:name', async (c) => {
}
});
// Serve static files (frontend)
// Serve CSS and JS files directly
app.get('/style.css', async (c) => {
const file = Bun.file('./src/frontend/style.css');
return new Response(file, {
headers: { 'Content-Type': 'text/css' }
});
const REACT_BUILD_PATH = './dist/client';
const LEGACY_FRONTEND_PATH = './src/frontend';
const USE_REACT = process.env.USE_REACT_FRONTEND !== 'false';
async function serveFile(reactPath: string, legacyPath: string, contentType: string) {
const filePath = USE_REACT ? `${REACT_BUILD_PATH}${reactPath}` : `${LEGACY_FRONTEND_PATH}${legacyPath}`;
const file = Bun.file(filePath);
if (await file.exists()) {
return new Response(file, { headers: { 'Content-Type': contentType } });
}
const fallbackFile = Bun.file(`${LEGACY_FRONTEND_PATH}${legacyPath}`);
if (await fallbackFile.exists()) {
return new Response(fallbackFile, { headers: { 'Content-Type': contentType } });
}
return new Response('Not Found', { status: 404 });
}
app.get('/assets/*', async (c) => {
const path = c.req.path;
const file = Bun.file(`${REACT_BUILD_PATH}${path}`);
if (await file.exists()) {
const ext = path.split('.').pop();
const contentTypes: Record<string, string> = {
js: 'application/javascript',
css: 'text/css',
svg: 'image/svg+xml',
png: 'image/png',
jpg: 'image/jpeg',
woff: 'font/woff',
woff2: 'font/woff2',
};
return new Response(file, {
headers: { 'Content-Type': contentTypes[ext || ''] || 'application/octet-stream' }
});
}
return new Response('Not Found', { status: 404 });
});
app.get('/app.js', async (c) => {
const file = Bun.file('./src/frontend/app.js');
return new Response(file, {
headers: { 'Content-Type': 'application/javascript' }
});
});
app.get('/style.css', (c) => serveFile('/style.css', '/style.css', 'text/css'));
app.get('/app.js', (c) => serveFile('/app.js', '/app.js', 'application/javascript'));
app.get('/og-image.png', (c) => serveFile('/og-image.png', '/og-image.png', 'image/png'));
app.get('/favicon.svg', (c) => serveFile('/favicon.svg', '/favicon.svg', 'image/svg+xml'));
app.get('/favicon.ico', (c) => serveFile('/favicon.ico', '/favicon.ico', 'image/x-icon'));
app.get('/favicon.png', (c) => serveFile('/favicon.png', '/favicon.png', 'image/png'));
app.get('/apple-touch-icon.png', (c) => serveFile('/apple-touch-icon.png', '/apple-touch-icon.png', 'image/png'));
app.get('/og-image.png', async (c) => {
const file = Bun.file('./src/frontend/og-image.png');
return new Response(file, {
headers: { 'Content-Type': 'image/png' }
});
});
app.get('/favicon.svg', async (c) => {
const file = Bun.file('./src/frontend/favicon.svg');
return new Response(file, {
headers: { 'Content-Type': 'image/svg+xml' }
});
});
app.get('/favicon.ico', async (c) => {
const file = Bun.file('./src/frontend/favicon.ico');
return new Response(file, {
headers: { 'Content-Type': 'image/x-icon' }
});
});
app.get('/favicon.png', async (c) => {
const file = Bun.file('./src/frontend/favicon.png');
return new Response(file, {
headers: { 'Content-Type': 'image/png' }
});
});
app.get('/apple-touch-icon.png', async (c) => {
const file = Bun.file('./src/frontend/apple-touch-icon.png');
return new Response(file, {
headers: { 'Content-Type': 'image/png' }
});
});
// Serve index.html for all other routes (SPA fallback)
app.get('/', async (c) => {
const file = Bun.file('./src/frontend/index.html');
return new Response(file, {
headers: { 'Content-Type': 'text/html' }
});
app.get('*', async (c) => {
if (c.req.path.startsWith('/api/') || c.req.path === '/health') {
return c.notFound();
}
const indexPath = USE_REACT ? `${REACT_BUILD_PATH}/index.html` : `${LEGACY_FRONTEND_PATH}/index.html`;
const file = Bun.file(indexPath);
if (await file.exists()) {
return new Response(file, { headers: { 'Content-Type': 'text/html' } });
}
const fallback = Bun.file(`${LEGACY_FRONTEND_PATH}/index.html`);
return new Response(fallback, { headers: { 'Content-Type': 'text/html' } });
});
console.log(`🚀 AI Stack Deployer (Production) starting on http://${HOST}:${PORT}`);