feat(blog): add file-based blog with dynamic slugs, MDX content and layout shell

- Introduced blog routing using Next.js App Router
- Implemented dynamic [slug] pages for blog posts
- Added MDX-based content loading via lib/posts
- Integrated shared TopBar layout with navigation
- Established clear content, lib and component separation
This commit is contained in:
PascalSchattenburg
2026-01-22 14:14:15 +01:00
parent b717952234
commit d147843c76
10412 changed files with 2475583 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
/**
* Loads a given module for a given ID.
*/
export interface ModuleLoader {
load<M = any>(id: string): Promise<M>;
}

View File

@@ -0,0 +1,8 @@
/**
* Loads a given module for a given ID.
*/ "use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
//# sourceMappingURL=module-loader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/server/lib/module-loader/module-loader.ts"],"sourcesContent":["/**\n * Loads a given module for a given ID.\n */\nexport interface ModuleLoader {\n load<M = any>(id: string): Promise<M>\n}\n"],"names":[],"mappings":"AAAA;;CAEC","ignoreList":[0]}

View File

@@ -0,0 +1,7 @@
import type { ModuleLoader } from './module-loader';
/**
* Loads a module using `await require(id)`.
*/
export declare class NodeModuleLoader implements ModuleLoader {
load<M>(id: string): Promise<M>;
}

View File

@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "NodeModuleLoader", {
enumerable: true,
get: function() {
return NodeModuleLoader;
}
});
class NodeModuleLoader {
async load(id) {
if (process.env.NEXT_RUNTIME !== 'edge') {
// Need to `await` to cover the case that route is marked ESM modules by ESM escalation.
return await (process.env.NEXT_MINIMAL ? __non_webpack_require__(id) : require(id));
}
throw Object.defineProperty(new Error('NodeModuleLoader is not supported in edge runtime.'), "__NEXT_ERROR_CODE", {
value: "E25",
enumerable: false,
configurable: true
});
}
}
//# sourceMappingURL=node-module-loader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/server/lib/module-loader/node-module-loader.ts"],"sourcesContent":["import type { ModuleLoader } from './module-loader'\n\n/**\n * Loads a module using `await require(id)`.\n */\nexport class NodeModuleLoader implements ModuleLoader {\n public async load<M>(id: string): Promise<M> {\n if (process.env.NEXT_RUNTIME !== 'edge') {\n // Need to `await` to cover the case that route is marked ESM modules by ESM escalation.\n return await (process.env.NEXT_MINIMAL\n ? // @ts-ignore\n __non_webpack_require__(id)\n : require(id))\n }\n\n throw new Error('NodeModuleLoader is not supported in edge runtime.')\n }\n}\n"],"names":["NodeModuleLoader","load","id","process","env","NEXT_RUNTIME","NEXT_MINIMAL","__non_webpack_require__","require","Error"],"mappings":";;;;+BAKaA;;;eAAAA;;;AAAN,MAAMA;IACX,MAAaC,KAAQC,EAAU,EAAc;QAC3C,IAAIC,QAAQC,GAAG,CAACC,YAAY,KAAK,QAAQ;YACvC,wFAAwF;YACxF,OAAO,MAAOF,CAAAA,QAAQC,GAAG,CAACE,YAAY,GAElCC,wBAAwBL,MACxBM,QAAQN,GAAE;QAChB;QAEA,MAAM,qBAA+D,CAA/D,IAAIO,MAAM,uDAAV,qBAAA;mBAAA;wBAAA;0BAAA;QAA8D;IACtE;AACF","ignoreList":[0]}

View File

@@ -0,0 +1,8 @@
import type { RouteModule } from '../../route-modules/route-module';
import type { ModuleLoader } from './module-loader';
export interface AppLoaderModule<M extends RouteModule = RouteModule> {
routeModule: M;
}
export declare class RouteModuleLoader {
static load<M extends RouteModule>(id: string, loader?: ModuleLoader): Promise<M>;
}

View File

@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "RouteModuleLoader", {
enumerable: true,
get: function() {
return RouteModuleLoader;
}
});
const _nodemoduleloader = require("./node-module-loader");
class RouteModuleLoader {
static async load(id, loader = new _nodemoduleloader.NodeModuleLoader()) {
const module = await loader.load(id);
if ('routeModule' in module) {
return module.routeModule;
}
throw Object.defineProperty(new Error(`Module "${id}" does not export a routeModule.`), "__NEXT_ERROR_CODE", {
value: "E53",
enumerable: false,
configurable: true
});
}
}
//# sourceMappingURL=route-module-loader.js.map

View File

@@ -0,0 +1 @@
{"version":3,"sources":["../../../../src/server/lib/module-loader/route-module-loader.ts"],"sourcesContent":["import type { RouteModule } from '../../route-modules/route-module'\nimport type { ModuleLoader } from './module-loader'\n\nimport { NodeModuleLoader } from './node-module-loader'\n\nexport interface AppLoaderModule<M extends RouteModule = RouteModule> {\n routeModule: M\n}\n\nexport class RouteModuleLoader {\n static async load<M extends RouteModule>(\n id: string,\n loader: ModuleLoader = new NodeModuleLoader()\n ): Promise<M> {\n const module: AppLoaderModule<M> = await loader.load(id)\n if ('routeModule' in module) {\n return module.routeModule\n }\n\n throw new Error(`Module \"${id}\" does not export a routeModule.`)\n }\n}\n"],"names":["RouteModuleLoader","load","id","loader","NodeModuleLoader","module","routeModule","Error"],"mappings":";;;;+BASaA;;;eAAAA;;;kCANoB;AAM1B,MAAMA;IACX,aAAaC,KACXC,EAAU,EACVC,SAAuB,IAAIC,kCAAgB,EAAE,EACjC;QACZ,MAAMC,SAA6B,MAAMF,OAAOF,IAAI,CAACC;QACrD,IAAI,iBAAiBG,QAAQ;YAC3B,OAAOA,OAAOC,WAAW;QAC3B;QAEA,MAAM,qBAA0D,CAA1D,IAAIC,MAAM,CAAC,QAAQ,EAAEL,GAAG,gCAAgC,CAAC,GAAzD,qBAAA;mBAAA;wBAAA;0BAAA;QAAyD;IACjE;AACF","ignoreList":[0]}