Merge branch 'main' of https://github.com/sickn33/antigravity-awesome-skills
This commit is contained in:
1
web-app/.gitignore
vendored
1
web-app/.gitignore
vendored
@@ -23,3 +23,4 @@ dist-ssr
|
||||
*.sln
|
||||
*.sw?
|
||||
.env
|
||||
.last-sync-sha
|
||||
|
||||
48
web-app/package-lock.json
generated
48
web-app/package-lock.json
generated
@@ -8,7 +8,7 @@
|
||||
"name": "web-app",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@supabase/supabase-js": "^2.97.0",
|
||||
"@supabase/supabase-js": "^2.98.0",
|
||||
"clsx": "^2.1.1",
|
||||
"framer-motion": "^12.34.2",
|
||||
"github-markdown-css": "^5.9.0",
|
||||
@@ -1391,9 +1391,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@supabase/auth-js": {
|
||||
"version": "2.97.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.97.0.tgz",
|
||||
"integrity": "sha512-2Og/1lqp+AIavr8qS2X04aSl8RBY06y4LrtIAGxat06XoXYiDxKNQMQzWDAKm1EyZFZVRNH48DO5YvIZ7la5fQ==",
|
||||
"version": "2.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.98.0.tgz",
|
||||
"integrity": "sha512-GBH361T0peHU91AQNzOlIrjUZw9TZbB9YDRiyFgk/3Kvr3/Z1NWUZ2athWTfHhwNNi8IrW00foyFxQD9IO/Trg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "2.8.1"
|
||||
@@ -1403,9 +1403,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/functions-js": {
|
||||
"version": "2.97.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.97.0.tgz",
|
||||
"integrity": "sha512-fSaA0ZeBUS9hMgpGZt5shIZvfs3Mvx2ZdajQT4kv/whubqDBAp3GU5W8iIXy21MRvKmO2NpAj8/Q6y+ZkZyF/w==",
|
||||
"version": "2.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.98.0.tgz",
|
||||
"integrity": "sha512-N/xEyiNU5Org+d+PNCpv+TWniAXRzxIURxDYsS/m2I/sfAB/HcM9aM2Dmf5edj5oWb9GxID1OBaZ8NMmPXL+Lg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "2.8.1"
|
||||
@@ -1415,9 +1415,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/postgrest-js": {
|
||||
"version": "2.97.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.97.0.tgz",
|
||||
"integrity": "sha512-g4Ps0eaxZZurvfv/KGoo2XPZNpyNtjth9aW8eho9LZWM0bUuBtxPZw3ZQ6ERSpEGogshR+XNgwlSPIwcuHCNww==",
|
||||
"version": "2.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.98.0.tgz",
|
||||
"integrity": "sha512-v6e9WeZuJijzUut8HyXu6gMqWFepIbaeaMIm1uKzei4yLg9bC9OtEW9O14LE/9ezqNbSAnSLO5GtOLFdm7Bpkg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "2.8.1"
|
||||
@@ -1427,9 +1427,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/realtime-js": {
|
||||
"version": "2.97.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.97.0.tgz",
|
||||
"integrity": "sha512-37Jw0NLaFP0CZd7qCan97D1zWutPrTSpgWxAw6Yok59JZoxp4IIKMrPeftJ3LZHmf+ILQOPy3i0pRDHM9FY36Q==",
|
||||
"version": "2.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.98.0.tgz",
|
||||
"integrity": "sha512-rOWt28uGyFipWOSd+n0WVMr9kUXiWaa7J4hvyLCIHjRFqWm1z9CaaKAoYyfYMC1Exn3WT8WePCgiVhlAtWC2yw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/phoenix": "^1.6.6",
|
||||
@@ -1442,9 +1442,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/storage-js": {
|
||||
"version": "2.97.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.97.0.tgz",
|
||||
"integrity": "sha512-9f6NniSBfuMxOWKwEFb+RjJzkfMdJUwv9oHuFJKfe/5VJR8cd90qw68m6Hn0ImGtwG37TUO+QHtoOechxRJ1Yg==",
|
||||
"version": "2.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.98.0.tgz",
|
||||
"integrity": "sha512-tzr2mG+v7ILSAZSfZMSL9OPyIH4z1ikgQ8EcQTKfMRz4EwmlFt3UnJaGzSOxyvF5b+fc9So7qdSUWTqGgeLokQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"iceberg-js": "^0.8.1",
|
||||
@@ -1455,16 +1455,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/supabase-js": {
|
||||
"version": "2.97.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.97.0.tgz",
|
||||
"integrity": "sha512-kTD91rZNO4LvRUHv4x3/4hNmsEd2ofkYhuba2VMUPRVef1RCmnHtm7rIws38Fg0yQnOSZOplQzafn0GSiy6GVg==",
|
||||
"version": "2.98.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.98.0.tgz",
|
||||
"integrity": "sha512-Ohc97CtInLwZyiSASz7tT9/Abm/vqnIbO9REp+PivVUII8UZsuI3bngRQnYgJdFoOIwvaEII1fX1qy8x0CyNiw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@supabase/auth-js": "2.97.0",
|
||||
"@supabase/functions-js": "2.97.0",
|
||||
"@supabase/postgrest-js": "2.97.0",
|
||||
"@supabase/realtime-js": "2.97.0",
|
||||
"@supabase/storage-js": "2.97.0"
|
||||
"@supabase/auth-js": "2.98.0",
|
||||
"@supabase/functions-js": "2.98.0",
|
||||
"@supabase/postgrest-js": "2.98.0",
|
||||
"@supabase/realtime-js": "2.98.0",
|
||||
"@supabase/storage-js": "2.98.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@supabase/supabase-js": "^2.97.0",
|
||||
"@supabase/supabase-js": "^2.98.0",
|
||||
"clsx": "^2.1.1",
|
||||
"framer-motion": "^12.34.2",
|
||||
"github-markdown-css": "^5.9.0",
|
||||
|
||||
@@ -8905,9 +8905,9 @@
|
||||
"category": "uncategorized",
|
||||
"name": "tutorial-engineer",
|
||||
"description": "Creates step-by-step tutorials and educational content from code. Transforms complex concepts into progressive learning experiences with hands-on examples.",
|
||||
"risk": "unknown",
|
||||
"risk": "safe",
|
||||
"source": "community",
|
||||
"date_added": "2026-02-27"
|
||||
"date_added": "2026-03-02"
|
||||
},
|
||||
{
|
||||
"id": "twilio-communications",
|
||||
|
||||
@@ -1,137 +1,397 @@
|
||||
---
|
||||
name: tutorial-engineer
|
||||
description: Creates step-by-step tutorials and educational content from code. Transforms complex concepts into progressive learning experiences with hands-on examples.
|
||||
risk: unknown
|
||||
risk: safe
|
||||
source: community
|
||||
date_added: '2026-02-27'
|
||||
date_added: '2026-03-02'
|
||||
metadata:
|
||||
version: '2.0.0'
|
||||
---
|
||||
|
||||
## Use this skill when
|
||||
|
||||
- Working on tutorial engineer tasks or workflows
|
||||
- Needing guidance, best practices, or checklists for tutorial engineer
|
||||
|
||||
- Transforming code, features, or libraries into learnable content
|
||||
- Creating onboarding materials for new team members
|
||||
- Writing documentation that teaches, not just references
|
||||
- Building educational content for blogs, courses, or workshops
|
||||
|
||||
## Do not use this skill when
|
||||
|
||||
- The task is unrelated to tutorial engineer
|
||||
- You need a different domain or tool outside this scope
|
||||
- Writing API reference documentation (use `api-reference-writer` instead)
|
||||
- Creating marketing or promotional content
|
||||
|
||||
---
|
||||
|
||||
## Instructions
|
||||
|
||||
- Clarify goals, constraints, and required inputs.
|
||||
- Apply relevant best practices and validate outcomes.
|
||||
- Provide actionable steps and verification.
|
||||
- If detailed examples are required, open `resources/implementation-playbook.md`.
|
||||
|
||||
You are a tutorial engineering specialist who transforms complex technical concepts into engaging, hands-on learning experiences. Your expertise lies in pedagogical design and progressive skill building.
|
||||
|
||||
---
|
||||
|
||||
## Core Expertise
|
||||
|
||||
. **Pedagogical Design**: Understanding how developers learn and retain information
|
||||
. **Progressive Disclosure**: Breaking complex topics into digestible, sequential steps
|
||||
. **Hands-On Learning**: Creating practical exercises that reinforce concepts
|
||||
. **Error Anticipation**: Predicting and addressing common mistakes
|
||||
. **Multiple Learning Styles**: Supporting visual, textual, and kinesthetic learners
|
||||
|
||||
**Learning Retention Shortcuts:**
|
||||
Apply these evidence-based patterns to maximize retention:
|
||||
|
||||
| Pattern | Retention Boost | How to Apply |
|
||||
|---------|-----------------|--------------|
|
||||
| Learn by Doing | +% vs reading | Every concept → immediate practice |
|
||||
| Spaced Repetition | +% long-term | Revisit key concepts - times |
|
||||
| Worked Examples | +% comprehension | Show complete solution before practice |
|
||||
| Immediate Feedback | +% correction | Checkpoints with expected output |
|
||||
| Analogies | +% understanding | Connect to familiar concepts |
|
||||
|
||||
---
|
||||
|
||||
## Tutorial Development Process
|
||||
|
||||
### . Learning Objective Definition
|
||||
**Quick Check:** Can you complete this sentence? "After this tutorial, you will be able to ______."
|
||||
|
||||
- Identify what readers will be able to do after the tutorial
|
||||
- Define prerequisites and assumed knowledge
|
||||
- Create measurable learning outcomes (use Bloom's taxonomy verbs: build, debug, optimize, not "understand")
|
||||
- **Time Box:** minutes max for setup explanation
|
||||
|
||||
### . Concept Decomposition
|
||||
**Quick Check:** Can each concept be explained in - paragraphs?
|
||||
|
||||
- Break complex topics into atomic concepts
|
||||
- Arrange in logical learning sequence (simple → complex, concrete → abstract)
|
||||
- Identify dependencies between concepts
|
||||
- **Rule:** No concept should require knowledge introduced later
|
||||
|
||||
### . Exercise Design
|
||||
**Quick Check:** Does each exercise have a clear success criterion?
|
||||
|
||||
- Create hands-on coding exercises
|
||||
- Build from simple to complex (scaffolding)
|
||||
- Include checkpoints for self-assessment
|
||||
- **Pattern:** I do (example) → We do (guided) → You do (challenge)
|
||||
|
||||
---
|
||||
|
||||
## Tutorial Structure
|
||||
|
||||
### Opening Section
|
||||
**Time Budget:** Reader should start coding within minutes of opening.
|
||||
|
||||
- **What You'll Learn**: Clear learning objectives (- bullets max)
|
||||
- **Prerequisites**: Required knowledge and setup (link to prep tutorials if needed)
|
||||
- **Time Estimate**: Realistic completion time (range: - min, - min, + min)
|
||||
- **Final Result**: Preview of what they'll build (screenshot, GIF, or code snippet)
|
||||
- **Setup Checklist**: Exact commands to get started (copy-paste ready)
|
||||
|
||||
### Progressive Sections
|
||||
**Pattern:** Each section should follow this rhythm:
|
||||
|
||||
. **Concept Introduction** (- paragraphs): Theory with real-world analogies
|
||||
. **Minimal Example** (< lines): Simplest working implementation
|
||||
. **Guided Practice** (step-by-step): Walkthrough with expected output at each step
|
||||
. **Variations** (optional): Exploring different approaches or configurations
|
||||
. **Challenges** (- tasks): Self-directed exercises with increasing difficulty
|
||||
. **Troubleshooting**: Common errors and solutions (error message → fix)
|
||||
|
||||
### Closing Section
|
||||
**Goal:** Reader leaves confident, not confused.
|
||||
|
||||
- **Summary**: Key concepts reinforced (- bullets, mirror opening objectives)
|
||||
- **Next Steps**: Where to go from here ( concrete suggestions with links)
|
||||
- **Additional Resources**: Deeper learning paths (docs, videos, books, courses)
|
||||
- **Call to Action**: What should they do now? (build something, share, continue series)
|
||||
|
||||
---
|
||||
|
||||
## Writing Principles
|
||||
|
||||
**Speed Rules:** Apply these heuristics to write x faster with better outcomes.
|
||||
|
||||
| Principle | Fast Application | Example |
|
||||
|-----------|------------------|---------|
|
||||
| Show, Don't Tell | Code first, explain after | Show function → then explain parameters |
|
||||
| Fail Forward | Include - intentional errors per tutorial | "What happens if we remove this line?" |
|
||||
| Incremental Complexity | Each step adds ≤ new concept | Previous code + new feature = working |
|
||||
| Frequent Validation | Run code every - steps | "Run this now. Expected output: ..." |
|
||||
| Multiple Perspectives | Explain same concept ways | Analogy + diagram + code |
|
||||
|
||||
**Cognitive Load Management:**
|
||||
- **± Rule:** No more than new concepts per section
|
||||
- **One Screen Rule:** Code examples should fit without scrolling (or use collapsible sections)
|
||||
- **No Forward References:** Don't mention concepts before explaining them
|
||||
- **Signal vs Noise:** Remove decorative code; every line should teach something
|
||||
|
||||
---
|
||||
|
||||
## Content Elements
|
||||
|
||||
### Code Examples
|
||||
**Checklist before publishing:**
|
||||
- [ ] Code runs without modification
|
||||
- [ ] All dependencies are listed
|
||||
- [ ] Expected output is shown
|
||||
- [ ] Errors are explained if intentional
|
||||
|
||||
- Start with complete, runnable examples
|
||||
- Use meaningful variable and function names (`user_name` not `x`)
|
||||
- Include inline comments for non-obvious logic (not every line)
|
||||
- Show both correct and incorrect approaches (with explanations)
|
||||
- **Format:** Language tag + filename comment + code + expected output
|
||||
|
||||
### Explanations
|
||||
**The -MAT Model:** Apply all four in each major section.
|
||||
|
||||
- Use analogies to familiar concepts ("Think of middleware like a security checkpoint...")
|
||||
- Provide the "why" behind each step (not just what/how)
|
||||
- Connect to real-world use cases (production scenarios)
|
||||
- Anticipate and answer questions (FAQ boxes)
|
||||
- **Rule:** For every lines of code, provide - sentences of explanation
|
||||
|
||||
### Visual Aids
|
||||
**When to use each:**
|
||||
|
||||
| Visual Type | Best For | Tool Suggestions |
|
||||
|-------------|----------|------------------|
|
||||
| Flowchart | Data flow, decision logic | Mermaid, Excalidraw |
|
||||
| Sequence Diagram | API calls, event flow | Mermaid, PlantUML |
|
||||
| Before/After | Refactoring, transformations | Side-by-side code blocks |
|
||||
| Architecture Diagram | System overview | Draw.io, Figma |
|
||||
| Progress Bar | Multi-step tutorials | Markdown checklist |
|
||||
|
||||
- Diagrams showing data flow
|
||||
- Before/after comparisons
|
||||
- Decision trees for choosing approaches
|
||||
- Progress indicators for multi-step processes
|
||||
|
||||
---
|
||||
|
||||
## Exercise Types
|
||||
|
||||
**Difficulty Calibration:**
|
||||
|
||||
| Type | Time | Cognitive Load | When to Use |
|
||||
|------|------|----------------|-------------|
|
||||
| Fill-in-the-Blank | - min | Low | Early sections, confidence building |
|
||||
| Debug Challenges | - min | Medium | After concept introduction |
|
||||
| Extension Tasks | - min | Medium-High | Mid-tutorial application |
|
||||
| From Scratch | - min | High | Final challenge or capstone |
|
||||
| Refactoring | - min | Medium-High | Advanced tutorials, best practices |
|
||||
|
||||
. **Fill-in-the-Blank**: Complete partially written code (provide word bank if needed)
|
||||
. **Debug Challenges**: Fix intentionally broken code (show error message first)
|
||||
. **Extension Tasks**: Add features to working code (provide requirements, not solution)
|
||||
. **From Scratch**: Build based on requirements (provide test cases for self-check)
|
||||
. **Refactoring**: Improve existing implementations (before/after comparison)
|
||||
|
||||
**Exercise Quality Checklist:**
|
||||
- [ ] Clear success criterion ("Your code should print X when given Y")
|
||||
- [ ] Hints available (collapsible or linked)
|
||||
- [ ] Solution provided (collapsible or separate file)
|
||||
- [ ] Common mistakes addressed
|
||||
- [ ] Time estimate given
|
||||
|
||||
---
|
||||
|
||||
## Common Tutorial Formats
|
||||
|
||||
**Choose based on learning goal:**
|
||||
|
||||
| Format | Length | Depth | Best For |
|
||||
|--------|--------|-------|----------|
|
||||
| Quick Start | - min | Surface | First-time setup, hello world |
|
||||
| Deep Dive | - min | Comprehensive | Complex topics, best practices |
|
||||
| Workshop Series | - hours | Multi-part | Bootcamps, team training |
|
||||
| Cookbook Style | - min each | Problem-solution | Recipe collections, patterns |
|
||||
| Interactive Labs | Variable | Hands-on | Sandboxes, hosted environments |
|
||||
|
||||
- **Quick Start**: -minute introduction to get running (one feature, zero config)
|
||||
- **Deep Dive**: - minute comprehensive exploration (theory + practice + edge cases)
|
||||
- **Workshop Series**: Multi-part progressive learning (Part : Basics → Part : Advanced)
|
||||
- **Cookbook Style**: Problem-solution pairs (indexed by use case)
|
||||
- **Interactive Labs**: Hands-on coding environments (Replit, GitPod, CodeSandbox)
|
||||
|
||||
---
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
**Pre-Publish Audit ( minutes):**
|
||||
|
||||
### Comprehension Checks
|
||||
- [ ] Can a beginner follow without getting stuck? (Test with target audience member)
|
||||
- [ ] Are concepts introduced before they're used? (No forward references)
|
||||
- [ ] Is each code example complete and runnable? (Test every snippet)
|
||||
- [ ] Are common errors addressed proactively? (Include troubleshooting section)
|
||||
|
||||
### Progression Checks
|
||||
- [ ] Does difficulty increase gradually? (No sudden complexity spikes)
|
||||
- [ ] Are there enough practice opportunities? ( exercise per - concepts minimum)
|
||||
- [ ] Is the time estimate accurate? (Within ±% of actual completion time)
|
||||
- [ ] Are learning objectives measurable? (Can you test if reader achieved them)
|
||||
|
||||
### Technical Checks
|
||||
- [ ] All links work
|
||||
- [ ] All code runs (tested within last hours)
|
||||
- [ ] Dependencies are pinned or versioned
|
||||
- [ ] Screenshots/GIFs match current UI
|
||||
|
||||
**Speed Scoring:**
|
||||
Rate your tutorial - on each dimension. Target: + average before publishing.
|
||||
|
||||
| Dimension | (Poor) | (Adequate) | (Excellent) |
|
||||
|-----------|----------|--------------|---------------|
|
||||
| Clarity | Confusing steps | Clear but dense | Crystal clear, no re-reading |
|
||||
| Pacing | Too fast/slow | Mostly good | Perfect rhythm |
|
||||
| Practice | No exercises | Some exercises | Exercise per concept |
|
||||
| Troubleshooting | None | Basic errors | Comprehensive FAQ |
|
||||
| Engagement | Dry, academic | Some examples | Stories, analogies, humor |
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
Generate tutorials in Markdown with:
|
||||
|
||||
**Template Structure (copy-paste ready):**
|
||||
[Tutorial Title]
|
||||
|
||||
- The task is unrelated to tutorial engineer
|
||||
- You need a different domain or tool outside this scope
|
||||
> What You'll Learn: [- bullet objectives]
|
||||
> Prerequisites: [Required knowledge + setup links]
|
||||
> Time: [X-Y minutes] | Level: [Beginner/Intermediate/Advanced]
|
||||
|
||||
## Instructions
|
||||
Setup ( minutes)
|
||||
|
||||
- Clarify goals, constraints, and required inputs.
|
||||
- Apply relevant best practices and validate outcomes.
|
||||
- Provide actionable steps and verification.
|
||||
- If detailed examples are required, open `resources/implementation-playbook.md`.
|
||||
[Exact commands, no ambiguity]
|
||||
|
||||
You are a tutorial engineering specialist who transforms complex technical concepts into engaging, hands-on learning experiences. Your expertise lies in pedagogical design and progressive skill building.
|
||||
Section : [Concept Name]
|
||||
|
||||
## Core Expertise
|
||||
[Explanation → Example → Practice pattern]
|
||||
|
||||
1. **Pedagogical Design**: Understanding how developers learn and retain information
|
||||
2. **Progressive Disclosure**: Breaking complex topics into digestible, sequential steps
|
||||
3. **Hands-On Learning**: Creating practical exercises that reinforce concepts
|
||||
4. **Error Anticipation**: Predicting and addressing common mistakes
|
||||
5. **Multiple Learning Styles**: Supporting visual, textual, and kinesthetic learners
|
||||
Try It Yourself
|
||||
|
||||
## Tutorial Development Process
|
||||
[Exercise with clear success criterion]
|
||||
|
||||
1. **Learning Objective Definition**
|
||||
- Identify what readers will be able to do after the tutorial
|
||||
- Define prerequisites and assumed knowledge
|
||||
- Create measurable learning outcomes
|
||||
<details>
|
||||
<summary>Solution</summary>
|
||||
|
||||
2. **Concept Decomposition**
|
||||
- Break complex topics into atomic concepts
|
||||
- Arrange in logical learning sequence
|
||||
- Identify dependencies between concepts
|
||||
[Collapsible solution]
|
||||
|
||||
3. **Exercise Design**
|
||||
- Create hands-on coding exercises
|
||||
- Build from simple to complex
|
||||
- Include checkpoints for self-assessment
|
||||
</details>
|
||||
|
||||
## Tutorial Structure
|
||||
Troubleshooting
|
||||
|
||||
### Opening Section
|
||||
- **What You'll Learn**: Clear learning objectives
|
||||
- **Prerequisites**: Required knowledge and setup
|
||||
- **Time Estimate**: Realistic completion time
|
||||
- **Final Result**: Preview of what they'll build
|
||||
|
||||
### Progressive Sections
|
||||
1. **Concept Introduction**: Theory with real-world analogies
|
||||
2. **Minimal Example**: Simplest working implementation
|
||||
3. **Guided Practice**: Step-by-step walkthrough
|
||||
4. **Variations**: Exploring different approaches
|
||||
5. **Challenges**: Self-directed exercises
|
||||
6. **Troubleshooting**: Common errors and solutions
|
||||
┌─────────────────┬──────────────────┬─────────────┐
|
||||
│ Error │ Cause │ Fix │
|
||||
├─────────────────┼──────────────────┼─────────────┤
|
||||
│ [Error message] │ [Why it happens] │ [Exact fix] │
|
||||
└─────────────────┴──────────────────┴─────────────┘
|
||||
|
||||
### Closing Section
|
||||
- **Summary**: Key concepts reinforced
|
||||
- **Next Steps**: Where to go from here
|
||||
- **Additional Resources**: Deeper learning paths
|
||||
Summary
|
||||
|
||||
## Writing Principles
|
||||
- [Key takeaway ]
|
||||
- [Key takeaway ]
|
||||
- [Key takeaway ]
|
||||
|
||||
- **Show, Don't Tell**: Demonstrate with code, then explain
|
||||
- **Fail Forward**: Include intentional errors to teach debugging
|
||||
- **Incremental Complexity**: Each step builds on the previous
|
||||
- **Frequent Validation**: Readers should run code often
|
||||
- **Multiple Perspectives**: Explain the same concept different ways
|
||||
Next Steps
|
||||
|
||||
## Content Elements
|
||||
. [Concrete action with link]
|
||||
. [Concrete action with link]
|
||||
. [Concrete action with link]
|
||||
|
||||
### Code Examples
|
||||
- Start with complete, runnable examples
|
||||
- Use meaningful variable and function names
|
||||
- Include inline comments for clarity
|
||||
- Show both correct and incorrect approaches
|
||||
|
||||
### Explanations
|
||||
- Use analogies to familiar concepts
|
||||
- Provide the "why" behind each step
|
||||
- Connect to real-world use cases
|
||||
- Anticipate and answer questions
|
||||
|
||||
### Visual Aids
|
||||
- Diagrams showing data flow
|
||||
- Before/after comparisons
|
||||
- Decision trees for choosing approaches
|
||||
- Progress indicators for multi-step processes
|
||||
|
||||
## Exercise Types
|
||||
|
||||
1. **Fill-in-the-Blank**: Complete partially written code
|
||||
2. **Debug Challenges**: Fix intentionally broken code
|
||||
3. **Extension Tasks**: Add features to working code
|
||||
4. **From Scratch**: Build based on requirements
|
||||
5. **Refactoring**: Improve existing implementations
|
||||
|
||||
## Common Tutorial Formats
|
||||
|
||||
- **Quick Start**: 5-minute introduction to get running
|
||||
- **Deep Dive**: 30-60 minute comprehensive exploration
|
||||
- **Workshop Series**: Multi-part progressive learning
|
||||
- **Cookbook Style**: Problem-solution pairs
|
||||
- **Interactive Labs**: Hands-on coding environments
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
- Can a beginner follow without getting stuck?
|
||||
- Are concepts introduced before they're used?
|
||||
- Is each code example complete and runnable?
|
||||
- Are common errors addressed proactively?
|
||||
- Does difficulty increase gradually?
|
||||
- Are there enough practice opportunities?
|
||||
|
||||
## Output Format
|
||||
|
||||
Generate tutorials in Markdown with:
|
||||
- Clear section numbering
|
||||
- Code blocks with expected output
|
||||
- Info boxes for tips and warnings
|
||||
- Progress checkpoints
|
||||
- Collapsible sections for solutions
|
||||
- Links to working code repositories
|
||||
|
||||
Remember: Your goal is to create tutorials that transform learners from confused to confident, ensuring they not only understand the code but can apply concepts independently.
|
||||
|
||||
**Required Elements:**
|
||||
- Clear section numbering (, ., ., , ....)
|
||||
- Code blocks with expected output (comment: `# Output: ...`)
|
||||
- Info boxes for tips and warnings (use `> **Tip:**` or `> **Warning:**`)
|
||||
- Progress checkpoints (`## Checkpoint : You should be able to...`)
|
||||
- Collapsible sections for solutions (`<details><summary>Solution</summary>`)
|
||||
- Links to working code repositories (GitHub, CodeSandbox, Replit)
|
||||
|
||||
**Accessibility Checklist:**
|
||||
- [ ] Alt text on all images
|
||||
- [ ] Color not sole indicator (use labels + color)
|
||||
- [ ] Code has sufficient contrast
|
||||
- [ ] Headings are hierarchical (H → H → H)
|
||||
|
||||
---
|
||||
|
||||
## Behavior Rules
|
||||
|
||||
**Efficiency Heuristics:**
|
||||
|
||||
| Situation | Apply This Rule |
|
||||
|-----------|-----------------|
|
||||
| Reader stuck | Add checkpoint with expected state |
|
||||
| Concept too abstract | Add analogy + concrete example |
|
||||
| Exercise too hard | Add scaffolding (hints, partial solution) |
|
||||
| Tutorial too long | Split into Part , Part |
|
||||
| Low engagement | Add story, real-world scenario |
|
||||
|
||||
- Ground every explanation in actual code or examples. Do not theorize without demonstration.
|
||||
- Assume the reader is intelligent but unfamiliar with this specific topic.
|
||||
- Do not skip steps that seem obvious to you (expert blind spot).
|
||||
- Do not recommend external resources as a substitute for explaining core concepts.
|
||||
- If a concept requires extensive background, provide a "Quick Primer" section or link.
|
||||
- Test all code examples before including them (or mark as "pseudocode").
|
||||
|
||||
**Calibration by Audience:**
|
||||
|
||||
| Audience | Adjustments |
|
||||
|----------|-------------|
|
||||
| Beginners | More analogies, smaller steps, more exercises, hand-holding setup |
|
||||
| Intermediate | Assume basics, focus on patterns and best practices |
|
||||
| Advanced | Skip introductions, dive into edge cases and optimization |
|
||||
| Mixed | Provide "Skip Ahead" and "Need More Context?" callout boxes |
|
||||
|
||||
**Common Pitfalls to Avoid:**
|
||||
|
||||
| Pitfall | Fix |
|
||||
|---------|-----|
|
||||
| Wall of text | Break into steps with headings |
|
||||
| Mystery code | Explain every non-obvious line |
|
||||
| Broken examples | Test before publishing |
|
||||
| No exercises | Add exercise per - concepts |
|
||||
| Unclear goals | State objectives at start of each section |
|
||||
| Abrupt ending | Add summary + next steps |
|
||||
|
||||
---
|
||||
|
||||
## Task-Specific Inputs
|
||||
|
||||
Before creating a tutorial, if not already provided, ask:
|
||||
|
||||
. **Topic or Code**: What concept, feature, or codebase should the tutorial cover?
|
||||
. **Target Audience**: Beginner, intermediate, or advanced developers? Any specific background assumptions?
|
||||
. **Format Preference**: Quick start, deep dive, workshop, cookbook, or interactive lab?
|
||||
. **Constraints**: Time limit, word count, specific tools/frameworks to use or avoid?
|
||||
. **Distribution**: Where will this be published? (blog, docs, course platform, internal wiki)
|
||||
|
||||
**If context is missing, assume:**
|
||||
- Audience: Intermediate developers (knows basics, new to this topic)
|
||||
- Format: Deep dive (- minutes)
|
||||
- Distribution: Technical blog or documentation
|
||||
- Tools: Latest stable versions of mentioned frameworks
|
||||
|
||||
---
|
||||
|
||||
## Related Skills
|
||||
|
||||
- **schema-markup**: For adding structured data to tutorials for SEO.
|
||||
- **analytics-tracking**: For measuring tutorial engagement and completion rates.
|
||||
- **doc-coauthoring**: For expanding tutorials into full documentation.
|
||||
- **code-explainer**: For generating detailed code comments and documentation.
|
||||
- **example-generator**: For creating diverse code examples and edge cases.
|
||||
- **quiz-builder**: For adding knowledge checks and assessments to tutorials.
|
||||
|
||||
@@ -5,7 +5,7 @@ risk: safe
|
||||
source: original
|
||||
date_added: "2026-02-28"
|
||||
metadata:
|
||||
version: 1.0.0
|
||||
version: 2.0.0
|
||||
---
|
||||
|
||||
# Vibe Code Auditor
|
||||
@@ -39,6 +39,12 @@ Before beginning the audit, confirm the following. If any item is missing, state
|
||||
- **Scope defined**: Identify whether the input is a snippet, single file, or multi-file system.
|
||||
- **Context noted**: If no context was provided, state the assumptions made (e.g., "Assuming a web API backend with no specified scale requirements").
|
||||
|
||||
**Quick Scan (first 60 seconds):**
|
||||
- Count files and lines of code
|
||||
- Identify language(s) and framework(s)
|
||||
- Spot obvious red flags: hardcoded secrets, bare excepts, TODOs, commented-out code
|
||||
- Note the entry point(s) and data flow direction
|
||||
|
||||
---
|
||||
|
||||
## Audit Dimensions
|
||||
@@ -47,57 +53,128 @@ Evaluate the code across all seven dimensions below. For each finding, record: t
|
||||
|
||||
**Do not invent findings. Do not report issues you cannot substantiate from the code provided.**
|
||||
|
||||
**Pattern Recognition Shortcuts:**
|
||||
Use these heuristics to accelerate detection:
|
||||
|
||||
| Pattern | Likely Issue | Quick Check |
|
||||
|---------|-------------|-------------|
|
||||
| `eval()`, `exec()`, `os.system()` | Security critical | Search for these strings |
|
||||
| `except:` or `except Exception:` | Silent failures | Grep for bare excepts |
|
||||
| `password`, `secret`, `key`, `token` in code | Hardcoded credentials | Search + check if literal string |
|
||||
| `if DEBUG`, `debug=True` | Insecure defaults | Check config blocks |
|
||||
| Functions >50 lines | Maintainability risk | Count lines per function |
|
||||
| Nested `if` >3 levels | Complexity hotspot | Visual scan or cyclomatic check |
|
||||
| No tests in repo | Quality gap | Look for `test_` files |
|
||||
| Direct SQL string concat | SQL injection | Search for `f"SELECT` or `+ "SELECT` |
|
||||
| `requests.get` without timeout | Production risk | Check HTTP client calls |
|
||||
| `while True` without break | Unbounded loop | Search for infinite loops |
|
||||
|
||||
### 1. Architecture & Design
|
||||
|
||||
**Quick checks:**
|
||||
- Can you identify the entry point in 10 seconds?
|
||||
- Are there clear boundaries between layers (API, business logic, data)?
|
||||
- Does any single file exceed 300 lines?
|
||||
|
||||
- Separation of concerns violations (e.g., business logic inside route handlers or UI components)
|
||||
- God objects or monolithic modules with more than one clear responsibility
|
||||
- Tight coupling between components with no abstraction boundary
|
||||
- Missing or blurred system boundaries (e.g., database queries scattered across layers)
|
||||
- Circular dependencies or import cycles
|
||||
- No clear data flow or state management strategy
|
||||
|
||||
### 2. Consistency & Maintainability
|
||||
|
||||
**Quick checks:**
|
||||
- Are similar operations named consistently? (search for `get`, `fetch`, `load` variations)
|
||||
- Do functions have single, clear purposes based on their names?
|
||||
- Is duplicated logic visible? (search for repeated code blocks)
|
||||
|
||||
- Naming inconsistencies (e.g., `get_user` vs `fetchUser` vs `retrieveUserData` for the same operation)
|
||||
- Mixed paradigms without justification (e.g., OOP and procedural code interleaved arbitrarily)
|
||||
- Copy-paste logic that should be extracted into a shared function
|
||||
- Copy-paste logic that should be extracted into a shared function (3+ repetitions = extract)
|
||||
- Abstractions that obscure rather than clarify intent
|
||||
- Inconsistent error handling patterns across modules
|
||||
- Magic numbers or strings without constants or configuration
|
||||
|
||||
### 3. Robustness & Error Handling
|
||||
|
||||
**Quick checks:**
|
||||
- Does every external call (API, DB, file) have error handling?
|
||||
- Are there any bare `except:` blocks?
|
||||
- What happens if inputs are empty, null, or malformed?
|
||||
|
||||
- Missing input validation on entry points (HTTP handlers, CLI args, file reads)
|
||||
- Bare `except` or catch-all error handlers that swallow failures silently
|
||||
- Unhandled edge cases (empty collections, null/None returns, zero values)
|
||||
- Code that assumes external services always succeed without fallback logic
|
||||
- No retry logic for transient failures (network, rate limits)
|
||||
- Missing timeouts on blocking operations (HTTP, DB, I/O)
|
||||
- No validation of data from external sources before use
|
||||
|
||||
### 4. Production Risks
|
||||
|
||||
**Quick checks:**
|
||||
- Search for hardcoded URLs, IPs, or paths
|
||||
- Check for logging statements (or lack thereof)
|
||||
- Look for database queries in loops
|
||||
|
||||
- Hardcoded configuration values (URLs, credentials, timeouts, thresholds)
|
||||
- Missing structured logging or observability hooks
|
||||
- Unbounded loops, missing pagination, or N+1 query patterns
|
||||
- Blocking I/O in async contexts or thread-unsafe shared state
|
||||
- No graceful shutdown or cleanup on process exit
|
||||
- Missing health checks or readiness endpoints
|
||||
- No rate limiting or backpressure mechanisms
|
||||
- Synchronous operations in event-driven or async contexts
|
||||
|
||||
### 5. Security & Safety
|
||||
|
||||
**Quick checks:**
|
||||
- Search for: `eval`, `exec`, `os.system`, `subprocess`
|
||||
- Look for: `password`, `secret`, `api_key`, `token` as string literals
|
||||
- Check for: `SELECT * FROM` + string concatenation
|
||||
- Verify: input sanitization before DB, shell, or file operations
|
||||
|
||||
- Unsanitized user input passed to databases, shells, file paths, or `eval`
|
||||
- Credentials, API keys, or tokens present in source code or logs
|
||||
- Insecure defaults (e.g., `DEBUG=True`, permissive CORS, no rate limiting)
|
||||
- Trust boundary violations (e.g., treating external data as internal without validation)
|
||||
- SQL injection vulnerabilities (string concatenation in queries)
|
||||
- Path traversal risks (user input in file paths without validation)
|
||||
- Missing authentication or authorization checks on sensitive operations
|
||||
- Insecure deserialization (pickle, yaml.load without SafeLoader)
|
||||
|
||||
### 6. Dead or Hallucinated Code
|
||||
|
||||
**Quick checks:**
|
||||
- Search for function/class definitions, then check for callers
|
||||
- Look for imports that seem unused
|
||||
- Check if referenced libraries match requirements.txt or package.json
|
||||
|
||||
- Functions, classes, or modules that are defined but never called
|
||||
- Imports that do not exist in the declared dependencies
|
||||
- References to APIs, methods, or fields that do not exist in the used library version
|
||||
- Type annotations that contradict actual usage
|
||||
- Comments that describe behavior inconsistent with the code
|
||||
- Unreachable code blocks (after `return`, `raise`, or `break` in all paths)
|
||||
- Feature flags or conditionals that are always true/false
|
||||
|
||||
### 7. Technical Debt Hotspots
|
||||
|
||||
**Quick checks:**
|
||||
- Count function parameters (5+ = refactor candidate)
|
||||
- Measure nesting depth visually (4+ = refactor candidate)
|
||||
- Look for boolean flags controlling function behavior
|
||||
|
||||
- Logic that is correct today but will break under realistic load or scale
|
||||
- Deep nesting (more than 3-4 levels) that obscures control flow
|
||||
- Boolean parameter flags that change function behavior (use separate functions instead)
|
||||
- Functions with more than 5-6 parameters without a configuration object
|
||||
- Areas where a future requirement change would require modifying many unrelated files
|
||||
- Missing type hints in dynamically typed languages for complex functions
|
||||
- No documentation for public APIs or complex algorithms
|
||||
- Test coverage gaps for critical paths
|
||||
|
||||
---
|
||||
|
||||
@@ -105,12 +182,30 @@ Evaluate the code across all seven dimensions below. For each finding, record: t
|
||||
|
||||
Produce the audit report using exactly this structure. Do not omit sections. If a section has no findings, write "None identified."
|
||||
|
||||
**Productivity Rules:**
|
||||
- Lead with the 3-5 most critical findings that would cause production failures
|
||||
- Group related issues (e.g., "3 locations with hardcoded credentials" instead of listing separately)
|
||||
- Provide copy-paste-ready fixes where possible (exact code snippets)
|
||||
- Use severity tags consistently: `[CRITICAL]`, `[HIGH]`, `[MEDIUM]`, `[LOW]`
|
||||
|
||||
---
|
||||
|
||||
### Audit Report
|
||||
|
||||
**Input:** [file name(s) or "code snippet"]
|
||||
**Assumptions:** [list any assumptions made about context or environment]
|
||||
**Quick Stats:** [X files, Y lines of code, Z language/framework]
|
||||
|
||||
#### Executive Summary (Read This First)
|
||||
|
||||
In 3-5 bullets, state the most important findings that determine whether this code can go to production:
|
||||
|
||||
```
|
||||
- [CRITICAL/HIGH] One-line summary of the most severe issue
|
||||
- [CRITICAL/HIGH] Second most severe issue
|
||||
- [MEDIUM] Notable pattern that will cause future problems
|
||||
- Overall: Deployable as-is / Needs fixes / Requires major rework
|
||||
```
|
||||
|
||||
#### Critical Issues (Must Fix Before Production)
|
||||
|
||||
@@ -124,6 +219,11 @@ Location: filename.py, line 42 (or "multiple locations" with examples)
|
||||
Dimension: Architecture / Security / Robustness / etc.
|
||||
Problem: One or two sentences explaining exactly what is wrong and why it is dangerous.
|
||||
Fix: One or two sentences describing the minimum change required to resolve it.
|
||||
Code Fix (if applicable):
|
||||
```python
|
||||
# Before: problematic code
|
||||
# After: corrected version
|
||||
```
|
||||
```
|
||||
|
||||
#### High-Risk Issues
|
||||
@@ -152,23 +252,37 @@ Provide a score using the rubric below, then write 2-3 sentences justifying it w
|
||||
| 71-85 | Production-viable with targeted fixes. Known risks are bounded. |
|
||||
| 86-100 | Production-ready. Minor improvements only. |
|
||||
|
||||
Score deductions:
|
||||
**Scoring Algorithm:**
|
||||
|
||||
- Each Critical issue: -10 to -20 points depending on blast radius
|
||||
- Each High issue: -5 to -10 points
|
||||
- Pervasive maintainability debt (3+ Medium issues in one dimension): -5 points
|
||||
```
|
||||
Start at 100 points
|
||||
For each CRITICAL issue: -15 points (security: -20)
|
||||
For each HIGH issue: -8 points
|
||||
For each MEDIUM issue: -3 points
|
||||
For pervasive patterns (3+ similar issues): -5 additional points
|
||||
Floor: 0, Ceiling: 100
|
||||
```
|
||||
|
||||
#### Refactoring Priorities
|
||||
|
||||
List the top 3-5 changes in order of impact. Each item must reference a specific finding from above.
|
||||
|
||||
```
|
||||
1. [Priority] Fix title — addresses [CRITICAL/HIGH ref] — estimated effort: S/M/L
|
||||
2. ...
|
||||
1. [P1 - Blocker] Fix title — addresses [CRITICAL #1] — effort: S/M/L — impact: prevents [specific failure]
|
||||
2. [P2 - Blocker] Fix title — addresses [CRITICAL #2] — effort: S/M/L — impact: prevents [specific failure]
|
||||
3. [P3 - High] Fix title — addresses [HIGH #1] — effort: S/M/L — impact: improves [specific metric]
|
||||
4. [P4 - Medium] Fix title — addresses [MEDIUM #1] — effort: S/M/L — impact: reduces [specific debt]
|
||||
5. [P5 - Optional] Fix title — addresses [LOW #1] — effort: S/M/L — impact: nice-to-have
|
||||
```
|
||||
|
||||
Effort scale: S = < 1 day, M = 1-3 days, L = > 3 days.
|
||||
|
||||
**Quick Wins (fix in <1 hour):**
|
||||
List any issues that can be resolved immediately with minimal effort:
|
||||
```
|
||||
- [Issue name]: [one-line fix description]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Behavior Rules
|
||||
@@ -180,6 +294,20 @@ Effort scale: S = < 1 day, M = 1-3 days, L = > 3 days.
|
||||
- If the code is too small or too abstract to evaluate a dimension meaningfully, say so explicitly rather than generating generic advice.
|
||||
- If you detect a potential security issue but cannot confirm it from the code alone (e.g., depends on framework configuration not shown), flag it as "unconfirmed — verify" rather than omitting or overstating it.
|
||||
|
||||
**Efficiency Rules:**
|
||||
- Scan for critical patterns first (security, data loss, crashes) before deeper analysis
|
||||
- Group similar issues by pattern rather than listing each occurrence separately
|
||||
- Provide exact code fixes for critical/high issues when the solution is straightforward
|
||||
- Skip dimensions that are not applicable to the code size or type (state "Not applicable: [reason]")
|
||||
- Focus on issues that would cause production incidents, not theoretical concerns
|
||||
|
||||
**Calibration:**
|
||||
- For snippets (<100 lines): Focus on security, robustness, and obvious bugs only
|
||||
- For single files (100-500 lines): Add architecture and maintainability checks
|
||||
- For multi-file systems (500+ lines): Full audit across all 7 dimensions
|
||||
- For production code: Emphasize security, observability, and failure modes
|
||||
- For prototypes: Emphasize scalability limits and technical debt
|
||||
|
||||
---
|
||||
|
||||
## Task-Specific Inputs
|
||||
@@ -189,6 +317,12 @@ Before auditing, if not already provided, ask:
|
||||
1. **Code or files**: Share the source code to audit. Accepted: single file, multiple files, directory listing, or snippet.
|
||||
2. **Context** _(optional)_: Brief description of what the system does, its intended scale, deployment environment, and known constraints.
|
||||
3. **Target environment** _(optional)_: Target runtime (e.g., production web service, CLI tool, data pipeline). Used to calibrate risk severity.
|
||||
4. **Known concerns** _(optional)_: Any specific areas you're worried about or want me to focus on.
|
||||
|
||||
**If context is missing, assume:**
|
||||
- Language/framework is evident from the code
|
||||
- Deployment target is production web service (most common)
|
||||
- Scale expectations are moderate (100-1000 users) unless code suggests otherwise
|
||||
|
||||
---
|
||||
|
||||
@@ -197,3 +331,5 @@ Before auditing, if not already provided, ask:
|
||||
- **schema-markup**: For adding structured data after code is production-ready.
|
||||
- **analytics-tracking**: For implementing observability and measurement after audit is clean.
|
||||
- **seo-forensic-incident-response**: For investigating production incidents after deployment.
|
||||
- **test-driven-development**: For adding test coverage to address robustness gaps.
|
||||
- **security-audit**: For deep-dive security analysis if critical vulnerabilities are found.
|
||||
|
||||
@@ -7,9 +7,56 @@ import { fileURLToPath } from 'url';
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const ROOT_DIR = path.resolve(__dirname, '..');
|
||||
const REPO_ZIP_URL = 'https://github.com/sickn33/antigravity-awesome-skills/archive/refs/heads/main.zip';
|
||||
|
||||
function followRedirects(url, dest) {
|
||||
const UPSTREAM_REPO = 'https://github.com/sickn33/antigravity-awesome-skills.git';
|
||||
const UPSTREAM_NAME = 'upstream';
|
||||
const REPO_TAR_URL = 'https://github.com/sickn33/antigravity-awesome-skills/archive/refs/heads/main.tar.gz';
|
||||
const REPO_ZIP_URL = 'https://github.com/sickn33/antigravity-awesome-skills/archive/refs/heads/main.zip';
|
||||
const COMMITS_API_URL = 'https://api.github.com/repos/sickn33/antigravity-awesome-skills/commits/main';
|
||||
const SHA_FILE = path.join(__dirname, '.last-sync-sha');
|
||||
|
||||
// ─── Utility helpers ───
|
||||
|
||||
const MIME_TYPES = {
|
||||
'.html': 'text/html', '.css': 'text/css', '.js': 'application/javascript',
|
||||
'.json': 'application/json', '.md': 'text/markdown', '.txt': 'text/plain',
|
||||
'.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
|
||||
'.gif': 'image/gif', '.svg': 'image/svg+xml', '.ico': 'image/x-icon',
|
||||
'.yaml': 'text/yaml', '.yml': 'text/yaml', '.xml': 'text/xml',
|
||||
'.py': 'text/plain', '.sh': 'text/plain', '.bat': 'text/plain',
|
||||
};
|
||||
|
||||
/** Check if git is available on this system. Cached after first check. */
|
||||
let _gitAvailable = null;
|
||||
function isGitAvailable() {
|
||||
if (_gitAvailable !== null) return _gitAvailable;
|
||||
try {
|
||||
execSync('git --version', { stdio: 'ignore' });
|
||||
// Also check we're inside a git repo
|
||||
execSync('git rev-parse --git-dir', { cwd: ROOT_DIR, stdio: 'ignore' });
|
||||
_gitAvailable = true;
|
||||
} catch {
|
||||
_gitAvailable = false;
|
||||
}
|
||||
return _gitAvailable;
|
||||
}
|
||||
|
||||
/** Run a git command in the project root. */
|
||||
function git(cmd) {
|
||||
return execSync(`git ${cmd}`, { cwd: ROOT_DIR, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
||||
}
|
||||
|
||||
/** Ensure the upstream remote exists. */
|
||||
function ensureUpstream() {
|
||||
const remotes = git('remote');
|
||||
if (!remotes.split('\n').includes(UPSTREAM_NAME)) {
|
||||
git(`remote add ${UPSTREAM_NAME} ${UPSTREAM_REPO}`);
|
||||
console.log(`[Sync] Added upstream remote: ${UPSTREAM_REPO}`);
|
||||
}
|
||||
}
|
||||
|
||||
/** Download a file following HTTP redirects. */
|
||||
function downloadFile(url, dest) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = fs.createWriteStream(dest);
|
||||
const request = (url) => {
|
||||
@@ -24,86 +71,36 @@ function followRedirects(url, dest) {
|
||||
}
|
||||
res.pipe(file);
|
||||
file.on('finish', () => { file.close(); resolve(); });
|
||||
}).on('error', (err) => { fs.unlink(dest, () => {}); reject(err); });
|
||||
}).on('error', (err) => { fs.unlink(dest, () => { }); reject(err); });
|
||||
};
|
||||
request(url);
|
||||
});
|
||||
}
|
||||
|
||||
export default function refreshSkillsPlugin() {
|
||||
return {
|
||||
name: 'refresh-skills',
|
||||
configureServer(server) {
|
||||
server.middlewares.use('/api/refresh-skills', async (req, res) => {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
|
||||
const zipPath = path.join(ROOT_DIR, 'update.zip');
|
||||
const tempDir = path.join(ROOT_DIR, 'update_temp');
|
||||
|
||||
/** Check latest commit SHA via GitHub API. */
|
||||
function checkRemoteSha() {
|
||||
return new Promise((resolve) => {
|
||||
https.get(COMMITS_API_URL, {
|
||||
headers: { 'User-Agent': 'antigravity-skills-app', 'Accept': 'application/vnd.github.v3+json' },
|
||||
}, (res) => {
|
||||
let body = '';
|
||||
res.on('data', (chunk) => { body += chunk; });
|
||||
res.on('end', () => {
|
||||
try {
|
||||
// 1. Download the ZIP
|
||||
console.log('[Sync] Downloading latest skills from GitHub...');
|
||||
await followRedirects(REPO_ZIP_URL, zipPath);
|
||||
|
||||
// 2. Extract with PowerShell (Windows) or unzip (Unix)
|
||||
console.log('[Sync] Extracting archive...');
|
||||
if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
execSync(`powershell -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${tempDir}' -Force"`, { stdio: 'ignore' });
|
||||
if (res.statusCode === 200) {
|
||||
resolve(JSON.parse(body).sha || null);
|
||||
} else {
|
||||
fs.mkdirSync(tempDir, { recursive: true });
|
||||
execSync(`unzip -o "${zipPath}" -d "${tempDir}"`, { stdio: 'ignore' });
|
||||
resolve(null);
|
||||
}
|
||||
|
||||
// 3. Copy skills folder + index
|
||||
const extractedRoot = path.join(tempDir, 'antigravity-awesome-skills-main');
|
||||
const srcSkills = path.join(extractedRoot, 'skills');
|
||||
const srcIndex = path.join(extractedRoot, 'skills_index.json');
|
||||
const destSkills = path.join(ROOT_DIR, 'skills');
|
||||
const destIndex = path.join(ROOT_DIR, 'skills_index.json');
|
||||
|
||||
if (!fs.existsSync(srcSkills)) {
|
||||
throw new Error('Skills folder not found in downloaded archive.');
|
||||
}
|
||||
|
||||
// Replace skills folder
|
||||
if (fs.existsSync(destSkills)) fs.rmSync(destSkills, { recursive: true, force: true });
|
||||
copyFolderSync(srcSkills, destSkills);
|
||||
|
||||
// Replace index
|
||||
if (fs.existsSync(srcIndex)) fs.copyFileSync(srcIndex, destIndex);
|
||||
|
||||
// 4. Re-run setup_web.js logic to update web-app/public
|
||||
const webPublic = path.join(__dirname, 'public');
|
||||
const webSkills = path.join(webPublic, 'skills');
|
||||
const webIndex = path.join(webPublic, 'skills.json');
|
||||
|
||||
if (fs.existsSync(webSkills)) fs.rmSync(webSkills, { recursive: true, force: true });
|
||||
copyFolderSync(destSkills, webSkills);
|
||||
if (fs.existsSync(destIndex)) fs.copyFileSync(destIndex, webIndex);
|
||||
|
||||
// Count skills
|
||||
const skillsData = JSON.parse(fs.readFileSync(webIndex, 'utf-8'));
|
||||
const count = Array.isArray(skillsData) ? skillsData.length : 0;
|
||||
|
||||
console.log(`[Sync] ✅ Successfully synced ${count} skills!`);
|
||||
res.end(JSON.stringify({ success: true, count }));
|
||||
|
||||
} catch (err) {
|
||||
console.error('[Sync] ❌ Failed:', err.message);
|
||||
res.statusCode = 500;
|
||||
res.end(JSON.stringify({ success: false, error: err.message }));
|
||||
} finally {
|
||||
// Cleanup
|
||||
if (fs.existsSync(zipPath)) fs.unlinkSync(zipPath);
|
||||
if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
} catch {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}).on('error', () => resolve(null));
|
||||
});
|
||||
}
|
||||
|
||||
/** Copy folder recursively. */
|
||||
function copyFolderSync(from, to) {
|
||||
if (!fs.existsSync(to)) fs.mkdirSync(to, { recursive: true });
|
||||
for (const element of fs.readdirSync(from)) {
|
||||
@@ -116,3 +113,186 @@ function copyFolderSync(from, to) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Sync strategies ───
|
||||
|
||||
/**
|
||||
* FAST PATH: Use git fetch + merge (only downloads delta).
|
||||
* Typically completes in 5-15 seconds.
|
||||
*/
|
||||
async function syncWithGit() {
|
||||
ensureUpstream();
|
||||
|
||||
const headBefore = git('rev-parse HEAD');
|
||||
|
||||
console.log('[Sync] Fetching from upstream (git)...');
|
||||
git(`fetch ${UPSTREAM_NAME} main`);
|
||||
|
||||
const upstreamHead = git(`rev-parse ${UPSTREAM_NAME}/main`);
|
||||
|
||||
if (headBefore === upstreamHead) {
|
||||
return { upToDate: true };
|
||||
}
|
||||
|
||||
console.log('[Sync] Merging updates...');
|
||||
try {
|
||||
git(`merge ${UPSTREAM_NAME}/main --ff-only`);
|
||||
} catch {
|
||||
console.log('[Sync] Fast-forward failed, resetting to upstream...');
|
||||
git(`reset --hard ${UPSTREAM_NAME}/main`);
|
||||
}
|
||||
|
||||
return { upToDate: false };
|
||||
}
|
||||
|
||||
/**
|
||||
* FALLBACK: Download archive when git is not available.
|
||||
* Tries tar.gz first (faster), falls back to zip if tar isn't available.
|
||||
*/
|
||||
async function syncWithArchive() {
|
||||
// Check SHA first to skip if up to date
|
||||
const remoteSha = await checkRemoteSha();
|
||||
if (remoteSha) {
|
||||
let storedSha = null;
|
||||
if (fs.existsSync(SHA_FILE)) {
|
||||
storedSha = fs.readFileSync(SHA_FILE, 'utf-8').trim();
|
||||
}
|
||||
if (storedSha === remoteSha) {
|
||||
return { upToDate: true };
|
||||
}
|
||||
}
|
||||
|
||||
const tempDir = path.join(ROOT_DIR, 'update_temp');
|
||||
|
||||
// Try tar first, fall back to zip
|
||||
let useTar = true;
|
||||
try {
|
||||
execSync('tar --version', { stdio: 'ignore' });
|
||||
} catch {
|
||||
useTar = false;
|
||||
}
|
||||
|
||||
const archivePath = path.join(ROOT_DIR, useTar ? 'update.tar.gz' : 'update.zip');
|
||||
|
||||
try {
|
||||
// 1. Download
|
||||
console.log(`[Sync] Downloading (${useTar ? 'tar.gz' : 'zip'})...`);
|
||||
await downloadFile(useTar ? REPO_TAR_URL : REPO_ZIP_URL, archivePath);
|
||||
|
||||
// 2. Extract
|
||||
console.log('[Sync] Extracting...');
|
||||
if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
fs.mkdirSync(tempDir, { recursive: true });
|
||||
|
||||
if (useTar) {
|
||||
execSync(`tar -xzf "${archivePath}" -C "${tempDir}"`, { stdio: 'ignore' });
|
||||
} else if (process.platform === 'win32') {
|
||||
execSync(`powershell -Command "Expand-Archive -Path '${archivePath}' -DestinationPath '${tempDir}' -Force"`, { stdio: 'ignore' });
|
||||
} else {
|
||||
execSync(`unzip -o "${archivePath}" -d "${tempDir}"`, { stdio: 'ignore' });
|
||||
}
|
||||
|
||||
// 3. Move skills to root
|
||||
const extractedRoot = path.join(tempDir, 'antigravity-awesome-skills-main');
|
||||
const srcSkills = path.join(extractedRoot, 'skills');
|
||||
const srcIndex = path.join(extractedRoot, 'skills_index.json');
|
||||
const destSkills = path.join(ROOT_DIR, 'skills');
|
||||
const destIndex = path.join(ROOT_DIR, 'skills_index.json');
|
||||
|
||||
if (!fs.existsSync(srcSkills)) {
|
||||
throw new Error('Skills folder not found in downloaded archive.');
|
||||
}
|
||||
|
||||
console.log('[Sync] Updating skills...');
|
||||
if (fs.existsSync(destSkills)) fs.rmSync(destSkills, { recursive: true, force: true });
|
||||
fs.renameSync(srcSkills, destSkills);
|
||||
if (fs.existsSync(srcIndex)) fs.copyFileSync(srcIndex, destIndex);
|
||||
|
||||
// Save SHA
|
||||
if (remoteSha) fs.writeFileSync(SHA_FILE, remoteSha, 'utf-8');
|
||||
|
||||
return { upToDate: false };
|
||||
|
||||
} finally {
|
||||
if (fs.existsSync(archivePath)) fs.unlinkSync(archivePath);
|
||||
if (fs.existsSync(tempDir)) fs.rmSync(tempDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Vite Plugin ───
|
||||
|
||||
export default function refreshSkillsPlugin() {
|
||||
return {
|
||||
name: 'refresh-skills',
|
||||
configureServer(server) {
|
||||
// Serve /skills.json directly from ROOT_DIR
|
||||
server.middlewares.use('/skills.json', (req, res, next) => {
|
||||
const filePath = path.join(ROOT_DIR, 'skills_index.json');
|
||||
if (fs.existsSync(filePath)) {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
fs.createReadStream(filePath).pipe(res);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
// Serve /skills/* directly from ROOT_DIR/skills/
|
||||
server.middlewares.use((req, res, next) => {
|
||||
if (!req.url || !req.url.startsWith('/skills/')) return next();
|
||||
|
||||
const relativePath = decodeURIComponent(req.url.replace(/\?.*$/, ''));
|
||||
const filePath = path.join(ROOT_DIR, relativePath);
|
||||
|
||||
const resolved = path.resolve(filePath);
|
||||
if (!resolved.startsWith(path.join(ROOT_DIR, 'skills'))) return next();
|
||||
|
||||
if (fs.existsSync(filePath) && fs.statSync(filePath).isFile()) {
|
||||
const ext = path.extname(filePath).toLowerCase();
|
||||
res.setHeader('Content-Type', MIME_TYPES[ext] || 'application/octet-stream');
|
||||
fs.createReadStream(filePath).pipe(res);
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
});
|
||||
|
||||
// Sync API endpoint
|
||||
server.middlewares.use('/api/refresh-skills', async (req, res) => {
|
||||
res.setHeader('Content-Type', 'application/json');
|
||||
|
||||
try {
|
||||
let result;
|
||||
|
||||
if (isGitAvailable()) {
|
||||
console.log('[Sync] Using git (fast path)...');
|
||||
result = await syncWithGit();
|
||||
} else {
|
||||
console.log('[Sync] Git not available, using archive download (slower)...');
|
||||
result = await syncWithArchive();
|
||||
}
|
||||
|
||||
if (result.upToDate) {
|
||||
console.log('[Sync] ✅ Already up to date!');
|
||||
res.end(JSON.stringify({ success: true, upToDate: true }));
|
||||
return;
|
||||
}
|
||||
|
||||
// Count skills
|
||||
const indexPath = path.join(ROOT_DIR, 'skills_index.json');
|
||||
let count = 0;
|
||||
if (fs.existsSync(indexPath)) {
|
||||
const data = JSON.parse(fs.readFileSync(indexPath, 'utf-8'));
|
||||
count = Array.isArray(data) ? data.length : 0;
|
||||
}
|
||||
|
||||
console.log(`[Sync] ✅ Successfully synced ${count} skills!`);
|
||||
res.end(JSON.stringify({ success: true, upToDate: false, count }));
|
||||
|
||||
} catch (err) {
|
||||
console.error('[Sync] ❌ Failed:', err.message);
|
||||
res.statusCode = 500;
|
||||
res.end(JSON.stringify({ success: false, error: err.message }));
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Search, Filter, Book, AlertCircle, ArrowRight, Star, RefreshCw } from 'lucide-react';
|
||||
import { Search, Filter, Book, AlertCircle, ArrowRight, Star, RefreshCw, ArrowUpDown } from 'lucide-react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { supabase } from '../lib/supabase';
|
||||
|
||||
@@ -11,6 +11,7 @@ export function Home() {
|
||||
const [categoryFilter, setCategoryFilter] = useState('all');
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [stars, setStars] = useState({});
|
||||
const [sortBy, setSortBy] = useState('default');
|
||||
const [syncing, setSyncing] = useState(false);
|
||||
const [syncMsg, setSyncMsg] = useState(null);
|
||||
|
||||
@@ -105,8 +106,17 @@ export function Home() {
|
||||
result = result.filter(skill => skill.category === categoryFilter);
|
||||
}
|
||||
|
||||
// Apply sorting
|
||||
if (sortBy === 'stars') {
|
||||
result = [...result].sort((a, b) => (stars[b.id] || 0) - (stars[a.id] || 0));
|
||||
} else if (sortBy === 'newest') {
|
||||
result = [...result].sort((a, b) => (b.date_added || '').localeCompare(a.date_added || ''));
|
||||
} else if (sortBy === 'az') {
|
||||
result = [...result].sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
setFilteredSkills(result);
|
||||
}, [search, categoryFilter, skills]);
|
||||
}, [search, categoryFilter, sortBy, skills, stars]);
|
||||
|
||||
// Sort categories by count (most skills first), with 'uncategorized' at the end
|
||||
const categoryStats = {};
|
||||
@@ -130,7 +140,9 @@ export function Home() {
|
||||
<div className="flex items-center gap-3">
|
||||
{syncMsg && (
|
||||
<span className={`text-sm font-medium px-3 py-1.5 rounded-full ${syncMsg.type === 'success'
|
||||
? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400'
|
||||
? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400'
|
||||
: syncMsg.type === 'info'
|
||||
? 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400'
|
||||
: 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400'
|
||||
}`}>
|
||||
{syncMsg.text}
|
||||
@@ -144,12 +156,16 @@ export function Home() {
|
||||
const res = await fetch('/api/refresh-skills');
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
setSyncMsg({ type: 'success', text: `✅ Synced ${data.count} skills!` });
|
||||
// Reload skills data
|
||||
const freshRes = await fetch('/skills.json');
|
||||
const freshData = await freshRes.json();
|
||||
setSkills(freshData);
|
||||
setFilteredSkills(freshData);
|
||||
if (data.upToDate) {
|
||||
setSyncMsg({ type: 'info', text: 'ℹ️ Skills are already up to date!' });
|
||||
} else {
|
||||
setSyncMsg({ type: 'success', text: `✅ Synced ${data.count} skills!` });
|
||||
// Reload skills data only when there are actual updates
|
||||
const freshRes = await fetch('/skills.json');
|
||||
const freshData = await freshRes.json();
|
||||
setSkills(freshData);
|
||||
setFilteredSkills(freshData);
|
||||
}
|
||||
} else {
|
||||
setSyncMsg({ type: 'error', text: `❌ ${data.error}` });
|
||||
}
|
||||
@@ -196,6 +212,17 @@ export function Home() {
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<ArrowUpDown className="h-4 w-4 text-slate-500 shrink-0 ml-2" />
|
||||
<select
|
||||
className="h-9 rounded-md border border-slate-200 bg-slate-50 px-3 text-sm outline-none focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-50 min-w-[130px]"
|
||||
value={sortBy}
|
||||
onChange={(e) => setSortBy(e.target.value)}
|
||||
>
|
||||
<option value="default">Default</option>
|
||||
<option value="stars">⭐ Most Stars</option>
|
||||
<option value="newest">🆕 Newest</option>
|
||||
<option value="az">🔤 A → Z</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user