feat(blueprints): launch 3 system blueprints, 12 topology layers & in-article mounting
Deploy / build (push) Successful in 24s
Deploy / build (push) Successful in 24s
This commit is contained in:
1 parent
419c962e2f
commit
c5e473aaad
103 files changed
+1290
-2
No files matched your search
@@ -0,0 +1,117 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import PostList from '../../components/PostList.astro';
|
||||
import { BLUEPRINT_SLUGS, getBlueprint } from '../../lib/blueprints';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { isEn } from '../../lib/lang';
|
||||
import { SITE } from '../../config';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return BLUEPRINT_SLUGS.map((slug) => ({
|
||||
params: { slug },
|
||||
}));
|
||||
}
|
||||
|
||||
const { slug } = Astro.params;
|
||||
const bp = getBlueprint(slug);
|
||||
|
||||
if (!bp) {
|
||||
throw new Error(`Blueprint not found: ${slug}`);
|
||||
}
|
||||
|
||||
const allPosts = await getCollection('posts', isEn);
|
||||
const mountedPosts = allPosts.filter((p) => p.data.blueprint === bp.slug);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${bp.title.en} — System Blueprint — Mr Hoelee`}
|
||||
description={bp.tagline.en}
|
||||
switchHref={`/zh/blueprints/${bp.slug}/`}
|
||||
altLocaleUrl={`${SITE.url}/zh/blueprints/${bp.slug}/`}
|
||||
>
|
||||
<nav class="meta-tag" style="margin-bottom: 1.25rem;">
|
||||
<a href="/blueprints/" style="color: inherit; text-decoration: none;">← All System Blueprints</a>
|
||||
</nav>
|
||||
|
||||
<article class="blueprint-article">
|
||||
<!-- Block 1: Hero & High-Density Stats -->
|
||||
<header class="blueprint-hero">
|
||||
<div class="bp-card-top" style="margin-bottom: 0.5rem;">
|
||||
<span class="bp-card-badge">Production Blueprint</span>
|
||||
<span class="bp-card-metric">{bp.metrics.en}</span>
|
||||
</div>
|
||||
<h1>{bp.title.en}</h1>
|
||||
<p class="blueprint-tagline">{bp.tagline.en}</p>
|
||||
|
||||
<div class="blueprint-stats-grid">
|
||||
{bp.stats.map((st) => (
|
||||
<div class="blueprint-stat-card">
|
||||
<div class="blueprint-stat-val">{st.value}</div>
|
||||
<div class="blueprint-stat-label">{st.label.en}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Interactive Layer Jump Bar -->
|
||||
<nav class="layer-nav-bar" aria-label="Quick jump to blueprint layer">
|
||||
<span class="layer-nav-label">Topology Layers:</span>
|
||||
{bp.layers.map((layer) => (
|
||||
<a class="layer-nav-pill" href={`#${layer.slug}`}>
|
||||
{layer.slug.split('-')[0]}: {layer.name.en.split(':')[1]?.trim() || layer.name.en}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<!-- Block 2: Architectural Decisions & Production Trade-offs -->
|
||||
<section class="tradeoffs-box">
|
||||
<h2>{bp.tradeOffs.title.en}</h2>
|
||||
<p>{bp.tradeOffs.content.en}</p>
|
||||
</section>
|
||||
|
||||
<!-- Block 3: L1..L4 Layer Guides & Mounted Posts -->
|
||||
<section class="blueprint-layers-section">
|
||||
{bp.layers.map((layer) => {
|
||||
const layerPosts = mountedPosts.filter((p) => p.data.blueprintLayer === layer.slug);
|
||||
return (
|
||||
<div class="layer-block" id={layer.slug}>
|
||||
<div class="layer-head-row">
|
||||
<h2>{layer.name.en}</h2>
|
||||
</div>
|
||||
<div class="layer-scope">Scope: {layer.scope.en}</div>
|
||||
<p class="layer-summary-text">{layer.summary.en}</p>
|
||||
|
||||
<div class="layer-tech-tags">
|
||||
{layer.keyTech.map((tech) => (
|
||||
<span class="layer-tech-pill">{tech}</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="layer-posts-container">
|
||||
<div class="layer-posts-title">
|
||||
{layerPosts.length > 0
|
||||
? `Mounted Technical Write-ups (${layerPosts.length})`
|
||||
: 'Referenced Production Stacks & Runbooks'}
|
||||
</div>
|
||||
|
||||
{layerPosts.length > 0 ? (
|
||||
<PostList posts={layerPosts} limit={10} lang="en" />
|
||||
) : (
|
||||
<p style="font-size: 0.9rem; color: var(--muted); margin: 0.5rem 0;">
|
||||
This architectural layer is backed by live production configurations in our primary repository. Related deep-dive case studies are referenced across the broader documentation.
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
|
||||
<!-- Block 4: Contextual CTA -->
|
||||
<section class={`blueprint-cta bp-cta-${bp.cta.track}`}>
|
||||
<h3>{bp.cta.heading.en}</h3>
|
||||
<p>{bp.cta.body.en}</p>
|
||||
<a class="btn btn-primary" href={bp.cta.buttonLink}>{bp.cta.buttonText.en}</a>
|
||||
</section>
|
||||
</article>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||
import { getAllBlueprints } from '../../lib/blueprints';
|
||||
import { SITE } from '../../config';
|
||||
|
||||
const blueprints = getAllBlueprints();
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="System Blueprints — Production Architecture Guides — Mr Hoelee"
|
||||
description="Explore three end-to-end architectural blueprints connecting 162 self-hosted containers, local GPU AI automation, and SME sovereign digital assets."
|
||||
switchHref="/zh/blueprints/"
|
||||
altLocaleUrl={`${SITE.url}/zh/blueprints/`}
|
||||
>
|
||||
<div class="page-head">
|
||||
<div class="meta-tag">Production Architecture</div>
|
||||
<h1>System Blueprints</h1>
|
||||
<p class="lede">
|
||||
Instead of scattered chronological posts, these <strong>three architectural blueprints</strong> serve as the foundational pillars of everything I run. Each blueprint provides an interactive topology from physical hardware up to application code, organizing 91 bilingual write-ups into four clear, battle-tested engineering layers.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="blueprints-grid">
|
||||
{blueprints.map((bp, idx) => (
|
||||
<a class="blueprint-card" href={`/blueprints/${bp.slug}/`}>
|
||||
<div class="bp-card-top">
|
||||
<span class="bp-card-badge">Pillar 0{idx + 1}</span>
|
||||
<span class="bp-card-metric">{bp.metrics.en}</span>
|
||||
</div>
|
||||
<h2>{bp.title.en}</h2>
|
||||
<p class="bp-tagline">{bp.tagline.en}</p>
|
||||
|
||||
<div class="bp-layers-preview">
|
||||
{bp.layers.map((layer) => (
|
||||
<div class="bp-layer-item">
|
||||
<span class="bp-l-num">{layer.slug.split('-')[0]}</span>
|
||||
<strong>{layer.name.en.split(':')[1]?.trim() || layer.name.en}</strong>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="bp-card-cta">
|
||||
Explore Blueprint & Layer Guides →
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="blueprint-cta bp-cta-hiring">
|
||||
<h3>Looking for Full-Ownership Engineering?</h3>
|
||||
<p>
|
||||
Whether you need robust Linux kernel and container infrastructure or autonomous AI workflows bound to deterministic state machines, explore my background and live system evidence.
|
||||
</p>
|
||||
<a class="btn btn-primary" href="/about/#hiring">View Tech Stack & Case Studies →</a>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
@@ -4,6 +4,7 @@ import AuthorCard from '../../components/AuthorCard.astro';
|
||||
import TableOfContents from '../../components/TableOfContents.astro';
|
||||
import ExecutiveSummary from '../../components/ExecutiveSummary.astro';
|
||||
import DynamicCTA from '../../components/DynamicCTA.astro';
|
||||
import { getBlueprint } from '../../lib/blueprints';
|
||||
import { getCollection, render } from 'astro:content';
|
||||
import { postLang } from '../../lib/lang';
|
||||
import { countWords, readingMinutes } from '../../lib/reading-time';
|
||||
@@ -29,6 +30,9 @@ const lang = postLang(post.slug);
|
||||
const words = countWords(post.body);
|
||||
const minutes = readingMinutes(post.body);
|
||||
|
||||
const bpMeta = post.data.blueprint ? getBlueprint(post.data.blueprint) : undefined;
|
||||
const bpLayer = bpMeta && post.data.blueprintLayer ? bpMeta.layers.find((l) => l.slug === post.data.blueprintLayer) : undefined;
|
||||
|
||||
const fmt = (d: Date) =>
|
||||
d.toLocaleDateString(lang === 'zh' ? 'zh-CN' : 'en-US', { year: 'numeric', month: 'long', day: 'numeric' });
|
||||
|
||||
@@ -106,6 +110,14 @@ const jsonLd = {
|
||||
>
|
||||
<script type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
|
||||
<article>
|
||||
{bpMeta && bpLayer && (
|
||||
<a class="article-blueprint-badge" href={lang === 'zh' ? `/zh/blueprints/${bpMeta.slug}/#${bpLayer.slug}` : `/blueprints/${bpMeta.slug}/#${bpLayer.slug}`}>
|
||||
<span>📌 {lang === 'zh' ? '隶属于架构蓝图:' : 'Part of Blueprint:'}</span>
|
||||
<strong>{lang === 'zh' ? bpMeta.title.zh.split(':')[0] : bpMeta.title.en.split(':')[0]}</strong>
|
||||
<span>→</span>
|
||||
<span>{lang === 'zh' ? bpLayer.name.zh : bpLayer.name.en}</span>
|
||||
</a>
|
||||
)}
|
||||
<header class="article-head">
|
||||
<h1>{post.data.title}</h1>
|
||||
<div class="meta">
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
---
|
||||
import BaseLayout from '../../../layouts/BaseLayout.astro';
|
||||
import PostList from '../../../components/PostList.astro';
|
||||
import { BLUEPRINT_SLUGS, getBlueprint } from '../../../lib/blueprints';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { isZh } from '../../../lib/lang';
|
||||
import { SITE } from '../../../config';
|
||||
|
||||
export async function getStaticPaths() {
|
||||
return BLUEPRINT_SLUGS.map((slug) => ({
|
||||
params: { slug },
|
||||
}));
|
||||
}
|
||||
|
||||
const { slug } = Astro.params;
|
||||
const bp = getBlueprint(slug);
|
||||
|
||||
if (!bp) {
|
||||
throw new Error(`Blueprint not found: ${slug}`);
|
||||
}
|
||||
|
||||
const allPosts = await getCollection('posts', isZh);
|
||||
const mountedPosts = allPosts.filter((p) => p.data.blueprint === bp.slug);
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title={`${bp.title.zh} — 系统架构蓝图 — Mr Hoelee`}
|
||||
description={bp.tagline.zh}
|
||||
lang="zh"
|
||||
switchHref={`/blueprints/${bp.slug}/`}
|
||||
altLocaleUrl={`${SITE.url}/blueprints/${bp.slug}/`}
|
||||
>
|
||||
<nav class="meta-tag" style="margin-bottom: 1.25rem;">
|
||||
<a href="/zh/blueprints/" style="color: inherit; text-decoration: none;">← 全部系统架构蓝图</a>
|
||||
</nav>
|
||||
|
||||
<article class="blueprint-article">
|
||||
<!-- Block 1: Hero & High-Density Stats -->
|
||||
<header class="blueprint-hero">
|
||||
<div class="bp-card-top" style="margin-bottom: 0.5rem;">
|
||||
<span class="bp-card-badge">生产级系统蓝图</span>
|
||||
<span class="bp-card-metric">{bp.metrics.zh}</span>
|
||||
</div>
|
||||
<h1>{bp.title.zh}</h1>
|
||||
<p class="blueprint-tagline">{bp.tagline.zh}</p>
|
||||
|
||||
<div class="blueprint-stats-grid">
|
||||
{bp.stats.map((st) => (
|
||||
<div class="blueprint-stat-card">
|
||||
<div class="blueprint-stat-val">{st.value}</div>
|
||||
<div class="blueprint-stat-label">{st.label.zh}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Interactive Layer Jump Bar -->
|
||||
<nav class="layer-nav-bar" aria-label="快捷跳转到分层">
|
||||
<span class="layer-nav-label">拓扑分层:</span>
|
||||
{bp.layers.map((layer) => (
|
||||
<a class="layer-nav-pill" href={`#${layer.slug}`}>
|
||||
{layer.slug.split('-')[0]}: {layer.name.zh.split(':')[1]?.trim() || layer.name.zh}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<!-- Block 2: Architectural Decisions & Production Trade-offs -->
|
||||
<section class="tradeoffs-box">
|
||||
<h2>{bp.tradeOffs.title.zh}</h2>
|
||||
<p>{bp.tradeOffs.content.zh}</p>
|
||||
</section>
|
||||
|
||||
<!-- Block 3: L1..L4 Layer Guides & Mounted Posts -->
|
||||
<section class="blueprint-layers-section">
|
||||
{bp.layers.map((layer) => {
|
||||
const layerPosts = mountedPosts.filter((p) => p.data.blueprintLayer === layer.slug);
|
||||
return (
|
||||
<div class="layer-block" id={layer.slug}>
|
||||
<div class="layer-head-row">
|
||||
<h2>{layer.name.zh}</h2>
|
||||
</div>
|
||||
<div class="layer-scope">范畴: {layer.scope.zh}</div>
|
||||
<p class="layer-summary-text">{layer.summary.zh}</p>
|
||||
|
||||
<div class="layer-tech-tags">
|
||||
{layer.keyTech.map((tech) => (
|
||||
<span class="layer-tech-pill">{tech}</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="layer-posts-container">
|
||||
<div class="layer-posts-title">
|
||||
{layerPosts.length > 0
|
||||
? `本层挂载实战手记 (${layerPosts.length})`
|
||||
: '生产环境参考栈与运行规约'}
|
||||
</div>
|
||||
|
||||
{layerPosts.length > 0 ? (
|
||||
<PostList posts={layerPosts} limit={10} lang="zh" />
|
||||
) : (
|
||||
<p style="font-size: 0.9rem; color: var(--muted); margin: 0.5rem 0;">
|
||||
本拓扑分层完全由我们在主仓库中的实际生产配置运行守护,对应的深度复盘与排障日志收录于相关专题中。
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
|
||||
<!-- Block 4: Contextual CTA -->
|
||||
<section class={`blueprint-cta bp-cta-${bp.cta.track}`}>
|
||||
<h3>{bp.cta.heading.zh}</h3>
|
||||
<p>{bp.cta.body.zh}</p>
|
||||
<a class="btn btn-primary" href={bp.cta.buttonLink.replace('/about/', '/zh/about/')}>{bp.cta.buttonText.zh}</a>
|
||||
</section>
|
||||
</article>
|
||||
</BaseLayout>
|
||||
@@ -0,0 +1,57 @@
|
||||
---
|
||||
import BaseLayout from '../../../layouts/BaseLayout.astro';
|
||||
import { getAllBlueprints } from '../../../lib/blueprints';
|
||||
import { SITE } from '../../../config';
|
||||
|
||||
const blueprints = getAllBlueprints();
|
||||
---
|
||||
|
||||
<BaseLayout
|
||||
title="系统蓝图 — 生产级系统架构全景指南 — Mr Hoelee"
|
||||
description="探索支撑 162 个自托管生产容器、本地 GPU AI 自动化与中小企业数字资产的三大顶层系统架构蓝图。"
|
||||
lang="zh"
|
||||
switchHref="/blueprints/"
|
||||
altLocaleUrl={`${SITE.url}/blueprints/`}
|
||||
>
|
||||
<div class="page-head">
|
||||
<div class="meta-tag">生产级系统架构</div>
|
||||
<h1>系统架构蓝图</h1>
|
||||
<p class="lede">
|
||||
打破传统的碎片化时间线归档,这<strong>三大系统蓝图(Pillar Blueprints)</strong>是我所管理的自托管生产体系的顶层基石。每个蓝图均包含从物理硬件底座到应用层的交互式拓扑全景,将 91 篇实战手记精确归拢至四个清晰的工程分层中。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="blueprints-grid">
|
||||
{blueprints.map((bp, idx) => (
|
||||
<a class="blueprint-card" href={`/zh/blueprints/${bp.slug}/`}>
|
||||
<div class="bp-card-top">
|
||||
<span class="bp-card-badge">基石 0{idx + 1}</span>
|
||||
<span class="bp-card-metric">{bp.metrics.zh}</span>
|
||||
</div>
|
||||
<h2>{bp.title.zh}</h2>
|
||||
<p class="bp-tagline">{bp.tagline.zh}</p>
|
||||
|
||||
<div class="bp-layers-preview">
|
||||
{bp.layers.map((layer) => (
|
||||
<div class="bp-layer-item">
|
||||
<span class="bp-l-num">{layer.slug.split('-')[0]}</span>
|
||||
<strong>{layer.name.zh.split(':')[1]?.trim() || layer.name.zh}</strong>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="bp-card-cta">
|
||||
查阅架构拓扑与分层实战指南 →
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="blueprint-cta bp-cta-hiring">
|
||||
<h3>需要具备全链路实战能力的架构与 DevOps 交付?</h3>
|
||||
<p>
|
||||
无论是从零搭建硬化的生产级 Linux 容器基础设施,还是构建接入确定性状态机与沙箱的私有 AI 业务系统,欢迎查阅实战履历与合作方案。
|
||||
</p>
|
||||
<a class="btn btn-primary" href="/zh/about/#hiring">查阅技术栈与代表作 →</a>
|
||||
</div>
|
||||
</BaseLayout>
|
||||
Reference in new issue
Block a user