Core Web Vitals
vmDeshpande/ai-agent-automation
Optimize Core Web Vitals (LCP, INP, CLS) for better page experience and search ranking.
Performance profiling and optimization for web apps — Core Web Vitals (LCP, INP, CLS), Lighthouse audits, bundle analysis, backend profiling (CPU, memory, DB queries), N+1 detection, caching…
$ npx skills add EliasOulkadi/shokunin --skill performance-profiler -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install EliasOulkadi/shokunin performance-profiler --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/EliasOulkadi/shokunin.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.pack/skills/performance-profiler .claude/skills/performance-profiler && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "performance-profiler" agent skill from https://github.com/EliasOulkadi/shokunin/tree/master/.pack/skills/performance-profiler into .claude/skills/performance-profiler/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "performance-profiler", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/EliasOulkadi/shokunin/tree/master/.pack/skills/performance-profilerType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add EliasOulkadi/shokunin --skill performance-profiler -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install EliasOulkadi/shokunin performance-profiler --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/EliasOulkadi/shokunin.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.pack/skills/performance-profiler .agents/skills/performance-profiler && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "performance-profiler" agent skill from https://github.com/EliasOulkadi/shokunin/tree/master/.pack/skills/performance-profiler into .agents/skills/performance-profiler/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "performance-profiler", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add EliasOulkadi/shokunin --skill performance-profiler -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install EliasOulkadi/shokunin performance-profiler --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/EliasOulkadi/shokunin.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.pack/skills/performance-profiler .cursor/skills/performance-profiler && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "performance-profiler" agent skill from https://github.com/EliasOulkadi/shokunin/tree/master/.pack/skills/performance-profiler into .cursor/skills/performance-profiler/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "performance-profiler", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/EliasOulkadi/shokunin.git --path .pack/skills/performance-profiler--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add EliasOulkadi/shokunin --skill performance-profiler -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install EliasOulkadi/shokunin performance-profiler --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/EliasOulkadi/shokunin.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.pack/skills/performance-profiler .gemini/skills/performance-profiler && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "performance-profiler" agent skill from https://github.com/EliasOulkadi/shokunin/tree/master/.pack/skills/performance-profiler into .gemini/skills/performance-profiler/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "performance-profiler", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install EliasOulkadi/shokunin performance-profilerInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add EliasOulkadi/shokunin --skill performance-profiler -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/EliasOulkadi/shokunin.git skills-src && mkdir -p .github/skills && cp -r skills-src/.pack/skills/performance-profiler .github/skills/performance-profiler && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "performance-profiler" agent skill from https://github.com/EliasOulkadi/shokunin/tree/master/.pack/skills/performance-profiler into .github/skills/performance-profiler/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "performance-profiler", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add EliasOulkadi/shokunin --skill performance-profiler -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install EliasOulkadi/shokunin performance-profiler --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/EliasOulkadi/shokunin.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.pack/skills/performance-profiler .opencode/skills/performance-profiler && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "performance-profiler" agent skill from https://github.com/EliasOulkadi/shokunin/tree/master/.pack/skills/performance-profiler into .opencode/skills/performance-profiler/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "performance-profiler", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
performance-profilerPerformance profiling and optimization for web apps — Core Web Vitals (LCP, INP, CLS), Lighthouse audits, bundle analysis, backend profiling (CPU, memory, DB queries), N+1 detection, caching…
Performance Profiler is an agent skill from EliasOulkadi/shokunin. Performance profiling and optimization for web apps — Core Web Vitals (LCP, INP, CLS), Lighthouse audits, bundle analysis, backend profiling (CPU, memory, DB queries), N+1 detection, caching strategies (Redis, CDN, HTTP), and performance budgets. Use when user asks to improve performance, run Lighthouse audit, profile a Node.js app, optimize Core Web Vitals, reduce bundle size, or investigate slow response times. Do NOT use for database schema optimization (use db-sculptor), Docker image optimization (use…
Its SKILL.md is about 2.7k tokens, which your agent loads only when the skill is triggered. The skill folder holds 6 other files, including scripts and reference files (for example `references/backend-performance.md` and `references/web-vitals.md`). Compatibility notes: opencode
It sits in Frontend & Design, covering Web performance. It works with Docker, Node.js, Redis and Contentful. The repository describes itself as: 職人 Shokunin 62 AI agent skills for OpenCode, Claude Code, Cursor, Windsurf. ChromaDB memory, MCP servers, declarative self-updates. Multi-model, open source, zero cost. The licence is MIT.
6 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 4c68e5b. It shows what the files ask for, not the result of running them.
Pre-approves these tools, so the agent can use them without asking each time:
ReadBashWriteWebFetchFrom allowed-tools in the SKILL.md frontmatter.
Ships 2 files in scripts/ (PowerShell), which the agent can run.
Shell commands in SKILL.md call:
npxnodepythonFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npx, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
opencode
From compatibility in the SKILL.md frontmatter.
Performance Profiler loads about 2.7k tokens when it runs, and up to ~6k if it reads all its reference files. Until then it costs about 141 tokens; SKILL.md has 840 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
allowed-tools: Read, Bash, Write, WebFetchAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from EliasOulkadi/shokunin at commit 4c68e5b, republished under its MIT licence (© EliasOulkadi). 840 words, ~2,723 tokens.
.claude/skills/performance-profiler/SKILL.md (or your agent's skills folder). This skill also uses 4 other files; get the full folder from GitHub.Find and fix performance issues from frontend to backend. Based on Google Core Web Vitals, Lighthouse, Chrome DevTools, and production patterns from WebPageTest and clinic.js.
| Command | Description |
|---|---|
audit | Run comprehensive performance audit (frontend + backend) |
vitals | Audit Core Web Vitals specifically (LCP, INP, CLS, TBT) |
lcp | Optimize Largest Contentful Paint |
inp | Fix Interaction to Next Paint (long tasks) |
bundle | Analyze bundle size and split strategy |
backend | Profile Node.js/Python backend performance |
budget | Set and verify performance budgets |
npx lighthouse https://example.com --preset=desktop --output=html --output-path=./lighthouse-report.html
npx lighthouse https://example.com --preset=desktop --output=json --output-path=./lighthouse.jsonTarget scores:
| Metric | Target | Severity if missed |
|---|---|---|
| Performance | > 90 | Critical |
| LCP (Largest Contentful Paint) | < 2.5s | Critical |
| INP (Interaction to Next Paint) | < 200ms | Critical |
| CLS (Cumulative Layout Shift) | < 0.1 | Critical |
| TBT (Total Blocking Time) | < 200ms | High |
| FCP (First Contentful Paint) | < 1.8s | Medium |
| Speed Index | < 3.4s | Medium |
<!-- 1. Preload LCP image -->
<link rel="preload" as="image" href="hero.webp" fetchpriority="high">
<!-- 2. LCP image: no lazy loading -->
<img src="hero.webp" width="1200" height="600" fetchpriority="high" alt="">
<!-- 3. Inline critical CSS in <head> -->
<style>
.hero { display: grid; min-height: 100dvh; }
.hero img { width: 100%; height: auto; aspect-ratio: 2/1; }
</style>
<!-- 4. Defer non-critical CSS -->
<link rel="preload" href="styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<!-- 5. Self-host fonts with font-display: swap -->
@font-face {
font-family: 'Geist';
src: url('/fonts/geist.woff2') format('woff2');
font-display: swap;
}LCP sub-parts breakdown:
// Break up long tasks with scheduler.yield()
async function processLargeDataset(items: Item[]) {
const CHUNK_SIZE = 50
for (let i = 0; i < items.length; i += CHUNK_SIZE) {
const chunk = items.slice(i, i + CHUNK_SIZE)
processChunk(chunk)
if (i + CHUNK_SIZE < items.length) {
// Yield to main thread every 50ms
await new Promise(resolve => setTimeout(resolve, 0))
}
}
}
// Or use scheduler.yield() (Chrome 115+)
for (let i = 0; i < items.length; i += CHUNK_SIZE) {
processChunk(items.slice(i, i + CHUNK_SIZE))
await scheduler.yield()
}Common INP causes:
/* Reserve space for images */
img, video, iframe {
width: 100%;
height: auto;
aspect-ratio: attr(width) / attr(height);
}
/* Reserve space for dynamic content */
.ad-container {
min-height: 250px;
}
/* Prevent layout shift from web fonts */
body {
font-display: swap;
}
/* Fixed size for injected elements */
.cookie-banner {
min-height: 80px;
}# Node.js CPU profile
node --cpu-prof --cpu-prof-interval=1 server.js
# Analyze: clinic doctor -- node server.js
# Node.js heap snapshot
node --heapsnapshot server.js
# Load in Chrome DevTools > Memory tab
# Python profiling
python -m cProfile -o output.prof server.py
# Analyze: snakeviz output.prof| Symptom | Likely cause | Fix |
|---|---|---|
| High CPU | N+1 queries, synchronous crypto | Add eager loading. Use async operations. |
| High memory | No streaming. Array growth. | Stream responses. Paginate results. |
| High latency p99 | DB lock contention | Add indexes. Use read replicas. |
| GC pauses | High allocation rate | Pool objects. Reduce allocations. Use Buffer pools. |
| Connection timeouts | Pool exhaustion | Increase pool size. Add connection queue. |
# Next.js
ANALYZE=true next build
# Vite/Rollup
npx vite-bundle-visualizer
# Generic
npx source-map-explorer dist/**/*.js| Target | Budget |
|---|---|
| Total JS | < 300KB (gzipped) |
| Total CSS | < 50KB (gzipped) |
| Total fonts | < 100KB |
| First load JS | < 100KB (gzipped) |
| Total image payload | < 500KB |
| Largest chunk | < 150KB (gzipped) |
| What | Cache where | TTL |
|---|---|---|
| Static assets (JS, CSS, images) | CDN + browser | 1 year (versioned filenames) |
| API responses (public, stable) | CDN + HTTP Cache-Control | 5 min to 1h (stale-while-revalidate) |
| Dynamic data (user-specific) | Redis | 30s to 5min |
| Database query results | Application memory (LRU) | 10s |
| Full pages (public) | CDN + Edge caching | 5 min |
| Auth tokens | Never cache | — |
{
"ci": {
"assert": {
"assertions": {
"categories:performance": ["error", { "minScore": 0.9 }],
"largest-contentful-paint": ["error", { "maxNumericValue": 2500 }],
"interactive": ["error", { "maxNumericValue": 3800 }],
"total-blocking-time": ["error", { "maxNumericValue": 200 }],
"cumulative-layout-shift": ["error", { "maxNumericValue": 0.1 }],
"resource-summary:script:size": ["warn", { "maxNumericValue": 300000 }]
}
}
}
}npx lighthouse https://staging.example.com --output=json | \
npx lighthouse-ci --collect --assert| Anti-pattern | Fix |
|---|---|
| Optimizing without measuring | Always measure first. Field data > lab data. |
| Only testing on dev machine | Test on real devices with throttling (3G, 4x CPU slowdown) |
| Cache everything | Cache only what changes infrequently. Stale cache is worse than no cache. |
| Lazy loading above-fold images | Only lazy load below-fold. LCP image must load immediately. |
| Bundle splitting too aggressively | Split at route boundaries. Not by component. |
| Optimizing non-bottleneck | Use Lighthouse + RUM to find actual bottleneck. |
| Ignoring mobile | Mobile is 2-4x slower than desktop. Optimize for mobile first. |
| No performance budget | CI must fail when budget exceeded. |
| Cause | Fix |
|---|---|
| Lighthouse audit crashes on SPA with hash routing | Use --chrome-flags="--disable-web-security" or serve localhost via static server, never file:// |
| Lighthouse scores vary 5+ points between runs | Normal. Run 3-5 times, use median. Always audit Incognito with no extensions. Variance from network jitter and CPU scheduling |
| Bundle analyzer can't parse source maps — blank treemap | Verify devtool: 'hidden-source-map' in webpack/Vite. Regenerate build with source maps enabled. Check sourceMapFilename matches |
| RUM field data shows much worse LCP than lab (Lighthouse) | Lab is synthetic (fast CPU/network). Field data from real users on slow devices. Trust field data. Optimize for p75, not median |
| Performance budget assertion fails CI on every PR | Investigate which chunk exceeded budget immediately. Treat as build failure. Block merge until resolved or budget explicitly raised with justification |
| Chrome DevTools Performance tab freezes on large trace (>30s) | Record shorter traces (5-10s max). Use --user-data-dir with clean profile. Export HAR for sharing instead of full trace |
clinic doctor fails with "Cannot find module" | Works only with Node.js < 22. For Node 22+, use node --cpu-prof and analyze with Chrome DevTools. clinic is community-maintained, lagging Node releases |
| WebPageTest results vary significantly by test location | Test from 2+ geographic regions. Use medianRun and repeatView in WPT API. Document which locations were tested in audit report |
© EliasOulkadi, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 4 other files (scripts, references) in .pack/skills/performance-profiler of EliasOulkadi/shokunin.
Open the folder on GitHubat commit 4c68e5b
Performance Profiler next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Performance Profiler this skillEliasOulkadi/shokunin | 114 | — | ~2.7k | Automated safety check: Notes | MIT | |
| Core Web VitalsvmDeshpande/ai-agent-automation | 178 | 4 repos | ~3.6k | Automated safety check: Pass | MIT | |
| Bun Buildinvolvex/youtube-music-cli | 456 | — | ~2.1k | Automated safety check: Notes | MIT | |
| Frontend UIoomol-lab/open-flow | 234 | — | ~819 | Automated safety check: Pass | Apache-2.0 | |
| Next.js DeveloperJeffallan/claude-skills | 12k | — | ~1.4k | Automated safety check: Pass | MIT | |
| Core Web Vitalstheopenco/llmgateway | 1.7k | — | ~955 | Automated safety check: Pass | Custom licence |
vmDeshpande/ai-agent-automation
Optimize Core Web Vitals (LCP, INP, CLS) for better page experience and search ranking.
involvex/youtube-music-cli
Create optimized production bundles with Bun's native bundler.
oomol-lab/open-flow
Implement and review Open Flow frontend components, styling, layout, and interactions.
Jeffallan/claude-skills
Builds Next.js 14+ apps on the App Router with server components, server actions, explicit caching, SEO metadata, loading and error boundaries and Vercel deployment.
theopenco/llmgateway
Diagnose and improve Largest Contentful Paint, Interaction to Next Paint, and Cumulative Layout Shift in this repository's Next.js App Router frontends.
agulli/atlas-agents
Audit project dependencies for vulnerabilities, license issues, and bloat.
EliasOulkadi/shokunin
Design CI/CD pipelines for GitHub Actions, GitLab CI, and CircleCI with matrix builds, test sharding, caching, Docker layer caching, OIDC auth, deployment strategies (rolling, blue-green, canary)…
EliasOulkadi/shokunin
Build production-grade components for React, Vue 3, and Svelte 5 with all states (loading, empty, error, success, idle), TypeScript strict, WCAG 2.2 accessibility, server components (RSC), and…
EliasOulkadi/shokunin
PostgreSQL database administration — backup/restore (pgdump, PITR, WAL archiving), health monitoring (connections, bloat, cache hit ratio, dead tuples), connection pooling (PgBouncer), replication…
EliasOulkadi/shokunin
Design database schemas with Prisma/Drizzle, PostgreSQL index strategy (B-tree, GIN, GiST, BRIN, Hash), query optimization (EXPLAIN ANALYZE), migration safety (expand/contract, zero-downtime), and…
EliasOulkadi/shokunin
Optimize Docker images with multi-stage builds, distroless bases, BuildKit cache mounts, multi-arch builds, compose watch, security hardening (non-root, seccomp, capabilities drop), and…
EliasOulkadi/shokunin
Design error handling, structured logging, and observability with OpenTelemetry (traces, metrics, logs), error classification, recovery patterns (retry with jitter, circuit breaker, bulkhead…
Works with
Categories
Performance profiling and optimization for web apps — Core Web Vitals (LCP, INP, CLS), Lighthouse audits, bundle analysis, backend profiling (CPU, memory, DB queries), N+1 detection, caching…. Performance Profiler is an agent skill from EliasOulkadi/shokunin. Performance profiling and optimization for web apps — Core Web Vitals (LCP, INP, CLS), Lighthouse audits, bundle analysis, backend profiling (CPU, memory, DB queries), N+1 detection, caching strategies (Redis, CDN, HTTP), and performance budgets.
Performance Profiler fits situations like: user asks to improve performance; run Lighthouse audit; profile a Node.js app; optimize Core Web Vitals.
Run `npx skills add EliasOulkadi/shokunin --skill performance-profiler -a claude-code`. Or copy the skill folder (.pack/skills/performance-profiler in EliasOulkadi/shokunin) into .claude/skills/performance-profiler in your project. Claude Code loads it when a task matches its description.
Run `npx skills add EliasOulkadi/shokunin --skill performance-profiler -a codex`. Or copy the skill folder (.pack/skills/performance-profiler in EliasOulkadi/shokunin) into .agents/skills/performance-profiler in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add EliasOulkadi/shokunin --skill performance-profiler -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/performance-profiler, .gemini/skills/performance-profiler, .github/skills/performance-profiler and .opencode/skills/performance-profiler in your project.
Going by SKILL.md and its folder, Performance Profiler needs PowerShell for the scripts in its folder and the command-line tools its instructions call (npx, node and python). Our summary lists: Python 3; Node.js; PowerShell; Docker. Its frontmatter pre-approves these tools: Read, Bash, Write, WebFetch. Compatibility (from SKILL.md): opencode.
SKILL.md contains no URLs. Its commands use npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (pre-approves every shell command (allowed-tools: bash)), nothing it rates as a warning. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Performance Profiler is published under the MIT licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.7k tokens (SKILL.md is roughly 11k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 3.3k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Performance Profiler: Core Web Vitals (vmDeshpande/ai-agent-automation, 178 stars), Bun Build (involvex/youtube-music-cli, 456 stars), Frontend UI (oomol-lab/open-flow, 234 stars) and Next.js Developer (Jeffallan/claude-skills, 12k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
EliasOulkadi (a GitHub user) maintains it in EliasOulkadi/shokunin, which has 114 GitHub stars. The repository holds 49 skills in this directory. The repository was last updated on October 5, 2026.
Source: EliasOulkadi/shokunin on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.