@seip/blue-bird 1.1.2 → 1.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/core/cli/route.js CHANGED
@@ -1,43 +1,144 @@
1
- import path from 'path';
2
- import fs from 'fs';
3
- import Config from "../config.js";
4
-
5
- const __dirname = Config.dirname();
6
-
7
- class RouteCLI {
8
- /**
9
- * Create route
10
- */
11
- create() {
12
- let nameRoute = process.argv[2];
13
- if (!nameRoute) {
14
- console.log("Please provide a route name. Usage: npm run route <route-name>");
15
- return;
16
- }
17
- nameRoute =nameRoute.charAt(0).toUpperCase() + nameRoute.slice(1);
18
- const folder= path.join(__dirname, 'backend/routes');
19
- if (!fs.existsSync(folder)){
20
- fs.mkdirSync(folder, { recursive: true });
21
- }
22
- const filePath = path.join(folder, `${nameRoute}.js`);
23
- if (fs.existsSync(filePath)) {
24
- console.log(`Route ${nameRoute} already exists.`);
25
- return;
26
- }
27
- const content =`import Router from "@seip/blue-bird/core/router.js"
28
-
29
- const router${nameRoute} = new Router("/${nameRoute.toLowerCase()}");
30
-
31
- router${nameRoute}.get("/", (req, res) => {
32
- res.json({ message: "Hello from ${nameRoute} route!" });
33
- });
34
-
35
- export default router${nameRoute};
36
- `;
37
- fs.writeFileSync(filePath, content);
38
- console.log(`Route ${nameRoute} created successfully at ${filePath}`);
39
- }
40
- }
41
-
42
- const routeCLI = new RouteCLI();
43
- routeCLI.create()
1
+ #!/usr/bin/env node
2
+
3
+ import path from "node:path";
4
+ import fs from "node:fs";
5
+ import chalk from "chalk";
6
+
7
+ class RouteCLI {
8
+ /**
9
+ * Creates a new RESTful route file with Validation, Cache, and optional Auth.
10
+ */
11
+ create() {
12
+ const rawArgs = process.argv.slice(2);
13
+ // Filter out command name if invoked as 'route' or 'make:route'
14
+ const args = rawArgs.filter(
15
+ (a) => a !== "route" && a !== "make:route" && !a.endsWith("route.js")
16
+ );
17
+
18
+ let routeName = args.find((a) => !a.startsWith("-"));
19
+ const withAuth = args.some((a) => a === "--auth" || a === "-a");
20
+
21
+ if (!routeName) {
22
+ console.log(chalk.red("[ERROR] Missing route name."));
23
+ console.log("");
24
+ console.log("Usage:");
25
+ console.log(" npx blue-bird make:route <name> [--auth]");
26
+ console.log("");
27
+ console.log("Examples:");
28
+ console.log(" npx blue-bird make:route products");
29
+ console.log(" npx blue-bird make:route articles --auth");
30
+ process.exit(1);
31
+ }
32
+
33
+ // Normalize casing
34
+ routeName = routeName.toLowerCase().replace(/[^a-z0-9_-]/g, "");
35
+ const singularName = routeName.endsWith("s") ? routeName.slice(0, -1) : routeName;
36
+ const pascalName = routeName.charAt(0).toUpperCase() + routeName.slice(1);
37
+ const routerVarName = `router${pascalName}`;
38
+ const basePath = `/${routeName}`;
39
+
40
+ const routesFolder = path.resolve(process.cwd(), "backend/routes");
41
+ if (!fs.existsSync(routesFolder)) {
42
+ fs.mkdirSync(routesFolder, { recursive: true });
43
+ }
44
+
45
+ const filePath = path.join(routesFolder, `${routeName}.js`);
46
+ if (fs.existsSync(filePath)) {
47
+ console.log(chalk.yellow(`[WARN] Route file '${routeName}.js' already exists at backend/routes/${routeName}.js.`));
48
+ return;
49
+ }
50
+
51
+ const authImport = withAuth
52
+ ? `import Auth from "@seip/blue-bird/core/auth.js";\n`
53
+ : "";
54
+
55
+ const authProtect = withAuth ? `Auth.protect(), ` : "";
56
+
57
+ const content = `import Router from "@seip/blue-bird/core/router.js";
58
+ import Validator from "@seip/blue-bird/core/validate.js";
59
+ import Cache from "@seip/blue-bird/core/cache.js";
60
+ ${authImport}
61
+ const ${routerVarName} = new Router("${basePath}");
62
+
63
+ // Validation schema for incoming requests
64
+ const ${singularName}Schema = {
65
+ name: { required: true, min: 2, max: 255 },
66
+ description: { required: false },
67
+ price: { required: false }
68
+ };
69
+
70
+ const validate${pascalName} = new Validator(${singularName}Schema, "en");
71
+
72
+ /**
73
+ * GET ${basePath}
74
+ * List all items with in-memory / Redis route caching (60 seconds)
75
+ */
76
+ ${routerVarName}.get("/", Cache.middleware(60), (req, res) => {
77
+ res.ok({ ${routeName}: [] }, "${pascalName} list retrieved successfully");
78
+ });
79
+
80
+ /**
81
+ * GET ${basePath}/:id
82
+ * Retrieve a single item by ID
83
+ */
84
+ ${routerVarName}.get("/:id", Cache.middleware(60), (req, res) => {
85
+ const { id } = req.params;
86
+ res.ok({ ${singularName}: { id } }, "${pascalName} retrieved successfully");
87
+ });
88
+
89
+ /**
90
+ * POST ${basePath}
91
+ * Create a new item (with validation and automatic cache invalidation)
92
+ */
93
+ ${routerVarName}.post("/", ${authProtect}validate${pascalName}.middleware(), async (req, res) => {
94
+ const data = req.body;
95
+
96
+ // Invalidate cached route list
97
+ await Cache.delete("${basePath}");
98
+
99
+ res.created({ ${singularName}: data }, "${pascalName} created successfully");
100
+ });
101
+
102
+ /**
103
+ * PUT ${basePath}/:id
104
+ * Update an existing item
105
+ */
106
+ ${routerVarName}.put("/:id", ${authProtect}validate${pascalName}.middleware(), async (req, res) => {
107
+ const { id } = req.params;
108
+ const data = req.body;
109
+
110
+ // Invalidate cached item and list
111
+ await Cache.delete("${basePath}");
112
+ await Cache.delete(\`${basePath}/\${id}\`);
113
+
114
+ res.ok({ ${singularName}: { id, ...data } }, "${pascalName} updated successfully");
115
+ });
116
+
117
+ /**
118
+ * DELETE ${basePath}/:id
119
+ * Delete an existing item
120
+ */
121
+ ${routerVarName}.delete("/:id", ${authProtect}async (req, res) => {
122
+ const { id } = req.params;
123
+
124
+ // Invalidate cache
125
+ await Cache.delete("${basePath}");
126
+ await Cache.delete(\`${basePath}/\${id}\`);
127
+
128
+ res.ok({ id }, "${pascalName} deleted successfully");
129
+ });
130
+
131
+ export default ${routerVarName};
132
+ `;
133
+
134
+ fs.writeFileSync(filePath, content, "utf-8");
135
+ console.log(chalk.green(`[OK] Route '${routeName}' created successfully at backend/routes/${routeName}.js`));
136
+ console.log("");
137
+ console.log(chalk.cyan("To register this route, import it in backend/index.js:"));
138
+ console.log(chalk.gray(` import ${routerVarName} from "./routes/${routeName}.js";`));
139
+ console.log(chalk.gray(` // Pass ${routerVarName} into App({ routes: [...] })`));
140
+ }
141
+ }
142
+
143
+ const routeCLI = new RouteCLI();
144
+ routeCLI.create();
@@ -1,3 +1,5 @@
1
+ #!/usr/bin/env node
2
+
1
3
  import { execSync } from "node:child_process";
2
4
 
3
5
  class SwaggerCli {
package/core/index.d.ts CHANGED
@@ -190,5 +190,12 @@ export class Database {
190
190
  close(): Promise<void>;
191
191
  }
192
192
 
193
+ export class Queue {
194
+ static process(jobName: string, handler: (payload: any) => Promise<any> | any): void;
195
+ static dispatch(jobName: string, payload?: any, options?: { delayMs?: number }): Promise<boolean>;
196
+ static loadJobs(jobsDir?: string): Promise<void>;
197
+ }
198
+
193
199
  export default App;
194
200
 
201
+
package/core/queue.js ADDED
@@ -0,0 +1,121 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { getRedisClient } from "./cache.js";
4
+
5
+ /**
6
+ * Lightweight background queue worker module with Redis and in-memory fallback.
7
+ */
8
+ class QueueManager {
9
+ constructor() {
10
+ this.handlers = new Map();
11
+ this.memoryQueue = [];
12
+ this.isProcessing = false;
13
+ this.redisPrefix = "bluebird:queue:";
14
+ }
15
+
16
+ /**
17
+ * Registers a job handler function.
18
+ * @param {string} jobName - Name of the job.
19
+ * @param {Function} handler - Async function(payload).
20
+ */
21
+ process(jobName, handler) {
22
+ if (typeof handler !== "function") {
23
+ throw new Error(`Handler for job '${jobName}' must be a function.`);
24
+ }
25
+ this.handlers.set(jobName, handler);
26
+ }
27
+
28
+ /**
29
+ * Dispatches a new job to the queue.
30
+ * @param {string} jobName - Name of the job.
31
+ * @param {any} payload - Data payload to pass to the handler.
32
+ * @param {object} [options] - Options (e.g. delayMs).
33
+ * @returns {Promise<boolean>}
34
+ */
35
+ async dispatch(jobName, payload = {}, options = {}) {
36
+ const jobItem = {
37
+ id: `${Date.now()}_${Math.random().toString(36).substring(2, 9)}`,
38
+ name: jobName,
39
+ payload,
40
+ createdAt: new Date().toISOString(),
41
+ };
42
+
43
+ const redis = getRedisClient();
44
+ if (redis && redis.isReady) {
45
+ try {
46
+ await redis.lPush(`${this.redisPrefix}jobs`, JSON.stringify(jobItem));
47
+ return true;
48
+ } catch (err) {
49
+ console.error("[QUEUE ERROR] Failed to dispatch job to Redis:", err.message);
50
+ }
51
+ }
52
+
53
+ // In-memory fallback
54
+ if (options.delayMs && options.delayMs > 0) {
55
+ setTimeout(() => {
56
+ this.memoryQueue.push(jobItem);
57
+ this.runMemoryWorker();
58
+ }, options.delayMs);
59
+ } else {
60
+ this.memoryQueue.push(jobItem);
61
+ setImmediate(() => this.runMemoryWorker());
62
+ }
63
+
64
+ return true;
65
+ }
66
+
67
+ /**
68
+ * Executes in-memory queue jobs sequentially.
69
+ * @private
70
+ */
71
+ async runMemoryWorker() {
72
+ if (this.isProcessing || this.memoryQueue.length === 0) return;
73
+ this.isProcessing = true;
74
+
75
+ while (this.memoryQueue.length > 0) {
76
+ const job = this.memoryQueue.shift();
77
+ if (!job) continue;
78
+
79
+ const handler = this.handlers.get(job.name);
80
+ if (!handler) {
81
+ console.warn(`[QUEUE WARN] No handler registered for job '${job.name}'.`);
82
+ continue;
83
+ }
84
+
85
+ try {
86
+ await handler(job.payload);
87
+ } catch (err) {
88
+ console.error(`[QUEUE ERROR] Error processing job '${job.name}' (${job.id}):`, err);
89
+ }
90
+ }
91
+
92
+ this.isProcessing = false;
93
+ }
94
+
95
+ /**
96
+ * Auto-loads all job definition files from backend/jobs/.
97
+ */
98
+ async loadJobs(jobsDir = path.resolve(process.cwd(), "backend/jobs")) {
99
+ if (!fs.existsSync(jobsDir)) return;
100
+
101
+ const files = fs
102
+ .readdirSync(jobsDir)
103
+ .filter((f) => f.endsWith(".js") || f.endsWith(".mjs"));
104
+
105
+ for (const file of files) {
106
+ const fullPath = path.join(jobsDir, file);
107
+ try {
108
+ const module = await import(`file://${fullPath}`);
109
+ if (typeof module.default === "function") {
110
+ const jobName = path.basename(file, path.extname(file));
111
+ this.process(jobName, module.default);
112
+ }
113
+ } catch (err) {
114
+ console.error(`[QUEUE ERROR] Failed to load job file '${file}':`, err.message);
115
+ }
116
+ }
117
+ }
118
+ }
119
+
120
+ export const Queue = new QueueManager();
121
+ export default Queue;
package/core/validate.js CHANGED
@@ -148,19 +148,20 @@ class Validator {
148
148
  * const result = await loginValidator.validate(req);
149
149
  */
150
150
  async validate(req) {
151
+ const isExpressReq = req && (req.body !== undefined || req.headers !== undefined);
151
152
  let lang =
152
153
  req?.body?.lang ||
153
154
  req?.query?.lang ||
154
155
  req?.params?.lang ||
155
156
  req?.cookies?.lang ||
156
- req?.headers["accept-language"]?.split(",")[0]?.split("-")[0] ||
157
+ req?.headers?.["accept-language"]?.split(",")[0]?.split("-")[0] ||
157
158
  req?.session?.lang ||
158
159
  this.lang_default ||
159
160
  "es";
160
161
  const msg = this.messages[lang] || this.messages.es;
161
162
  const errors = [];
162
163
  const messages = [];
163
- const body = req.body || {};
164
+ const body = isExpressReq ? (req.body || {}) : (req || {});
164
165
 
165
166
  for (const [field, config] of Object.entries(this.schema)) {
166
167
  let value = body[field];
package/docker/nginx.conf CHANGED
@@ -65,6 +65,29 @@ http {
65
65
  try_files $uri =404;
66
66
  }
67
67
 
68
+ # -------------------------------------------------------------
69
+ # Optional: Protected Static Frontend Pages (auth_request)
70
+ # Uncomment this block to protect private static pages (e.g. /dashboard)
71
+ # Nginx will subrequest Express /api/auth/check before serving HTML.
72
+ # -------------------------------------------------------------
73
+ # location ~ ^/(dashboard|admin|app|account) {
74
+ # auth_request /api/auth/check;
75
+ # error_page 401 = @login_redirect;
76
+ # try_files $uri $uri.html /index.html =404;
77
+ # }
78
+ #
79
+ # location = /api/auth/check {
80
+ # internal;
81
+ # proxy_pass http://app:3000/api/auth/check;
82
+ # proxy_pass_request_body off;
83
+ # proxy_set_header Content-Length "";
84
+ # proxy_set_header X-Original-URI $request_uri;
85
+ # }
86
+ #
87
+ # location @login_redirect {
88
+ # return 302 /login?redirect=$request_uri;
89
+ # }
90
+
68
91
  location / {
69
92
  add_header Cache-Control "no-cache";
70
93
  try_files $uri $uri.html $uri/ @node_app;
@@ -1,108 +1,157 @@
1
- <!DOCTYPE html>
2
- <html lang="en" data-theme="dark">
3
-
4
- <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Blue Bird - About</title>
8
- <link rel="canonical" href="https://seip25.github.io/Blue-bird/" />
9
- <meta name="description" content="Blue Bird is a fast, structured, and opinionated Express.js framework for developers who want
10
- visual elegance and performance with raw HTML and CSS.">
11
- <meta name="keywords" content="">
12
- <meta name="author" content="Seip25">
13
- <link rel="icon" href="/images/favicon.ico" />
14
- <script src="/js/tailwind.js"></script>
15
- <script src="/js/utils.js"></script>
16
- <style type="text/tailwindcss">
17
- @custom-variant dark (&:where(.dark, .dark *));
18
- </style>
19
- </head>
20
-
21
- <body class="min-h-screen bg-slate-950 text-white font-sans antialiased selection:bg-blue-500 selection:text-white">
22
- <header class="sticky top-0 z-50 px-4 py-3">
23
- <div
24
- class="max-w-7xl mx-auto flex items-center justify-between backdrop-blur-md bg-slate-900/60 border border-white/10 rounded-2xl px-6 py-3 shadow-lg">
25
- <div class="flex items-center space-x-3">
26
- <div
27
- class="w-10 h-10 bg-gradient-to-tr from-blue-500 to-indigo-600 rounded-xl flex items-center justify-center shadow-md shadow-blue-500/30">
28
- <svg class="w-6 h-6 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
29
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
30
- d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
31
- </svg>
32
- </div>
33
- <span
34
- class="text-xl font-bold tracking-tight bg-gradient-to-r from-blue-400 via-indigo-200 to-white bg-clip-text text-transparent">Blue
35
- Bird</span>
36
- </div>
37
-
38
- <nav class="flex space-x-8 text-sm font-medium text-slate-300">
39
- <a href="/" class="hover:text-blue-400 transition-colors">Home</a>
40
- <a href="/about" class="hover:text-blue-400 transition-colors">About</a>
41
- </nav>
42
- </div>
43
- </header>
44
-
45
- <main class="max-w-7xl mx-auto px-4 pt-12 pb-24">
46
-
47
- <div
48
- class="relative py-16 px-6 md:px-12 rounded-3xl overflow-hidden bg-gradient-to-b from-blue-900/20 to-slate-950 border border-white/5 shadow-2xl mb-12">
49
- <div class="relative max-w-4xl mx-auto space-y-6 text-center">
50
- <h1
51
- class="text-4xl sm:text-5xl font-extrabold tracking-tight bg-gradient-to-r from-blue-400 via-indigo-300 to-white bg-clip-text text-transparent">
52
- About Blue Bird
53
- </h1>
54
- <p class="text-lg sm:text-xl text-slate-400 leading-relaxed max-w-2xl mx-auto">
55
- Built for performance, simplicity, and raw speed.
56
- </p>
57
- </div>
58
- </div>
59
-
60
- <section class="max-w-4xl mx-auto space-y-12">
61
- <article class="p-8 rounded-2xl bg-slate-900/40 border border-white/5 shadow-xl">
62
- <h2 class="text-2xl font-bold text-white mb-4">Our Philosophy</h2>
63
- <p class="text-slate-400 leading-relaxed mb-4">
64
- Blue Bird was born out of a desire for a clean, performance-first approach to web development. We
65
- believe in harnessing the raw power of Express.js and Nginx, stripping away unnecessary bloat, and
66
- providing developers with a robust foundation that just works.
67
- </p>
68
- <p class="text-slate-400 leading-relaxed">
69
- By separating the static frontend delivery (handled blazingly fast by Nginx) from the dynamic API
70
- layer (powered by Express and Redis), Blue Bird achieves unparalleled performance out of the box.
71
- </p>
72
- </article>
73
-
74
- <article class="p-8 rounded-2xl bg-slate-900/40 border border-white/5 shadow-xl">
75
- <h2 class="text-2xl font-bold text-white mb-4">Why Blue Bird?</h2>
76
- <ul class="space-y-3 text-slate-400">
77
- <li class="flex items-start">
78
- <span class="text-blue-500 mr-2">✓</span>
79
- <span><strong>Zero Config Docker:</strong> Go from development to production seamlessly.</span>
80
- </li>
81
- <li class="flex items-start">
82
- <span class="text-blue-500 mr-2">✓</span>
83
- <span><strong>Military Grade Security:</strong> Built-in AES-256-GCM JWT encryption.</span>
84
- </li>
85
- <li class="flex items-start">
86
- <span class="text-blue-500 mr-2">✓</span>
87
- <span><strong>High Performance:</strong> Redis caching for the data layer and Nginx static
88
- delivery.</span>
89
- </li>
90
- <li class="flex items-start">
91
- <span class="text-blue-500 mr-2">✓</span>
92
- <span><strong>Pure HTML/CSS:</strong> No bloated frontend frameworks. Write code close to the
93
- metal.</span>
94
- </li>
95
- </ul>
96
- </article>
97
- </section>
98
- </main>
99
-
100
- <footer class="border-t border-white/5 py-8 bg-slate-950 mt-16">
101
- <div class="max-w-7xl mx-auto px-4 text-center text-sm text-slate-500">
102
- <p>Powered by Blue Bird Framework. All rights reserved.</p>
103
- </div>
104
- </footer>
105
-
106
- </body>
107
-
1
+ <!DOCTYPE html>
2
+ <html lang="en" data-theme="dark">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Blue Bird - About</title>
8
+ <link rel="canonical" href="https://seip25.github.io/Blue-bird/" />
9
+ <meta name="description"
10
+ content="Blue Bird is a fast, structured, and opinionated Express.js framework for developers who want visual elegance and performance with raw HTML and CSS.">
11
+ <meta name="keywords" content="Blue Bird, Express.js, About, Semantic CSS, Architecture">
12
+ <meta name="author" content="Seip25">
13
+ <link rel="icon" href="/images/favicon.ico" />
14
+ <link rel="stylesheet" href="/css/bluebird.css" />
15
+ <script src="/js/bluebird.js"></script>
16
+ </head>
17
+
18
+ <body>
19
+ <header>
20
+ <nav>
21
+ <a href="/" class="flex items-center gap-2">
22
+ <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
23
+ stroke-linecap="round" stroke-linejoin="round" class="text-blue">
24
+ <path d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
25
+ </svg>
26
+ <strong class="text-xl text-gradient">Blue Bird</strong>
27
+ </a>
28
+ </nav>
29
+ </header>
30
+
31
+ <main>
32
+ <aside>
33
+ <h4>Menu</h4>
34
+ <a href="/">Home</a>
35
+ <a href="/about" class="active badge badge-glow px-3 py-3">About</a>
36
+ <a href="https://seip25.github.io/Blue-bird-css/" target="_blank">Blue Bird CSS</a>
37
+ <a href="https://github.com/seip25/Blue-bird" target="_blank" role="button"
38
+ class="btn-sm outline">GitHub</a>
39
+ </aside>
40
+
41
+ <div>
42
+ <section class="hero ">
43
+ <h1 class="mt-3 text-gradient font-bold">About Blue Bird</h1>
44
+ <p class="lead">Built for performance, simplicity, and raw speed.</p>
45
+ </section>
46
+
47
+ <article class="mt-6 ">
48
+ <header>
49
+ <h2 class="text-gradient-blue font-semibold">Our Philosophy</h2>
50
+ </header>
51
+ <p>
52
+ Blue Bird was born out of a desire for a clean, performance-first approach to web development. We
53
+ believe in harnessing the raw power of Express.js and Nginx, stripping away unnecessary bloat, and
54
+ providing developers with a robust foundation that just works.
55
+ </p>
56
+ <p>
57
+ By separating the static frontend delivery (handled blazingly fast by Nginx) from the dynamic API
58
+ layer (powered by Express and Redis), Blue Bird achieves unparalleled performance out of the box.
59
+ </p>
60
+ </article>
61
+
62
+ <div class="px-4 py-4 mb-4">
63
+ <h2 class="text-gradient-blue font-semibold">Why Blue Bird?</h2>
64
+
65
+ <div class="grid cols-2 gap-4">
66
+ <div>
67
+ <details open>
68
+ <summary>Zero Config Docker</summary>
69
+ <p>Go from development to production seamlessly with ready-to-use
70
+ Docker orchestration for
71
+ SQLite, MySQL, PostgreSQL, and Redis.</p>
72
+ </details>
73
+ <details open>
74
+ <summary>Military Grade Security</summary>
75
+ <p>Built-in AES-256-GCM JWT encryption, secure HttpOnly cookie
76
+ sessions, helmet headers, and
77
+ route rate limiting.</p>
78
+ </details>
79
+ </div>
80
+ <div>
81
+ <details open>
82
+ <summary>High Performance Layer</summary>
83
+ <p>Redis caching for the data layer and Nginx static delivery with
84
+ 1-month browser asset
85
+ caching.</p>
86
+ </details>
87
+ <details open>
88
+ <summary>Pure Semantic HTML &amp; CSS</summary>
89
+ <p>No bloated frontend frameworks or heavy node compile steps. Write
90
+ clean, accessible code
91
+ close to the metal.</p>
92
+ </details>
93
+ </div>
94
+ </div>
95
+ </article>
96
+
97
+ <article class="">
98
+ <header>
99
+ <h2 class="text-gradient-blue font-semibold">Core Architecture Summary</h2>
100
+ </header>
101
+ <table class="table table-hover">
102
+ <thead>
103
+ <tr>
104
+ <th>Layer</th>
105
+ <th>Technology</th>
106
+ <th>Role</th>
107
+ </tr>
108
+ </thead>
109
+ <tbody>
110
+ <tr>
111
+ <td><strong>Frontend</strong></td>
112
+ <td>Pure Semantic HTML5 + <a href="https://seip25.github.io/Blue-bird-css/"
113
+ target="_blank">Blue Bird CSS</a></td>
114
+ <td>Static rendering served directly via Nginx</td>
115
+ </tr>
116
+ <tr>
117
+ <td><strong>Backend</strong></td>
118
+ <td>Node.js + Express + PM2</td>
119
+ <td>High-performance REST API services</td>
120
+ </tr>
121
+ <tr>
122
+ <td><strong>Cache</strong></td>
123
+ <td>Redis / In-Memory RAM</td>
124
+ <td>Sub-millisecond route &amp; query caching</td>
125
+ </tr>
126
+ <tr>
127
+ <td><strong>Database</strong></td>
128
+ <td>SQLite (WAL) / PostgreSQL / MySQL</td>
129
+ <td>Unified driver with connection pooling</td>
130
+ </tr>
131
+ </tbody>
132
+ </table>
133
+ </article>
134
+
135
+
136
+ </div>
137
+ </main>
138
+
139
+ <footer>
140
+ <div class="footer-content">
141
+ <p>Powered by <strong class="text-gradient">Blue Bird Framework</strong> &amp;
142
+ <strong class="text-gradient-blue">
143
+ <a href="https://seip25.github.io/Blue-bird-css/" target="_blank">Blue Bird
144
+ CSS</a>
145
+ </strong>.
146
+ </p>
147
+ <div class="lang-switcher">
148
+ <a href="/" class="lang-link">Home</a>
149
+ <a href="/about" class="lang-link">About</a>
150
+ <a href="https://github.com/seip25/Blue-bird" target="_blank" class="github-star mt-2">&#9733;
151
+ GitHub</a>
152
+ </div>
153
+ </div>
154
+ </footer>
155
+ </body>
156
+
108
157
  </html>