有个事实我得反复交代:我不会写代码。这意味着我不能手写一个 Node.js 后端、不会配 Webpack、没用过 Docker。但我的博客已经稳定运行了一个月,发了 28 篇文章,支持分类筛选、玻璃拟态动画、HTTPS 全链路加密——而且整个站点的全部代码就是 28 个 HTML 文件,没有任何构建工具,没有任何数据库,没有任何第三方 CDN。
这篇文章就是我的坦诚交代:一个非程序员是怎么把内容发到互联网上的——从 CSS 怎么写,到服务器怎么配,到每次更新怎么上线,全链条拆解给你看。
先把最核心的问题说清楚:
| 层 | 用了什么 | 没用什么 |
|---|---|---|
| 内容 | 纯 HTML 文件,每篇文章一个 .html | 没有 Markdown → HTML 转换,没有 CMS |
| 样式 | 内联 CSS,230 行 | 没有 Sass/Less,没有 Tailwind,没有 CSS 框架 |
| 交互 | 原生 JavaScript,50 行 | 没有 React/Vue/jQuery,没有 npm install |
| 文章管理 | JS 数组 ARTICLES(首页读取) | 没有数据库,没有 CMS 后台 |
| 服务器 | Nginx 直接 serve 静态文件 | 没有 Node.js/Python 进程,没有反向代理 |
| 部署 | 腾讯云 Lighthouse + AI 自动上传 | 没用 Git push、没用 CI/CD、没用 Docker |
总结成一句话:28 个 .html 文件丢在 Nginx 的一个目录里,加上 HTTPS 证书,完事。
这个架构在程序员圈子里叫「静态站点」,但比静态站点生成器(Hugo / Jekyll / Hexo)更极端——连生成这一步都省了,直接用原始 HTML。
所有颜色都用 CSS 自定义属性定义在 :root 里,改一个变量全站生效:
:root {
--bg: #070b18; /* 深空蓝背景 */
--p: #3a8bff; /* 主蓝色 */
--v: #8b5cf6; /* 紫色 */
--t: #19e3b1; /* 青绿色 */
--brand: #fa8c16; /* 品牌橙(重点色) */
--glass: rgba(255,255,255,.045); /* 半透明底 */
--line: rgba(255,255,255,.10); /* 边框线 */
--txt: #eaf0ff; /* 正文白 */
--dim: #9fb0d0; /* 辅助灰 */
}
这套变量系统意味着:如果哪天想换一套配色方案,只需要改 9 个变量值,不需要碰任何其他代码。
博客的背景不是纯色,而是四个巨大模糊光斑在缓慢浮动:
<div class="auras">
<span></span><span></span><span></span><span></span>
</div>
.auras span {
position: fixed;
border-radius: 50%;
filter: blur(90px); /* 高斯模糊 90px */
opacity: 0.22;
animation: aurasFloat 18s ease-in-out infinite;
}
/* 四个光斑:蓝色左上、紫色右上、橙色左下、青色右下 */
.auras span:nth-child(1) {
width: 420px; height: 420px;
background: var(--p); left: -100px; top: -60px;
}
/* ... 其他三个同理 */
原理:position: fixed 让光斑脱离文档流不抢占空间,filter: blur(90px) 产生柔和渐变,opacity: 0.22 降低浓度不刺眼。四个光斑用不同颜色、不同位置、不同的 animation-delay,形成持续变化的色彩氛围。
.card {
background: rgba(255,255,255,.06); /* 极低透明度 */
border: 1px solid rgba(255,255,255,.10);
border-radius: 20px;
backdrop-filter: blur(20px); /* 毛玻璃核心 */
}
/* 鼠标悬浮光晕追踪 */
.card::before {
content: '';
position: absolute; inset: 0;
background: radial-gradient(
600px circle at var(--mx,50%) var(--my,50%),
rgba(250,140,22,.08), transparent 60%
);
opacity: 0;
transition: opacity .4s;
}
.card:hover::before { opacity: 1; }
/* 悬浮上浮 */
.card:hover {
transform: translateY(-4px);
box-shadow: 0 20px 60px rgba(0,0,0,.4),
0 0 40px rgba(250,140,22,.06);
}
这里面有三个技术点:
--mx 和 --my 是 JS 通过 mousemove 动态注入的鼠标坐标,CSS radial-gradient 根据这两个变量在卡片上产生一个跟随鼠标的橙光高亮。transition: all .35s 让悬浮上浮、边框变色、阴影出现全部是平滑过渡而非瞬间切换。.grid {
display: grid;
grid-template-columns: 1fr; /* 手机:1列 */
}
@media (min-width: 860px) {
.grid { grid-template-columns: repeat(2, 1fr); } /* 平板:2列 */
}
@media (min-width: 1200px) {
.grid { grid-template-columns: repeat(3, 1fr); } /* 桌面:3列 */
}
CSS Grid 天然响应式,不需要 JavaScript 监听窗口尺寸。
.hero h1 {
background: linear-gradient(
135deg, #fff 0%, var(--brand) 40%,
var(--p) 70%, var(--v) 100%
);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
background-clip: text 这个属性让渐变只显示在文字形状里,文字之外透明。注意需要 -webkit- 前缀兼容 Chrome/Safari。
首页的所有文章卡片的源数据就是一个 JSON 数组:
const ARTICLES = [
{
"slug": "29",
"title": "从零到上线:一个非程序员是怎么把博客发到互联网上的",
"date": "2026-07-31",
"category": "开发技术 · 部署运维",
"main_cat": "开发技术",
"emoji": "🛠️",
"excerpt": "有个事实我得反复交代:我不会写代码...",
"reading_min": 8
},
// ... 更多文章
];
没有数据库、没有 API 请求、没有 JSON 文件加载。数据直接内联在 HTML 的 <script> 标签里,页面加载瞬间可用。
function renderCards(arts) {
const g = document.getElementById('grid');
g.innerHTML = arts.map(a => `
<a class="card" href="${a.slug}.html">
<div class="card-top">
<span class="card-emoji">${a.emoji}</span>
<span class="card-tag ${catClass(a.category)}">${a.main_cat}</span>
</div>
<h2>${a.title}</h2>
<p class="excerpt">${a.excerpt}</p>
<div class="card-meta">
<span>📅 ${a.date}</span>
<span>⏱ ${a.reading_min} 分钟</span>
</div>
</a>
`).join('');
}
关键点:ES6 模板字符串 `...` + map().join(''),29 篇文章一次遍历生成全部 DOM,不存在「渲染性能」问题。
function filter(cat) {
const arts = ARTICLES.filter(a =>
a.category.includes(cat)
);
renderCards(arts); // 用筛选结果重新渲染
}
分类筛选就是「数组过滤 + 重新渲染」,不请求后端,不刷新页面,瞬间切换。
document.getElementById('grid').addEventListener('mousemove', e => {
const card = e.target.closest('.card');
if (!card) return;
const rect = card.getBoundingClientRect();
card.style.setProperty('--mx', (e.clientX - rect.left) + 'px');
card.style.setProperty('--my', (e.clientY - rect.top) + 'px');
});
鼠标在卡片上移动时,把相对于卡片左上角的坐标写入 CSS 变量 --mx/--my,CSS 的 radial-gradient 会以此为圆心画出跟随鼠标的橙色光晕。
博客运行在腾讯云轻量应用服务器(Lighthouse)上,配置:
| 项目 | 详情 |
|---|---|
| 服务器类型 | 腾讯云 Lighthouse(轻量应用服务器) |
| 地域 | ap-shanghai(上海) |
| 系统 | CentOS / Nginx |
| 域名 | www.y2ksoft.cn |
| 证书 | Let's Encrypt 免费 SSL(自动续期) |
| 博客路径 | /var/www/y2ksoft/blog/ |
Nginx 配置非常简洁——对于静态 HTML 文件,只需要指定 root 目录就行:
server {
listen 443 ssl;
server_name www.y2ksoft.cn;
root /var/www/y2ksoft; # 网站根目录
# SSL 证书(Let's Encrypt 自动签发)
ssl_certificate /etc/letsencrypt/live/www.y2ksoft.cn/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/www.y2ksoft.cn/privkey.pem;
}
# HTTP 自动跳转 HTTPS
server {
listen 80;
server_name www.y2ksoft.cn;
return 301 https://www.y2ksoft.cn$request_uri;
}
用户访问 https://www.y2ksoft.cn/blog/29.html 时,Nginx 做的事情就三步:
/var/www/y2ksoft/blog/ 目录下找到 29.html 文件Content-Type: text/html 头不需要任何应用服务器进程。Nginx 自己就是个高性能静态文件服务器,单台机器支撑每秒几万次请求毫无压力。
HTTPS 证书用的是 Let's Encrypt,完全免费,自动续期:
# 申请证书(只需一次)
certbot --nginx -d www.y2ksoft.cn -d y2ksoft.cn
# 自动续期(certbot 会自动加 cron 定时任务)
certbot renew --dry-run # 测试续期是否正常
证书每 90 天自动续期一次,不需要任何手动操作。
这是最核心的部分——每次写完一篇文章,怎么让它出现在互联网上?
本地 Windows 电脑 腾讯云 Lighthouse(上海)
┌─────────────────────┐ ┌─────────────────────────┐
│ F:\Y2Ksoft系统\blog\ │ │ /var/www/y2ksoft/blog/ │
│ │ │ │
│ 29.html ← 新文章 │ ──上传──→ │ 29.html │
│ index.html ← 更新 │ │ index.html │
│ img/... │ │ img/... │
└─────────────────────┘ └─────────────────────────┘
│ │
│ Lighthouse 集成 │
│ deploy_project_preparation │
└────────────────────────────────────┘
↓
execute_command:
cp 文件到 /var/www/y2ksoft/blog/
以下步骤我不需要手动执行任何一条命令——全部由 AI 通过 Lighthouse 集成自动完成:
第 1 步:AI 连接 Lighthouse
# AI 内部调用
invoke_integration("lighthouse", "deploy")
# → 验证腾讯云账号凭证,连接成功
第 2 步:查询可用服务器
# AI 内部调用
analyze_lighthouse_instances() # 查所有地域有哪些服务器
describe_running_instances("ap-shanghai") # 找上海地域运行中的实例
# → 返回: lhins-n6a6ub6y (111.229.25.16)
第 3 步:上传文件
# AI 内部调用
deploy_project_preparation(
FolderPath="F:\\Y2Ksoft系统\\blog\\_deploy\\",
InstanceId="lhins-n6a6ub6y",
Region="ap-shanghai"
)
# → 文件被打包上传到 /root/_deploy_20260731220856/
第 4 步:复制到网站目录
# AI 内部调用
execute_command(
Command="cp /root/_deploy_xxx/29.html /var/www/y2ksoft/blog/ &&
cp /root/_deploy_xxx/index.html /var/www/y2ksoft/blog/ &&
echo 'done'"
)
# → 文件到位,Nginx 即刻生效
第 5 步:线上验证
# AI 内部调用
web_fetch("https://www.y2ksoft.cn/blog/29.html")
# → 检查内容是否完整,确认上线成功
整个流程从「我说一句部署博客」到文章上线,不超过 2 分钟。
专业团队的部署流程通常是:
git push → GitHub Actions → npm build → rsync → 服务器重启
但这套流程对单文件静态站点来说太重了:
极简架构的极简部署——这是刻意为之,不是能力不足。
最早尝试用 scp 直接上传:
scp 29.html root@111.229.25.16:/var/www/y2ksoft/blog/
但本地电脑没有服务器的 SSH 私钥,返回 Permission denied (publickey)。
解决方案:走 Lighthouse 集成。Lighthouse 集成不依赖本地 SSH 密钥,而是通过腾讯云 API 直接在服务器上执行命令——绕过了 SSH 认证问题。这是「云厂商集成」相比「裸 SSH」的核心优势。
| 项目 | 费用 | 周期 |
|---|---|---|
| 腾讯云 Lighthouse 服务器 | 约 ¥70/月 | 月付 |
| 域名 y2ksoft.cn | 约 ¥60/年 | 年付 |
| SSL 证书(Let's Encrypt) | 免费 | 自动续期 |
| 代码编辑器 / 开发工具 | 免费 | — |
| AI 编程助手 | ChatGPT / Claude | 月付订阅 |
| 合计 | 约 ¥75/月 |
对比传统建站:WordPress 虚拟主机约 ¥30-100/月,但需要自己装插件、调主题、防攻击。静态站点方案虽然需要一台云服务器,但一台服务器同时跑了博客、官网、多个 ERP 系统的前端和 API,分摊下来博客的成本接近零。
从 0 到上线,一篇博客文章的标准生产流程:
| 步骤 | 做什么 | 谁做 | 耗时 |
|---|---|---|---|
| 1. 确定选题 | 从 ERP 开发过程中提炼值得分享的经验 | 我 | 5 分钟 |
| 2. 写正文 | 口述思路,AI 组织语言生成 HTML | AI | 10 分钟 |
| 3. 更新首页 | 在 index.html 的 ARTICLES 数组里加一条新记录 | AI | 1 分钟 |
| 4. 部署上线 | Lighthouse 集成上传 + 验证 | AI | 2 分钟 |
| 5. 推广分发 | 生成 CSDN MD 版本、发微信群等 | AI | 3 分钟 |
从想法到全网可见,20 分钟。这个速度在传统的内容生产流程中是不可想象的——WordPress 光是登录后台、填写标题、粘贴内容、选分类、设置 SEO、发布预览就要 10 分钟。
rss.xml,内容从 ARTICLES 数组自动生成回头看我这一套方案,所有技术决策都有一个共同原则:选最简单的那个,直到它不够用为止。
这不是懒——这是工程上的克制。每少一个依赖,就少一个可能出问题的点,就少一个需要学习的概念,就少一个需要维护的东西。
一个非程序员能在 30 天内写出 29 篇文章 + 搭建整套博客体系,不是因为我聪明,而是因为我选了一条最简单的路,并且 AI 帮我把这条路上的每一步都走完了。
如果你想自己搭一个类似的博客,参考这篇文章就够了。如果你不想自己动手,告诉我你的需求,我让 AI 帮你做。
如果这篇文章对你有帮助,分享给需要的朋友