Rene Fichtmueller a6f2b2ef9e feat: Phase 8 — Dashboard frontend + static serving
Single-file dashboard with 6 tabs: Overview, Semantic Search,
Hype Cycle, Transceivers, News, Blog Engine. Dark theme, no
build step, served as static HTML from Express.

- Overview: health stats, vector collection counts, recent news
- Semantic Search: query across all 6 Qdrant collections
- Hype Cycle: Norton-Bass table with phase colors + position bars
- Transceivers: searchable table with form factor/speed/reach
- News: semantic news search with source links
- Blog: generate drafts from templates, view draft history

Live at: https://transceiver-db.context-x.org/dashboard/
2026-03-28 00:37:10 +13:00

89 lines
2.8 KiB
TypeScript

import express from "express";
import cors from "cors";
import helmet from "helmet";
import rateLimit from "express-rate-limit";
import { join } from "path";
import { cfg } from "./config";
import { transceiverRouter } from "./routes/transceivers";
import { switchRouter } from "./routes/switches";
import { vendorRouter } from "./routes/vendors";
import { standardRouter } from "./routes/standards";
import { healthRouter } from "./routes/health";
import { hypeCycleRouter } from "./routes/hype-cycle";
import { searchRouter } from "./routes/search";
import { documentRouter } from "./routes/documents";
import { blogRouter } from "./routes/blog";
const app = express();
// Middleware
app.use(helmet({ contentSecurityPolicy: false }));
app.use(cors());
app.use(express.json());
app.use(
rateLimit({
windowMs: 60 * 1000,
max: 200,
standardHeaders: true,
legacyHeaders: false,
})
);
// Routes
app.use("/api/transceivers", transceiverRouter);
app.use("/api/switches", switchRouter);
app.use("/api/vendors", vendorRouter);
app.use("/api/standards", standardRouter);
app.use("/api/health", healthRouter);
app.use("/api/hype-cycle", hypeCycleRouter);
app.use("/api/search", searchRouter);
app.use("/api/documents", documentRouter);
app.use("/api/blog", blogRouter);
// Dashboard (static HTML)
app.use("/dashboard", express.static(join(__dirname, "..", "..", "dashboard")));
// Root — redirect to dashboard
app.get("/", (_req, res) => {
res.redirect("/dashboard/");
});
// API info
app.get("/api", (_req, res) => {
res.json({
name: "Transceiver Intelligence Platform",
version: "0.1.0",
endpoints: [
"GET /api/transceivers?q=&form_factor=&speed=&category=&fiber_type=&wdm_type=&coherent=",
"GET /api/transceivers/:id",
"GET /api/switches?q=&category=",
"GET /api/switches/:id",
"GET /api/switches/:id/compatibility",
"GET /api/vendors?type=",
"GET /api/standards?speed=",
"GET /api/health",
"GET /api/hype-cycle",
"GET /api/hype-cycle/:tech",
"GET /api/search?q=&collection=&limit=",
"GET /api/search/products?q=&form_factor=&speed_gbps=&fiber_type=",
"GET /api/search/documents?q=&doc_type=&vendor=&collection=",
"GET /api/search/news?q=&source=",
"GET /api/search/stats",
"POST /api/documents/process {url, title?, doc_type?, vendor?, collection?}",
"GET /api/documents",
"GET /api/documents/:id",
"POST /api/blog/generate {topic, speed?, form_factor?, use_case?}",
"GET /api/blog",
"GET /api/blog/:id",
"PUT /api/blog/:id/status {status: draft|review|approved|published}",
],
});
});
// Start
app.listen(cfg.port, () => {
console.log(`\n TIP API running on http://localhost:${cfg.port}`);
console.log(` Environment: ${cfg.nodeEnv}`);
console.log(` Database: ${cfg.db.host}:${cfg.db.port}/${cfg.db.database}\n`);
});