Generate tech profile
Skill jasonChen0604/codebase-to-portfolio/skills/generate-tech-profile
Turn your entire codebase history into a portfolio-ready tech profile — with any AI coding agent (Claude Code, Codex, Copilot, Cursor).
npx -y skills add jasonChen0604/codebase-to-portfolio --skill generate-tech-profileAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 29 days oldThe repository was created 29 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Generate a personal tech profile and project mapping from all latest-version project docs. Produces one Markdown file per configured language (tech-profile-<lang>.md), each a structured Markdown suitable for building a personal website skill tree / mind map. Triggers when the user says "generate tech profile", "build tech profile", "generate skill tree", "生成技術檔案", "產出個人技術樹", or "建立技術側寫".
SKILL.md
13.3 KB, as published. Nobody here has run it
Generate Tech Profile Skill
Goal
Read all project docs (doc_filename) from projects that have the latest skill_version, extract structured frontmatter data (tags, category, status, description, etc.), then generate one Markdown file per configured language (languages in config, default ["en"]):
tech-profile-en.md— English version (ifenis inlanguages)tech-profile-<lang>.md— one file per additional configured language, e.g.tech-profile-zh-TW.md
All files share the same data and structure, but differ in language for all human-readable text. All are designed to be consumed by a personal website as the data source for skill tree / mind map rendering.
Step 0: Read config
Read profile.config.json from the current working directory. If missing, tell the user to copy examples/profile.config.example.json to profile.config.json and fill it in, then stop.
profile.name— used in the document title (e.g.# <name> — Personal Tech Profile)doc_filename(defaultCLAUDE.md)languages(default["en"])timezone(default+00:00) — used forgenerated_atprivacy_blocklist(default[]) — additional names to sanitize out ofdisplay_name, on top of the built-in rules belowcustom_domains(default{}) — extra tag → domain mappings merged into the built-in domain table in Step 5
Execution Steps
Step 1: Get the latest version
Run the /get-latest-version skill to obtain the current latest skill_version string (e.g. "2.0").
- If
noneis returned, abort and tell the user to run/batch-initfirst.
Step 2: Filter projects with latest version
Read projects-list.md and filter rows where:
- "Active" column is ✅
- Doc-file column is ✅
- "Version" column equals the latest version string from Step 1
Collect each matching project's Path column value, expanding ~ via $HOME.
Step 3: Read each project's doc frontmatter
For each filtered project path, read <path>/<doc_filename> and extract the YAML frontmatter block (between the --- delimiters).
Extract these fields (use — or empty array if missing):
project_namecategorystatustags(array)one_line_descriptioncore_techdatabasedeploymentfeatured
Also read the ## 📋 Portfolio Summary section body to extract:
- The
Highlightsbullet point text (the key technical highlight)
Also record:
path— the project's absolute path (used for grouping in Step 3b)
After extracting fields, derive a display_name for each project using this logic:
Privacy-Safe Display Name Rules
The core rule: display_name must describe only system function — never a client, company, brand, or product name.
Two categories of names require sanitization:
Category 1 — Project code prefixes (structural identifiers in project_name):
- Patterns: any 2–3 letter prefix followed by 2 digits (e.g.
pa27,pt07,wp18), or a prefix matching an entry inprivacy_blocklist - Action: strip prefix, derive name from
one_line_description
Category 2 — Client/brand/product names (appear in project_name directly or as the product display name after stripping suffixes):
- Names listed in the config's
privacy_blocklist— apply judgment for any unfamiliar name that looks like a client/company/brand token too - Also applies when the derived display name itself still contains a brand/client name — re-derive from
one_line_description - Action: replace with a purely functional description from
one_line_description
Deriving a safe display name from one_line_description:
- Extract the core system/feature name — translate into each target language as needed; keep original language for non-English files where appropriate
- Append role suffix:
-web→— Frontend,-server→— Backend,-nest-server→— Backend (NestJS),-docker→— Docker / Infra,-ios/-android→— iOS App/— Android App; or derive fromcore_tech - If
one_line_descriptionalso contains the client/brand name, paraphrase around the function not the brand
Final check before output: scan every display_name for every token in privacy_blocklist. If found, re-derive.
Safe (generic tech/function words only) — keep as-is after cleaning:
gitlab-ci-template → "GitLab CI/CD Template Library", tool_website → "Utility Tools Website"
Example transformation pattern (illustrative — apply the same logic to your own blocklisted names):
project_name | ❌ Unsafe draft | ✅ display_name (EN) |
|---|---|---|
pa27-lab-space-and-rack-management-web | — | Lab Space & Rack Management — Frontend |
pa27-lab-space-and-rack-management-nest-server | — | Lab Space & Rack Management — Backend (NestJS) |
pt07-ai-tcr-server | — | AI Test Coverage Analysis — Backend |
gitlab-ci-template | — | GitLab CI/CD Template Library |
Step 3b: Group projects by product
After deriving display names, group projects that belong to the same product/system:
Grouping logic (apply both; a project may match either):
- Projects sharing the same parent directory path → one product group
- Projects whose
project_nameshares a common prefix after stripping the role suffix (-web,-server,-nest-server,-docker,-backend,-frontend,-api,-cli) → one product group
For each group:
- Assign a product display name: the common functional name without the role suffix (e.g. "Lab Space & Rack Management")
- List each member's role (Frontend / Backend / Backend NestJS / Docker / Infra / CLI / etc.)
- Use the highest-priority status among members as the group's representative status
In the Project Index (Step 6): grouped products appear as one row listing all roles:
| Lab Space & Rack Management | Frontend · Backend (Laravel) · Backend (NestJS) · Docker | Backend | Production | TypeScript / Next.js + NestJS + Laravel | <description> |
Ungrouped (solo) projects appear as individual rows as before.
Tech Tree (Step 4/5): tags still map to individual component display_name entries — grouping is only applied to the Project Index, not the Tech Tree.
Step 4: Build the tech → projects mapping
From all collected tags arrays, build an inverted index:
tech_tag → [{ project_name, category, status, one_line_description }]
Sort projects under each tag by status priority: Production > In Progress > Maintenance > Side Project > Archived > Prototype.
Step 5: Group tags into skill domains
Map each tag to one of the following top-level domains. Use this built-in mapping, merged with custom_domains from config (custom entries extend or override the built-in lists):
Frontend:
React, Next.js, Vue.js, Nuxt 3, Vite, TypeScript, JavaScript, CSS Modules,
MUI, Tailwind CSS, Redux, Redux-Saga, React Native, Expo, WebView, Static Site,
Ant Design, HTML, CSS
Backend:
Node.js, NestJS, Express, Laravel, PHP, Python, FastAPI, Flask, Fastify,
REST API, GraphQL, WebSocket, BullMQ, Prisma, TypeORM, Swagger, OpenAPI
AI / LLM:
LangChain, LangGraph, LangChain.js, Azure OpenAI, OpenAI, LLM, RAG, pgvector,
Weaviate, Embedding, Fine-tuning, Claude, Prompt Engineering, MCP, AI Agent,
n8n, LLM Orchestration
Database:
PostgreSQL, MySQL, MongoDB, Redis, SQLite, Oracle, OCI8, pgvector, Prisma,
TypeORM, SQL Server, Google Sheet
DevOps / Infrastructure:
Docker, Docker Compose, Docker Swarm, Nginx, GitLab CI/CD, GitHub Actions,
CI/CD, Kubernetes, NAS, Reverse Proxy, Nginx Proxy Manager, Shell Script
Mobile:
React Native, Expo, iOS, Android, Swift, Java, WebView, Firebase, Push Notification
Tools & Automation:
Chrome Extension, Gmail API, Google Sheet, n8n, Swagger, OpenAPI, MCP,
AI Coding Agent, Bash, Automation
Languages:
TypeScript, JavaScript, PHP, Python, Java, Ruby, Go, Rust, SQL, Bash
A tag can appear in multiple domains if it fits. Tags with no match → place in "Other".
Step 6: Generate one output file per configured language
Write all files simultaneously to the current working directory: tech-profile-<lang>.md for each entry in languages (e.g. tech-profile-en.md, tech-profile-zh-TW.md).
---
generated_at: <ISO8601 timestamp in configured timezone>
source_version: "<latest version string>"
total_projects: <N>
lang: <lang code, e.g. en>
---
# <profile.name> — Personal Tech Profile
> Auto-generated from <N> project docs (skill_version: <version>).
> Each technology links to the projects that use it.
> Intended for use in personal website skill tree / mind map rendering.
---
## 🗂 Domain Overview
| Domain | Technologies | Projects |
|--------|-------------|----------|
| Frontend | React, Next.js, ... | N |
| Backend | NestJS, Laravel, ... | N |
| AI / LLM | LangGraph, Azure OpenAI, ... | N |
| Database | PostgreSQL, Redis, ... | N |
| DevOps / Infrastructure | Docker, GitLab CI/CD, ... | N |
| Mobile | React Native, Expo, ... | N |
| Tools & Automation | Chrome Extension, n8n, ... | N |
| Languages | TypeScript, PHP, Python, ... | N |
---
## 🌳 Tech Tree (Skill → Projects Mapping)
> Format: each technology lists all projects that use it, grouped by domain.
> `[P]` = Production, `[IP]` = In Progress, `[M]` = Maintenance, `[S]` = Side Project, `[A]` = Archived
### Frontend
#### React
- **project-name** [P] — one_line_description (translated into this file's language if needed)
- ...
[... repeat for all domains and tags ...]
---
## 📦 Project Index
> All projects with latest doc, sorted by domain then status.
| Project | Domain | Status | Core Tech | Description |
|---------|--------|--------|-----------|-------------|
| project-name | Frontend Web Development | Production | TypeScript / Next.js 15 | <description in this file's language> |
| ... |
---
## 🧠 Domain Expertise Summary
> One paragraph per domain, written in this file's language.
### Frontend
<paragraph synthesized from Highlights of all frontend projects>
### Backend
<paragraph>
[... repeat for all domains present ...]
---
## 🏷 All Tags (Flat Index)
| Tag | Domain | Projects |
|----|--------|---------|
| Azure OpenAI | AI / LLM | 2 |
| BullMQ | Backend | 1 |
| ... |
Domain name translation table (English → other configured languages)
Maintain a translation table per configured non-English language for domain labels ("Frontend", "Backend", "AI / LLM", "Database", "DevOps / Infrastructure", "Mobile", "Tools & Automation", "Languages", "Other") and status labels ("Production", "In Progress", "Maintenance", "Side Project", "Archived", "Prototype"). For zh-TW, use: 前端開發, 後端開發, AI / 大型語言模型, 資料庫, DevOps / 基礎架構, 行動應用, 工具與自動化, 程式語言, 其他; 正式上線, 開發中, 維護中, 個人專案, 已封存, 原型. For other languages, translate naturally and keep the mapping internally consistent across all output files.
Step 7: Report results
After writing all files, output a summary:
✅ Tech profile generated (<count> files)
- Projects included: N (skill_version: X.Y)
- Unique technologies: M tags
- Domains covered: [Frontend, Backend, AI / LLM, ...]
- tech-profile-en.md → <absolute path>
[- tech-profile-<lang>.md → <absolute path>, one line per additional language]
Notes
- Read project docs in parallel (batch of up to 10) to reduce execution time
- Write all output files in parallel (one Write tool call per language, issued simultaneously)
- If a project's doc frontmatter is malformed or missing required fields, skip it and log a warning (do not abort)
- The
Highlightstext is the most valuable signal for Domain Expertise Summary paragraphs — prioritize it for all languages - For non-English output files, translate
one_line_descriptionandHighlightscontent into natural target-language text; do NOT just leave the source language as-is - For a file matching the source data's original language, descriptions may be used as-is; still translate domain/status labels using the tables above
- Status badge mapping: Production →
[P], In Progress →[IP], Maintenance →[M], Side Project →[S], Archived →[A], Prototype →[Proto] featured: trueprojects should be marked with ⭐ in the Project Index of every file- Always overwrite all output files on each run; they are generated artifacts
- Privacy:
display_namemust describe only system function — never a client, company, or brand name. This applies to ALL projects, not just those matching structural code prefixes. After deriving every display name, scan it againstprivacy_blocklistand re-derive fromone_line_descriptionif any token is found. The Tech Tree, Project Index, and all output sections must be free of client/company/brand identifiers. - Grouping: Projects sharing a parent directory or common name prefix are grouped as one product row in the Project Index. The Tech Tree still lists individual component display names under each tag.