WIP! A BB-style forum, on the ATmosphere!
We're still working... we'll be back soon when we have something to show off!
node
typescript
hono
htmx
atproto
1import { Hono } from "hono";
2import { serve } from "@hono/node-server";
3import { serveStatic } from "@hono/node-server/serve-static";
4import { requestLogger } from "@atbb/logger/middleware";
5import { existsSync } from "node:fs";
6import { resolve } from "node:path";
7import { webRoutes } from "./routes/index.js";
8import { loadConfig } from "./lib/config.js";
9import { logger } from "./lib/logger.js";
10
11const config = loadConfig();
12
13const app = new Hono();
14
15app.use("*", requestLogger(logger));
16
17const staticRoot = "./public";
18if (!existsSync(resolve(staticRoot))) {
19 logger.error("Static file directory not found", {
20 resolvedPath: resolve(staticRoot),
21 cwd: process.cwd(),
22 });
23}
24app.use("/static/*", serveStatic({ root: staticRoot }));
25app.route("/", webRoutes);
26
27app.onError((err, c) => {
28 logger.error("Unhandled error in web route", {
29 path: c.req.path,
30 method: c.req.method,
31 error: err.message,
32 stack: err.stack,
33 });
34 const detail =
35 process.env.NODE_ENV !== "production"
36 ? `<p><code>${err.message}</code></p>`
37 : "";
38 return c.html(
39 `<!DOCTYPE html><html lang="en"><body><h1>Internal Server Error</h1><p>Something went wrong. Please try again later.</p>${detail}</body></html>`,
40 500
41 );
42});
43
44serve(
45 {
46 fetch: app.fetch,
47 port: config.port,
48 },
49 (info) => {
50 logger.info("Server started", {
51 url: `http://localhost:${info.port}`,
52 port: info.port,
53 });
54 }
55);