mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-14 15:16:35 +03:00
Add animated mesh gradient hero with overlay content
- Add @paper-design/shaders for WebGL mesh gradient effect - Create hero-shader.js with liquid ink gradient (grayscale palette) - Add overlay content: title, tagline, and CTA on shader - Update hero section structure and styling - Fix accessibility: gallery dot buttons, toggle ARIA attributes - Fix undefined --color-terracotta CSS variable - Update distribution structure for Codex/Cursor skills 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
f75321b2c1
commit
97c83fc51a
@@ -79,11 +79,18 @@ export function transformClaudeCode(commands, skills, distDir, patterns = null)
|
||||
for (const skill of skills) {
|
||||
const skillDir = path.join(skillsDir, skill.name);
|
||||
|
||||
const frontmatter = generateYamlFrontmatter({
|
||||
const frontmatterObj = {
|
||||
name: skill.name,
|
||||
description: skill.description,
|
||||
...(skill.license && { license: skill.license })
|
||||
});
|
||||
};
|
||||
|
||||
// Add optional fields if present
|
||||
if (skill.license) frontmatterObj.license = skill.license;
|
||||
if (skill.compatibility) frontmatterObj.compatibility = skill.compatibility;
|
||||
if (skill.metadata) frontmatterObj.metadata = skill.metadata;
|
||||
if (skill.allowedTools) frontmatterObj['allowed-tools'] = skill.allowedTools;
|
||||
|
||||
const frontmatter = generateYamlFrontmatter(frontmatterObj);
|
||||
|
||||
let body = skill.body;
|
||||
|
||||
|
||||
@@ -1,19 +1,65 @@
|
||||
import path from 'path';
|
||||
import { cleanDir, ensureDir, writeFile } from '../utils.js';
|
||||
import { cleanDir, ensureDir, writeFile, generateYamlFrontmatter } from '../utils.js';
|
||||
|
||||
/**
|
||||
* Codex Transformer (Full Featured - Custom Prompts + Modular Skills)
|
||||
* Generate markdown from structured patterns/antipatterns data
|
||||
*/
|
||||
function generatePatternsMarkdown(patterns) {
|
||||
if (!patterns || (!patterns.patterns?.length && !patterns.antipatterns?.length)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let md = `## Design Patterns Reference
|
||||
|
||||
This reference defines what TO do and what NOT to do when creating frontend interfaces. These patterns fight against model bias—the tendency of LLMs to converge on the same predictable choices.
|
||||
|
||||
### What TO Do (Patterns)
|
||||
|
||||
Focus on intentional, distinctive design choices:
|
||||
`;
|
||||
|
||||
for (const category of patterns.patterns || []) {
|
||||
md += `\n**${category.name}**:\n`;
|
||||
for (const item of category.items || []) {
|
||||
md += `- ${item}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
md += `
|
||||
### What NOT to Do (Anti-Patterns)
|
||||
|
||||
These patterns create generic "AI slop" aesthetics:
|
||||
`;
|
||||
|
||||
for (const category of patterns.antipatterns || []) {
|
||||
md += `\n**${category.name}**:\n`;
|
||||
for (const item of category.items || []) {
|
||||
md += `- ${item}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
md += `
|
||||
These anti-patterns are baked into training data from countless generic templates. Without explicit guidance, AI reproduces them. This skill ensures your AI knows both what to do AND what to avoid.
|
||||
`;
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
/**
|
||||
* Codex Transformer (Full Featured - Agent Skills Standard)
|
||||
*
|
||||
* Commands: Uses argument-hint format with $VARIABLE placeholders
|
||||
* Skills: Creates modular files with guiding AGENTS.md
|
||||
* Reference files are inlined into the main skill file for Codex
|
||||
* Commands: Uses argument-hint format with $VARIABLE placeholders in .codex/prompts/
|
||||
* Skills: Uses Agent Skills standard with SKILL.md in .codex/skills/{name}/
|
||||
* Reference files are copied to skill subdirectories
|
||||
*/
|
||||
export function transformCodex(commands, skills, distDir, patterns = null) {
|
||||
const codexDir = path.join(distDir, 'codex');
|
||||
const promptsDir = path.join(codexDir, '.codex/prompts');
|
||||
const skillsDir = path.join(codexDir, '.codex/skills');
|
||||
|
||||
cleanDir(codexDir);
|
||||
ensureDir(promptsDir);
|
||||
ensureDir(skillsDir);
|
||||
|
||||
// Commands: Transform to Codex prompt format
|
||||
for (const command of commands) {
|
||||
@@ -42,67 +88,48 @@ export function transformCodex(commands, skills, distDir, patterns = null) {
|
||||
writeFile(outputPath, content);
|
||||
}
|
||||
|
||||
// Skills: Create modular files (with references inlined)
|
||||
const skillEntries = [];
|
||||
// Skills: Use Agent Skills standard with SKILL.md in subdirectories
|
||||
let refCount = 0;
|
||||
for (const skill of skills) {
|
||||
let content = skill.body;
|
||||
const skillDir = path.join(skillsDir, skill.name);
|
||||
|
||||
// Merge patterns body into frontend-design skill (before Domain Reference Files section)
|
||||
if (skill.name === 'frontend-design' && patterns && patterns.body) {
|
||||
const insertPoint = content.indexOf('---\n\n## Domain Reference Files');
|
||||
if (insertPoint > -1) {
|
||||
content = content.slice(0, insertPoint) + '\n\n' + patterns.body + '\n\n' + content.slice(insertPoint);
|
||||
} else {
|
||||
content += '\n\n' + patterns.body;
|
||||
const frontmatter = generateYamlFrontmatter({
|
||||
name: skill.name,
|
||||
description: skill.description,
|
||||
...(skill.license && { license: skill.license })
|
||||
});
|
||||
|
||||
let body = skill.body;
|
||||
|
||||
// Generate and merge patterns into frontend-design skill
|
||||
if (skill.name === 'frontend-design' && patterns) {
|
||||
const patternsMarkdown = generatePatternsMarkdown(patterns);
|
||||
if (patternsMarkdown) {
|
||||
const insertPoint = body.indexOf('---\n\n## Domain Reference Files');
|
||||
if (insertPoint > -1) {
|
||||
body = body.slice(0, insertPoint) + '\n\n' + patternsMarkdown + '\n\n' + body.slice(insertPoint);
|
||||
} else {
|
||||
body += '\n\n' + patternsMarkdown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inline reference files if they exist
|
||||
if (skill.references && skill.references.length > 0) {
|
||||
const refSections = skill.references.map(ref => {
|
||||
refCount++;
|
||||
return `\n\n---\n\n## Reference: ${ref.name}\n\n${ref.content}`;
|
||||
});
|
||||
content += refSections.join('');
|
||||
}
|
||||
|
||||
const outputPath = path.join(codexDir, `AGENTS.${skill.name}.md`);
|
||||
const content = `${frontmatter}\n\n${body}`;
|
||||
const outputPath = path.join(skillDir, 'SKILL.md');
|
||||
writeFile(outputPath, content);
|
||||
skillEntries.push({
|
||||
name: skill.name,
|
||||
description: skill.description,
|
||||
file: `AGENTS.${skill.name}.md`
|
||||
});
|
||||
|
||||
// Copy reference files if they exist
|
||||
if (skill.references && skill.references.length > 0) {
|
||||
const refDir = path.join(skillDir, 'reference');
|
||||
ensureDir(refDir);
|
||||
for (const ref of skill.references) {
|
||||
const refOutputPath = path.join(refDir, `${ref.name}.md`);
|
||||
writeFile(refOutputPath, ref.content);
|
||||
refCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create main AGENTS.md that guides Codex to the right skill files
|
||||
const agentsMd = [
|
||||
'# Codex Agent Instructions',
|
||||
'',
|
||||
'This repository contains specialized skills for different tasks. When the user requests work in a particular domain, read the corresponding skill file for detailed guidance.',
|
||||
'',
|
||||
'## Available Skills',
|
||||
'',
|
||||
'Each skill provides deep expertise in its domain. Use the descriptions below to decide which skill file to read:',
|
||||
'',
|
||||
...skillEntries.map(skill =>
|
||||
`### ${skill.name}\n\n**When to use**: ${skill.description}\n\n**Read**: \`${skill.file}\` for complete instructions.\n`
|
||||
),
|
||||
'',
|
||||
'## How to Use Skills',
|
||||
'',
|
||||
'1. Identify the user\'s request domain',
|
||||
'2. Match it to a skill description above',
|
||||
'3. Read the corresponding skill file',
|
||||
'4. Follow the guidance in that file',
|
||||
'',
|
||||
'Multiple skills can be combined when the task requires expertise from different domains.'
|
||||
].join('\n');
|
||||
|
||||
writeFile(path.join(codexDir, 'AGENTS.md'), agentsMd);
|
||||
|
||||
const refInfo = refCount > 0 ? ` (${refCount} refs inlined)` : '';
|
||||
console.log(`✓ Codex: ${commands.length} prompts, ${skills.length} skills (modular)${refInfo}`);
|
||||
const refInfo = refCount > 0 ? ` (${refCount} reference files)` : '';
|
||||
console.log(`✓ Codex: ${commands.length} prompts, ${skills.length} skills${refInfo}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,57 +1,116 @@
|
||||
import path from 'path';
|
||||
import { cleanDir, ensureDir, writeFile } from '../utils.js';
|
||||
import { cleanDir, ensureDir, writeFile, generateYamlFrontmatter } from '../utils.js';
|
||||
|
||||
/**
|
||||
* Cursor Transformer (Downgraded - No Frontmatter/Args)
|
||||
* Generate markdown from structured patterns/antipatterns data
|
||||
*/
|
||||
function generatePatternsMarkdown(patterns) {
|
||||
if (!patterns || (!patterns.patterns?.length && !patterns.antipatterns?.length)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let md = `## Design Patterns Reference
|
||||
|
||||
This reference defines what TO do and what NOT to do when creating frontend interfaces. These patterns fight against model bias—the tendency of LLMs to converge on the same predictable choices.
|
||||
|
||||
### What TO Do (Patterns)
|
||||
|
||||
Focus on intentional, distinctive design choices:
|
||||
`;
|
||||
|
||||
for (const category of patterns.patterns || []) {
|
||||
md += `\n**${category.name}**:\n`;
|
||||
for (const item of category.items || []) {
|
||||
md += `- ${item}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
md += `
|
||||
### What NOT to Do (Anti-Patterns)
|
||||
|
||||
These patterns create generic "AI slop" aesthetics:
|
||||
`;
|
||||
|
||||
for (const category of patterns.antipatterns || []) {
|
||||
md += `\n**${category.name}**:\n`;
|
||||
for (const item of category.items || []) {
|
||||
md += `- ${item}\n`;
|
||||
}
|
||||
}
|
||||
|
||||
md += `
|
||||
These anti-patterns are baked into training data from countless generic templates. Without explicit guidance, AI reproduces them. This skill ensures your AI knows both what to do AND what to avoid.
|
||||
`;
|
||||
|
||||
return md;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor Transformer (Agent Skills Standard)
|
||||
*
|
||||
* Strips all frontmatter and metadata, outputs body only.
|
||||
* Cursor doesn't support arguments or frontmatter.
|
||||
* Reference files are inlined into the main skill file.
|
||||
* Commands: Body only in .cursor/commands/ (Cursor doesn't support command frontmatter)
|
||||
* Skills: Agent Skills standard with SKILL.md in .cursor/skills/{name}/
|
||||
* Reference files are copied to skill subdirectories
|
||||
*
|
||||
* Note: Agent Skills in Cursor require nightly channel and are agent-decided rules.
|
||||
*/
|
||||
export function transformCursor(commands, skills, distDir, patterns = null) {
|
||||
const cursorDir = path.join(distDir, 'cursor');
|
||||
const commandsDir = path.join(cursorDir, '.cursor/commands');
|
||||
const rulesDir = path.join(cursorDir, '.cursor/rules');
|
||||
const skillsDir = path.join(cursorDir, '.cursor/skills');
|
||||
|
||||
cleanDir(cursorDir);
|
||||
ensureDir(commandsDir);
|
||||
ensureDir(rulesDir);
|
||||
ensureDir(skillsDir);
|
||||
|
||||
// Commands: Body only (no frontmatter)
|
||||
// Commands: Body only (Cursor doesn't support command frontmatter/args)
|
||||
for (const command of commands) {
|
||||
const outputPath = path.join(commandsDir, `${command.name}.md`);
|
||||
writeFile(outputPath, command.body);
|
||||
}
|
||||
|
||||
// Skills: Body only (with references inlined)
|
||||
// Skills: Agent Skills standard with SKILL.md in subdirectories
|
||||
let refCount = 0;
|
||||
for (const skill of skills) {
|
||||
let content = skill.body;
|
||||
const skillDir = path.join(skillsDir, skill.name);
|
||||
|
||||
// Merge patterns body into frontend-design skill (before Domain Reference Files section)
|
||||
if (skill.name === 'frontend-design' && patterns && patterns.body) {
|
||||
const insertPoint = content.indexOf('---\n\n## Domain Reference Files');
|
||||
if (insertPoint > -1) {
|
||||
content = content.slice(0, insertPoint) + '\n\n' + patterns.body + '\n\n' + content.slice(insertPoint);
|
||||
} else {
|
||||
content += '\n\n' + patterns.body;
|
||||
const frontmatter = generateYamlFrontmatter({
|
||||
name: skill.name,
|
||||
description: skill.description,
|
||||
...(skill.license && { license: skill.license })
|
||||
});
|
||||
|
||||
let body = skill.body;
|
||||
|
||||
// Generate and merge patterns into frontend-design skill
|
||||
if (skill.name === 'frontend-design' && patterns) {
|
||||
const patternsMarkdown = generatePatternsMarkdown(patterns);
|
||||
if (patternsMarkdown) {
|
||||
const insertPoint = body.indexOf('---\n\n## Domain Reference Files');
|
||||
if (insertPoint > -1) {
|
||||
body = body.slice(0, insertPoint) + '\n\n' + patternsMarkdown + '\n\n' + body.slice(insertPoint);
|
||||
} else {
|
||||
body += '\n\n' + patternsMarkdown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Inline reference files if they exist
|
||||
if (skill.references && skill.references.length > 0) {
|
||||
const refSections = skill.references.map(ref => {
|
||||
refCount++;
|
||||
return `\n\n---\n\n## Reference: ${ref.name}\n\n${ref.content}`;
|
||||
});
|
||||
content += refSections.join('');
|
||||
}
|
||||
|
||||
const outputPath = path.join(rulesDir, `${skill.name}.md`);
|
||||
const content = `${frontmatter}\n\n${body}`;
|
||||
const outputPath = path.join(skillDir, 'SKILL.md');
|
||||
writeFile(outputPath, content);
|
||||
|
||||
// Copy reference files if they exist
|
||||
if (skill.references && skill.references.length > 0) {
|
||||
const refDir = path.join(skillDir, 'reference');
|
||||
ensureDir(refDir);
|
||||
for (const ref of skill.references) {
|
||||
const refOutputPath = path.join(refDir, `${ref.name}.md`);
|
||||
writeFile(refOutputPath, ref.content);
|
||||
refCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const refInfo = refCount > 0 ? ` (${refCount} refs inlined)` : '';
|
||||
console.log(`✓ Cursor: ${commands.length} commands, ${skills.length} skills (downgraded)${refInfo}`);
|
||||
const refInfo = refCount > 0 ? ` (${refCount} reference files)` : '';
|
||||
console.log(`✓ Cursor: ${commands.length} commands, ${skills.length} skills${refInfo}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -163,6 +163,9 @@ export function readSourceFiles(rootDir) {
|
||||
name: frontmatter.name || entry.name,
|
||||
description: frontmatter.description || '',
|
||||
license: frontmatter.license || '',
|
||||
compatibility: frontmatter.compatibility || '',
|
||||
metadata: frontmatter.metadata || null,
|
||||
allowedTools: frontmatter['allowed-tools'] || '',
|
||||
body,
|
||||
filePath: skillMdPath,
|
||||
references
|
||||
@@ -178,6 +181,9 @@ export function readSourceFiles(rootDir) {
|
||||
name: frontmatter.name || name,
|
||||
description: frontmatter.description || '',
|
||||
license: frontmatter.license || '',
|
||||
compatibility: frontmatter.compatibility || '',
|
||||
metadata: frontmatter.metadata || null,
|
||||
allowedTools: frontmatter['allowed-tools'] || '',
|
||||
body,
|
||||
filePath: entryPath,
|
||||
references: []
|
||||
|
||||
Reference in New Issue
Block a user