Osint-Witch/osint-witch.com
GitHub: Osint-Witch/osint-witch.com
一个基于 Astro 的静态网站模板,专供网络威胁情报(CTI)专业人员展示简历和分析文章,支持葡/英双语切换并可直接部署到 Cloudflare Pages。
Stars: 0 | Forks: 0
# CTIWitch — Cyber Threat Intelligence 作品集
**Cyber Threat Intelligence** 专业人员的个人**双语 (PT/EN)** 作品集,使用 **Astro** 和 **Content Collections** 构建,并输出**100% 静态**(`output: 'static'`)—— 准备就绪可直接发布到 **Cloudflare Pages**,无需任何后端。
包含 CV/resume、带有标签过滤和搜索功能的 write-ups 博客、带有 syntax highlight 的文章页面、按路由持久化的 PT|EN 切换,以及出现在所有页面上的伴侣小云朵(CSS/SVG + 纯 JS)。
## 🚀 本地运行
要求 **Node.js 18.17+**(或 20+)。
```
npm install
npm run dev # http://localhost:4321
```
生产环境构建与预览:
```
npm run build # gera /dist (HTML estático)
npm run preview # serve /dist localmente
```
## ☁️ 部署到 Cloudflare Pages
1. 将此项目上传到 Git 仓库(GitHub/GitLab)。
2. 在 Cloudflare Pages 中 → **Create a project** → 连接到该仓库。
3. 构建设置:
- **Framework preset:** `Astro`
- **Build command:** `npm run build`
- **Build output directory:** `dist`
4. 部署。无需环境变量,也无需后端。
## 🌎 双语(PT/EN)的工作原理
**界面**为葡萄牙语;**内容**(CV 和文章)提供 PT 和 EN 两种版本。
语言由**路由**决定,因此**在导航期间持久保存,无需使用 `localStorage`/`sessionStorage`**:
| 语言 | 首页 | 博客 | 文章 |
| --- | --- | --- | --- |
| PT(默认) | `/` | `/blog` | `/blog/` |
| EN | `/en/` | `/en/blog` | `/en/blog/` |
**PT|EN 切换**(右上角)只是一个指向另一种语言对应 URL 的链接。在一篇文章中,得益于**共享 slug**,它会指向另一种语言的**相同 write-up**。如果该版本不存在,按钮将被优雅地**禁用**(`indisponível neste idioma`),且不会破坏导航。相关逻辑位于 `src/i18n/ui.ts` 和 `src/lib/posts.ts` 中。
## ✍️ 如何添加 write-up
策略:**每个语言一个文件,且共享 slug**。
在 frontmatter 中创建两个具有**相同 `slug`** 的文件:
```
src/content/posts/pt/meu-write-up.md (lang: pt)
src/content/posts/en/meu-write-up.md (lang: en)
```
Frontmatter(在 `src/content.config.ts` 中进行类型化和验证):
```
---
title: "Título do post"
date: 2026-06-01
lang: pt # 'pt' | 'en'
slug: meu-write-up # IGUAL nas duas versões → liga PT⇄EN
tags: ["OSINT", "IOC"]
summary: "Resumo curto que aparece no card do blog."
draft: false # true = oculto no build
cover: "linear-gradient(135deg,#2a1f5c,#7c5cff 60%,#2ee6d6)" # opcional
---
## 您的 markdown
Blocos de código ganham **syntax highlight** automático (Shiki):
```python
print("hello, threat intel")
```
```
- Se um post existir **só em um idioma**, ele aparece apenas na listagem daquele
idioma; no outro, o toggle marca como indisponível.
- `draft: true` esconde o post no build de produção (aparece em `npm run dev`).
---
## 🧾 如何编辑 CV
Os dados do CV/home ficam em JSON, um por idioma:
```
src/data/cv.pt.json
src/data/cv.en.json
```
Edite os campos (`role`, `about`, `experience`, `skills`, `certs`, `contacts`…)
e a home se atualiza no próximo build. Para trocar o **PDF do CV**, substitua:
```
public/cv/cv-jady-pt.pdf
public/cv/cv-jady-en.pdf
```
(os arquivos atuais são placeholders; o botão de download aponta para eles).
---
## 🗂 结构
```
astro-site/
├── astro.config.mjs # output: 'static' + Shiki (syntax highlight)
├── package.json
├── public/
│ ├── favicon.svg
│ └── cv/ # CV 的 PDF 文件 (placeholders)
└── src/
├── content.config.ts # "posts" 集合的 schema + glob loader
├── content/posts/
│ ├── pt/*.md # PT 版本
│ └── en/*.md # EN 版本
├── data/
│ ├── cv.pt.json # 为首页提供数据 (PT)
│ └── cv.en.json # 为首页提供数据 (EN)
├── i18n/ui.ts # 界面字符串 + 语言/路由 helpers
├── lib/posts.ts # getCollection helpers (getPosts, hasVersion…)
├── styles/global.css # 柔和的 synthwave 主题 (tokens + classes)
├── components/
│ ├── Nav.astro
│ ├── LangToggle.astro
│ ├── CloudCompanion.astro # 小云朵 (CSS/SVG + JS, reduced-motion)
│ ├── Resume.astro # 首页/CV 主体
│ ├── BlogList.astro # grid + tag filter + search
│ ├── PostCard.astro
│ ├── PostArticle.astro
│ └── Footer.astro
├── layouts/Base.astro # , nav, footer 和小云朵 (global)
└── pages/
├── index.astro # 首页 PT
├── 404.astro
├── en/index.astro # 首页 EN
├── blog/index.astro # 博客 PT
├── blog/[slug].astro # 文章 PT (getStaticPaths)
├── en/blog/index.astro # 博客 EN
└── en/blog/[slug].astro # 文章 EN (getStaticPaths)
```
---
## ☁️ 云端
Vive no layout (`CloudCompanion.astro`), então aparece em todas as páginas.
Flutua com parallax leve no scroll, segue o cursor de forma preguiçosa, pisca,
tira soneca (💤) e, ao ser clicada, solta moeda/coração/estrela/nota com um
"poof". O **som** (tilim de varinha) é **opcional e desligado por padrão** —
ligável no botão 🔇 da barra. Respeita `prefers-reduced-motion` (fica estática).
---
## 笔记
- Os 3 write-ups inclusos são **exemplos ilustrativos** de CTI (substitua pelos
seus). O post `mitre-attack-mapping-apt` existe **só em PT** de propósito, para
demonstrar o estado "indisponível neste idioma".
- Sem dependências de backend, banco ou storage do navegador.
```
标签:Astro, Homebrew安装, MITM代理, 个人博客, 威胁情报, 开发者工具, 简历, 网络安全, 防御加固, 隐私保护, 静态网站