New design v0.2
New design and framework
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 2.8 MiB |
109
src/index.ts
109
src/index.ts
@@ -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}`);
|
||||
|
||||
Reference in New Issue
Block a user