diff --git a/package-lock.json b/package-lock.json
index 95c56aa..eb4b193 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,7 +19,8 @@
"helmet": "^8.1.0",
"marked": "^15.0.11",
"morgan": "^1.10.0",
- "nodemon": "^3.1.10"
+ "nodemon": "^3.1.10",
+ "path": "^0.12.7"
}
},
"node_modules/@isaacs/cliui": {
@@ -1314,6 +1315,15 @@
"node": ">= 0.8"
}
},
+ "node_modules/path": {
+ "version": "0.12.7",
+ "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
+ "integrity": "sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q==",
+ "dependencies": {
+ "process": "^0.11.1",
+ "util": "^0.10.3"
+ }
+ },
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -1360,6 +1370,14 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -1870,6 +1888,19 @@
"node": ">= 0.8"
}
},
+ "node_modules/util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
+ "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
+ "dependencies": {
+ "inherits": "2.0.3"
+ }
+ },
+ "node_modules/util/node_modules/inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw=="
+ },
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
diff --git a/package.json b/package.json
index d3130d2..e1479f7 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
"helmet": "^8.1.0",
"marked": "^15.0.11",
"morgan": "^1.10.0",
- "nodemon": "^3.1.10"
+ "nodemon": "^3.1.10",
+ "path": "^0.12.7"
}
}
diff --git a/posts/2025/05/example.md b/posts/2025/05/example.md
index 7b0cfb1..13883b9 100644
--- a/posts/2025/05/example.md
+++ b/posts/2025/05/example.md
@@ -18,3 +18,4 @@
```js
console.log("Hello, world!");
+```
diff --git a/public/css/styles.css b/public/css/styles.css
index 7d70a75..2502362 100644
--- a/public/css/styles.css
+++ b/public/css/styles.css
@@ -60,6 +60,13 @@
background-color: #34495e;
}
+footer {
+ background: #f0f0f0;
+ padding: 1rem 0;
+ text-align: center;
+ border-top: 1px solid #ccc;
+}
+
/* Layout */
.layout {
display: flex;
diff --git a/src/app.js b/src/app.js
index 8cc7662..dd42755 100644
--- a/src/app.js
+++ b/src/app.js
@@ -4,6 +4,7 @@
const setupMiddleware = require("./middleware");
const { registerHelpers } = require("./utils/hbsHelpers");
const app = express();
+const path = require("path");
const hbs = exphbs.create({
layoutsDir: "src/views/layouts",
diff --git a/src/middleware/index.js b/src/middleware/index.js
index bccf674..f7ca64e 100644
--- a/src/middleware/index.js
+++ b/src/middleware/index.js
@@ -27,6 +27,11 @@
app.use("/static", express.static("public"));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(routes);
+ app.use((req, res, next) => {
+ const err = new Error("Not Found");
+ err.statusCode = 404;
+ next(err);
+ });
app.use(errorHandler);
}
diff --git a/src/routes/index.js b/src/routes/index.js
index a0047e2..ee077b6 100644
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -53,12 +53,12 @@
});
router.get("/", async (req, res) => {
- const context = getBaseContext({
+ const context = await getBaseContext({
title: "Blog Home",
content: "Welcome to the blog.",
});
- res.render("pages/home", context);
+ res.render("pages/home.handlebars", context);
});
module.exports = router;
diff --git a/src/utils/logging.js b/src/utils/logging.js
index ffa8ab7..eeddafe 100644
--- a/src/utils/logging.js
+++ b/src/utils/logging.js
@@ -9,6 +9,7 @@
// Define log file paths
const logFiles = {
+ session: path.join(logDir, "session.log"),
info: path.join(logDir, "info", "info.log"),
notice: path.join(logDir, "notice", "notice.log"),
error: path.join(logDir, "error", "error.log"),
@@ -29,8 +30,11 @@
fs.mkdirSync(functionsLogDir, { recursive: true });
}
+const originalConsole = { ...console };
+
// Create write streams
const logStreams = {
+ session: fs.createWriteStream(logFiles.session, { flags: "a" }),
info: fs.createWriteStream(logFiles.info, { flags: "a" }),
notice: fs.createWriteStream(logFiles.notice, { flags: "a" }),
error: fs.createWriteStream(logFiles.error, { flags: "a" }),
@@ -72,47 +76,41 @@
//console.log(`[${functionName}]`, ...args)
};
+// Generic log writer
+function writeLog(level, stream, consoleFn, ...args) {
+ const message = args.join(" ") + "\n";
+ stream.write(message);
+ logStreams.session.write(`[${level}] ${message}`);
+ consoleFn(`[${level}]`, ...args);
+}
+
+function patchConsole() {
+ console.log = (...args) =>
+ writeLog("INFO", logStreams.info, originalConsole.log, ...args);
+ console.error = (...args) =>
+ writeLog("ERROR", logStreams.error, originalConsole.error, ...args);
+ console.warn = (...args) =>
+ writeLog("WARN", logStreams.warn, originalConsole.warn, ...args);
+ console.info = (...args) =>
+ writeLog("INFO", logStreams.info, originalConsole.info, ...args);
+ console.debug = (...args) =>
+ writeLog("DEBUG", logStreams.debug, originalConsole.debug, ...args);
+}
+
// Exported logger object
const logger = {
streams: logStreams,
function: functionLog,
- info: (...args) => {
- const message = args.join(" ") + "\n";
- logger.streams.info.write(message);
- console.log("[INFO]", ...args);
- },
- function: functionLog,
- notice: (...args) => {
- const message = args.join(" ") + "\n";
- logger.streams.notice.write(message);
- console.log("[NOTICE]", ...args);
- },
- warn: (...args) => {
- const message = args.join(" ") + "\n";
- logger.streams.warn.write(message);
- console.warn("[WARN]", ...args);
- },
- error: (...args) => {
- const message = args.join(" ") + "\n";
- logger.streams.error.write(message);
- console.error("[ERROR]", ...args);
- },
- debug: (message, ...args) => {
- let logMessage = message;
- // If the first argument is an object, use util.inspect to handle circular structures
- if (args.length > 0 && typeof args[0] === "object") {
- logMessage +=
- "\n" +
- util.inspect(args[0], { showHidden: false, depth: null, colors: true });
- } else {
- logMessage += " " + args.join(" ");
- }
-
- // Write to file (debug log file)
- logger.streams.debug.write(logMessage + "\n");
-
- // Log to the console (with [DEBUG] prefix)
- console.log("[DEBUG]", logMessage);
- },
+ info: (...args) => writeLog("INFO", logStreams.info, console.log, ...args),
+ notice: (...args) =>
+ writeLog("NOTICE", logStreams.notice, console.log, ...args),
+ warn: (...args) => writeLog("WARN", logStreams.warn, console.warn, ...args),
+ error: (...args) =>
+ writeLog("ERROR", logStreams.error, console.error, ...args),
+ debug: (...args) =>
+ writeLog("DEBUG", logStreams.debug, console.debug, ...args),
};
+if (process.env.NODE_ENV !== "production") {
+ patchConsole();
+}
module.exports = logger;
diff --git a/src/views/layouts/main.handlebars b/src/views/layouts/main.handlebars
index d14fb3f..0034c38 100644
--- a/src/views/layouts/main.handlebars
+++ b/src/views/layouts/main.handlebars
@@ -16,6 +16,9 @@
{{{body}}}
+