mirror of
https://github.com/unclecatvn/agent-skills.git
synced 2026-09-14 20:53:17 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5bad070965 | |||
| ad4af2f3cd | |||
| 9ca3d5b7d2 |
@@ -0,0 +1,70 @@
|
||||
name: Auto tag and release from package.json
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
paths:
|
||||
- "package.json"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: auto-tag-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
tag-and-release:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !contains(github.event.head_commit.message, '[skip tag]') }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Detect version bump
|
||||
id: ver
|
||||
run: |
|
||||
set -euo pipefail
|
||||
CUR="$(node -p "require('./package.json').version")"
|
||||
PREV="$(git show HEAD~1:package.json 2>/dev/null | node -p "JSON.parse(require('fs').readFileSync(0,'utf8')).version" 2>/dev/null || echo "")"
|
||||
echo "current=$CUR" >> "$GITHUB_OUTPUT"
|
||||
echo "previous=$PREV" >> "$GITHUB_OUTPUT"
|
||||
if [ "$CUR" != "$PREV" ]; then
|
||||
echo "bumped=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "bumped=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Skip if no version change
|
||||
if: steps.ver.outputs.bumped != 'true'
|
||||
run: echo "Version unchanged vs previous commit; skipping."
|
||||
|
||||
- name: Tag, push, and create GitHub Release
|
||||
if: steps.ver.outputs.bumped == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
V="${{ steps.ver.outputs.current }}"
|
||||
TAG="v${V}"
|
||||
git fetch --tags --force
|
||||
if git rev-parse "$TAG" >/dev/null 2>&1; then
|
||||
echo "Tag $TAG already exists locally; skipping."
|
||||
exit 0
|
||||
fi
|
||||
if git ls-remote --tags origin "refs/tags/$TAG" | grep -q .; then
|
||||
echo "Tag $TAG already exists on remote; skipping."
|
||||
exit 0
|
||||
fi
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git tag -a "$TAG" -m "$TAG"
|
||||
git push origin "$TAG"
|
||||
if gh release view "$TAG" >/dev/null 2>&1; then
|
||||
echo "Release for $TAG already exists; skipping."
|
||||
else
|
||||
gh release create "$TAG" --title "$TAG" --generate-notes
|
||||
fi
|
||||
@@ -0,0 +1,26 @@
|
||||
name: GitHub Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*.*.*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Create release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
name: ${{ github.ref_name }}
|
||||
generate_release_notes: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -30,16 +30,6 @@ npx skills add unclecatvn/agent-skills
|
||||
|
||||
That's it! Your AI assistant will now have access to all the skills in this repository.
|
||||
|
||||
### Alternative: Manual Installation
|
||||
|
||||
```bash
|
||||
# Install the CLI globally
|
||||
npm install -g @unclecat/agent-skills-cli
|
||||
|
||||
# Initialize a specific skill (e.g., Odoo 19 for Cursor)
|
||||
agent-skills init --ai cursor odoo --version 19.0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What's Inside?
|
||||
@@ -50,14 +40,16 @@ In-depth guides written specifically for AI consumption:
|
||||
|
||||
| Skill | Description |
|
||||
|-------|-------------|
|
||||
| **[Odoo 18.0](skills/odoo-18.0/)** | Complete Odoo 18 development guide (ORM, OWL, Web Client, Performance) |
|
||||
| **[Odoo 19.0](skills/odoo-19.0/)** | Complete Odoo 19 development guide with latest features |
|
||||
| **[Odoo 18.0](skills/odoo-18.0/)** | Odoo 18 development (ORM, views, security, OWL, reports, migrations, performance) |
|
||||
| **[Odoo 19.0](skills/odoo-19.0/)** | Odoo 19 development guide with current conventions |
|
||||
| **[DTG Base](skills/dtg-base/)** | DTGBase utilities (date/period, timezone, batch, barcode, Vietnamese text) |
|
||||
| **[Payment Integration](skills/payment-integration/)** | Integration guides for SePay, Polar, Stripe, Paddle, Creem.io |
|
||||
| **[Code Review](skills/code-review/)** | Standards and protocols for automated code review |
|
||||
| **[Brainstorming](skills/brainstorming/)** | Structured framework for feature ideation |
|
||||
| **[Writing Skills](skills/writing-skills/)** | Guide for creating and editing AI skills |
|
||||
| **[MCP Builder](skills/mcp-builder/)** | Guide for building Model Context Protocol servers |
|
||||
| **[Payment Integration](skills/payment-integration/)** | SePay, Polar, Stripe, Paddle, Creem.io and related patterns |
|
||||
| **[Code Review](skills/code-review/)** | Standards and workflows for automated code review |
|
||||
| **[Brainstorming](skills/brainstorming/)** | Structured framework for feature ideation and spec review |
|
||||
| **[Writing Skills](skills/writing-skills/)** | Creating and editing AI skills (structure, evals, quality) |
|
||||
| **[MCP Builder](skills/mcp-builder/)** | Building Model Context Protocol servers |
|
||||
| **[Slide (AI Vibe Slides)](skills/slide/)** | Self-contained HTML/React slide decks for fullscreen presentation |
|
||||
| **[Visual Explainer](skills/visual-explainer/)** | Self-contained HTML for diagrams, diff/plan review, tables, and visual explanations |
|
||||
|
||||
### Agents - Autonomous Reviewers
|
||||
|
||||
@@ -65,11 +57,8 @@ Specialized agents that act as senior technical leads:
|
||||
|
||||
| Agent | What it does |
|
||||
|-------|--------------|
|
||||
| **[Odoo Code Review](agents/odoo-code-review/SKILL.md)** | Automatically reviews Odoo code with scoring (1-10) and detailed feedback |
|
||||
| **[Odoo Code Tracer](agents/odoo-code-tracer/SKILL.md)** | Traces execution flow from entry point to end, identifying all function calls |
|
||||
| **[Odoo Module Generator](agents/odoo-module-generator/SKILL.md)** | Scaffolds complete Odoo 18 modules with proper structure |
|
||||
| **[Odoo Query Optimizer](agents/odoo-query-optimizer/SKILL.md)** | Diagnoses N+1 queries and provides optimization suggestions |
|
||||
| **[Odoo Migration Helper](agents/odoo-migration-helper/SKILL.md)** | Converts Odoo 16/17 code to Odoo 18 (tree→list, unlink→ondelete, etc.) |
|
||||
| **[Odoo Code Review](agents/odoo-code-review/SKILL.md)** | Reviews Odoo code with scoring (1–10) and structured feedback |
|
||||
| **[Odoo Code Tracer](agents/odoo-code-tracer/SKILL.md)** | Traces execution flow from an entry point through the call graph |
|
||||
| **[Planner](agents/planner.md)** | Breaks down complex features into actionable implementation steps |
|
||||
|
||||
### Rules - Coding Standards
|
||||
@@ -88,17 +77,19 @@ Enforced patterns for consistent, secure code:
|
||||
```
|
||||
agent-skills/
|
||||
├── skills/
|
||||
│ ├── odoo-18.0/ # Odoo 18 development guide
|
||||
│ ├── odoo-19.0/ # Odoo 19 development guide
|
||||
│ ├── dtg-base/ # DTGBase utilities (date/period, timezone, batch)
|
||||
│ ├── payment-integration/ # Payment provider integrations
|
||||
│ ├── code-review/ # Code review standards
|
||||
│ ├── brainstorming/ # Feature ideation framework
|
||||
│ ├── writing-skills/ # Guide for creating skills
|
||||
│ └── mcp-builder/ # MCP server development guide
|
||||
├── agents/ # Autonomous code reviewers and planners
|
||||
├── rules/ # Coding standards and security patterns
|
||||
└── lib/ # Shared resources and images
|
||||
│ ├── odoo-18.0/ # Odoo 18 guides
|
||||
│ ├── odoo-19.0/ # Odoo 19 guides
|
||||
│ ├── dtg-base/ # DTGBase utilities
|
||||
│ ├── payment-integration/ # Payment integrations
|
||||
│ ├── code-review/ # Code review standards
|
||||
│ ├── brainstorming/ # Ideation and spec review
|
||||
│ ├── writing-skills/ # Authoring AI skills
|
||||
│ ├── mcp-builder/ # MCP servers
|
||||
│ ├── slide/ # HTML/React slide decks
|
||||
│ └── visual-explainer/ # HTML diagrams and visual explanations
|
||||
├── agents/ # Odoo reviewers + planner
|
||||
├── rules/ # Coding style and security
|
||||
└── lib/ # Shared assets (e.g. images)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -107,7 +98,7 @@ agent-skills/
|
||||
|
||||
Agent Skills works with popular AI-powered IDEs:
|
||||
|
||||
- **Cursor** - Full integration via CLI
|
||||
- **Cursor** - Rules, remote rules, or `npx skills add`
|
||||
- **Claude Code** - Native skill support
|
||||
- **Windsurf** - Compatible
|
||||
- **Aider** - Compatible
|
||||
@@ -139,8 +130,8 @@ graph LR
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Documentation | 10,000+ lines |
|
||||
| Skill Packs | 8 (Odoo 18.0, 19.0, DTG Base, Payment, Code Review, Brainstorming, Writing, MCP) |
|
||||
| Agents | 6 (Code Review, Tracer, Module Generator, Query Optimizer, Migration Helper, Planner) |
|
||||
| Skill packs | 10 (Odoo 18.0, 19.0, DTG Base, Payment, Code Review, Brainstorming, Writing Skills, MCP Builder, Slide, Visual Explainer) |
|
||||
| Agents | 3 (Odoo Code Review, Odoo Code Tracer, Planner) |
|
||||
| License | MIT |
|
||||
|
||||
---
|
||||
@@ -154,7 +145,7 @@ We welcome contributions! Here's how you can help:
|
||||
- **Create agents** - Build specialized reviewers or planners
|
||||
- **Report issues** - Let us know what's missing or broken
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
||||
Open an issue or discussion on GitHub if you want to propose changes or new skills.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@unclecat/agent-skills-cli",
|
||||
"version": "0.1.0",
|
||||
"version": "1.0.6",
|
||||
"description": "CLI and docs for installing agent skills by version.",
|
||||
"bin": {
|
||||
"agent-skills": "bin/agent-skills.js"
|
||||
|
||||
@@ -1,26 +1,13 @@
|
||||
---
|
||||
name: odoo-18
|
||||
description: >-
|
||||
Odoo 18 development knowledge base with 18 specialized guides covering
|
||||
Actions (ir.actions.*, cron jobs, server actions), Controllers (HTTP
|
||||
routing, endpoints, auth types), Data files (XML/CSV records, shortcuts,
|
||||
noupdate), API Decorators (@api.depends, @api.constrains, @api.ondelete,
|
||||
@api.onchange, @api.model), Module development (manifest, wizards,
|
||||
reports), Field types (Char, Text, Monetary, relational fields),
|
||||
Manifest configuration (__manifest__.py, dependencies, asset bundles),
|
||||
Mixins (mail.thread, mail.activity.mixin, mail.alias.mixin, utm.mixin),
|
||||
ORM Model methods (search, CRUD, domain filters, recordsets, prefetch),
|
||||
Migration scripts (pre/post/end hooks, data migration), OWL frontend
|
||||
components (hooks, services, lifecycle), Performance optimization (N+1
|
||||
prevention, batch ops, read_group), QWeb Reports (PDF/HTML, paper formats,
|
||||
barcodes), Security/ACL (record rules, field permissions, multi-company),
|
||||
Testing (TransactionCase, HttpCase, mocking, query count assertions),
|
||||
Transactions (savepoints, UniqueViolation, serialization failures),
|
||||
Translations (i18n, PO files, translatable fields), XML Views
|
||||
(list/form/search, xpath inheritance, QWeb templates). Use when writing,
|
||||
reviewing, or debugging any Odoo 18 Python or XML code, creating or
|
||||
modifying modules, fixing performance issues, or looking up Odoo 18 API
|
||||
patterns and best practices.
|
||||
description: >
|
||||
Odoo 18 development reference for Python models and ORM (search, domain, read_group, compute fields),
|
||||
XML/CSV data and views, OWL/JS client code, QWeb reports, security (ACL, record rules, groups),
|
||||
cron and server actions, migrations and module upgrades, tests, i18n, and performance.
|
||||
Use this skill whenever work involves Odoo 18 or custom addons—even if the user only pastes a traceback,
|
||||
mentions addons/ or __manifest__.py, describes form/list/kanban/XML errors, HTTP controllers, or
|
||||
business rules on models—including building features, fixing bugs, refactoring, or reviewing addon code.
|
||||
globs: "**/*.{py,xml,csv,js,ts}"
|
||||
---
|
||||
|
||||
# Odoo 18 Skill - Master Index
|
||||
|
||||
@@ -34,6 +34,7 @@ Complete reference for Odoo 18 data files: XML structure, records, fields, short
|
||||
6. [Shortcuts](#shortcuts)
|
||||
7. [CSV Data Files](#csv-data-files)
|
||||
8. [noupdate Attribute](#noupdate-attribute)
|
||||
9. [Data Processing Patterns (Partner Merge)](#data-processing-patterns-partner-merge)
|
||||
|
||||
---
|
||||
|
||||
@@ -650,6 +651,71 @@ Data in `<data noupdate="1">` is only loaded at installation:
|
||||
|
||||
---
|
||||
|
||||
## Data Processing Patterns (Partner Merge)
|
||||
|
||||
Patterns below are extracted from `odoo/addons/base/wizard/base_partner_merge.py` and are useful when building safe data-migration or merge logic in custom modules.
|
||||
|
||||
### 1) Normalize Before Grouping
|
||||
|
||||
When finding duplicates, normalize values first so grouping is stable:
|
||||
|
||||
- `lower(name)` / `lower(email)` for case-insensitive comparisons
|
||||
- `replace(vat, ' ', '')` to ignore formatting spaces
|
||||
|
||||
This avoids false negatives when data is logically equal but formatted differently.
|
||||
|
||||
### 2) SQL for Candidate Detection, ORM for Access-Safe Filtering
|
||||
|
||||
`base_partner_merge` uses SQL (`min(id), array_agg(id)`) to detect duplicate groups quickly, then re-reads partners with ORM:
|
||||
|
||||
```python
|
||||
self._cr.execute(query)
|
||||
for min_id, aggr_ids in self._cr.fetchall():
|
||||
partners = self.env['res.partner'].search([('id', 'in', aggr_ids)])
|
||||
```
|
||||
|
||||
This pattern combines performance (SQL) with Odoo security/record-rule behavior (ORM).
|
||||
|
||||
### 3) Generic FK Rewrite with Savepoint Fallback
|
||||
|
||||
For merge operations across many tables:
|
||||
|
||||
1. Discover FK relations dynamically
|
||||
2. Try bulk `UPDATE ... SET fk = dst_id WHERE fk IN src_ids`
|
||||
3. On unique constraint collision, fallback to deleting conflicting rows
|
||||
4. Keep each table operation isolated in a savepoint
|
||||
|
||||
This prevents one collision from rolling back the whole merge process.
|
||||
|
||||
### 4) Reference Field Rewrite (`model,res_id`)
|
||||
|
||||
For `reference` fields and models like `ir.attachment`, `mail.followers`, `mail.activity`, `mail.message`, update links from source records to destination records in batch. Always use guarded writes and savepoints.
|
||||
|
||||
### 5) Company-Dependent JSONB Data Migration
|
||||
|
||||
For company-dependent many2one values stored as JSONB:
|
||||
|
||||
- Update per-company values in SQL (`jsonb_each`, `jsonb_object_agg`)
|
||||
- Merge source JSONB values into destination in deterministic order
|
||||
- Flush environment after SQL updates
|
||||
|
||||
This is safer than partial ORM-only writes when data is stored in JSONB structures.
|
||||
|
||||
### 6) Deterministic Destination Selection
|
||||
|
||||
The wizard selects destination partner by ordered criteria (`active`, `create_date`) before merge. In custom dedup flows, define and document an explicit winner strategy to keep behavior predictable.
|
||||
|
||||
### 7) Defensive Checks Before Merge
|
||||
|
||||
Before data merge, validate constraints to avoid corrupt states:
|
||||
|
||||
- Do not merge parent with child (`child_of` checks)
|
||||
- Block conflicting user links
|
||||
- Enforce consistency checks (for example, same email unless admin)
|
||||
- Limit merge group size for operational safety
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### record Tag
|
||||
|
||||
@@ -0,0 +1,453 @@
|
||||
---
|
||||
name: ai-vibe-slides
|
||||
description: "Create beautiful, professional HTML or React slide decks ready for fullscreen presentation. Use this skill when the user wants to: create a PPT/slide/presentation from an idea or outline; build a visually stunning slide deck from existing content; generate an HTML presentation that can be projected fullscreen; convert a document into a presentation. Trigger when you hear: 'create slides', 'make a PPT', 'presentation', 'slide deck', 'pitch deck', 'vibe ppt', 'make a talk', or any request to create a presentation. This skill produces a single self-contained HTML/React artifact — no backend, no installation, no dependencies."
|
||||
---
|
||||
|
||||
# AI Vibe Slides — Beautiful HTML Slide Decks, Ready to Present
|
||||
|
||||
## Goal
|
||||
|
||||
Produce **a single HTML or React artifact file** containing a complete slide deck that can:
|
||||
|
||||
- Present fullscreen directly in the browser
|
||||
- Navigate via arrow keys, spacebar, or click
|
||||
- Look professional, polished, and stylistically consistent
|
||||
- Print or export to PDF when needed
|
||||
|
||||
Inspired by [banana-slides](https://github.com/Anionex/banana-slides): a 3-step pipeline of **Idea → Outline → Finished Slides**, but the output is a self-contained HTML file instead of a fullstack application.
|
||||
|
||||
---
|
||||
|
||||
## Slide Creation Pipeline
|
||||
|
||||
### Step 1: Understand the Request → Build an Outline
|
||||
|
||||
When the user provides a request, first **build an outline mentally** (no need to display it unless the user asks):
|
||||
|
||||
1. Identify the **main topic** and **target audience** (students, business, tech talk...)
|
||||
2. Break it into **logical sections**:
|
||||
- Slide 1: Cover (title + subtitle + author)
|
||||
- Slides 2-3: Introduction / context
|
||||
- Middle slides: Core content (one key idea per slide)
|
||||
- Final slide: Conclusion / Call to action / Thank you
|
||||
3. Each slide should have: a title, 2-5 bullet points or visual content, and a layout type
|
||||
|
||||
If the user only gives a short sentence (e.g., "create slides about AI in healthcare"), automatically expand it into 8-12 slides with a logical structure.
|
||||
|
||||
### Step 2: Choose a Design Direction
|
||||
|
||||
Based on context, commit to **one clear design direction**:
|
||||
|
||||
| Context | Suggested Style |
|
||||
| ---------------------- | ----------------------------------------------------- |
|
||||
| Startup pitch deck | Bold, dark theme, gradient accents, strong sans-serif |
|
||||
| Academic / education | Clean, light, diagram-heavy, readable fonts |
|
||||
| Tech talk / conference | Modern dark, code-style typography, neon accents |
|
||||
| Corporate / report | Minimal, professional, navy/white, serif headings |
|
||||
| Creative / marketing | Colorful, asymmetric layout, bold typography |
|
||||
| Kids / early education | Pastel, rounded corners, playful icons, large text |
|
||||
|
||||
General rules:
|
||||
|
||||
- **Pick 2-3 primary colors** and use them consistently across the entire deck
|
||||
- **1 heading font + 1 body font** (use Google Fonts)
|
||||
- **Minimal text, generous whitespace** — max 5-6 lines per slide
|
||||
- **Clear visual hierarchy**: large title → medium content → small notes
|
||||
|
||||
### Step 3: Generate the HTML/React Slide Deck
|
||||
|
||||
Create **a single file** (`.html` or `.jsx`) containing everything:
|
||||
|
||||
---
|
||||
|
||||
## HTML Slide Deck Structure
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>{Presentation Title}</title>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family={Font1}&family={Font2}&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<style>
|
||||
/* === RESET + BASE === */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* === SLIDE CONTAINER === */
|
||||
.slide-deck {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.slide {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 60px 80px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.slide.active {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* === TYPOGRAPHY === */
|
||||
h1 {
|
||||
font-family: "{Font1}", sans-serif;
|
||||
font-size: 3.2rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
h2 {
|
||||
font-family: "{Font1}", sans-serif;
|
||||
font-size: 2.4rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
p,
|
||||
li {
|
||||
font-family: "{Font2}", sans-serif;
|
||||
font-size: 1.4rem;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
/* === THEME COLORS === */
|
||||
:root {
|
||||
--bg-primary: #0f172a;
|
||||
--bg-slide: #1e293b;
|
||||
--text-primary: #f8fafc;
|
||||
--text-secondary: #94a3b8;
|
||||
--accent: #3b82f6;
|
||||
--accent-2: #8b5cf6;
|
||||
}
|
||||
|
||||
/* === NAVIGATION UI === */
|
||||
.nav-hint {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 30px;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-secondary);
|
||||
opacity: 0.5;
|
||||
}
|
||||
.slide-counter {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 30px;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
/* === TRANSITIONS === */
|
||||
.slide {
|
||||
animation: fadeIn 0.4s ease;
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* === LAYOUT VARIANTS === */
|
||||
.slide.cover {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
.slide.two-column {
|
||||
flex-direction: row;
|
||||
gap: 60px;
|
||||
align-items: center;
|
||||
}
|
||||
.slide.two-column .col {
|
||||
flex: 1;
|
||||
}
|
||||
.slide.centered {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* === VISUAL ELEMENTS === */
|
||||
.card {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
margin: 8px 0;
|
||||
}
|
||||
.badge {
|
||||
display: inline-block;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
padding: 4px 14px;
|
||||
border-radius: 20px;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.divider {
|
||||
width: 60px;
|
||||
height: 4px;
|
||||
background: var(--accent);
|
||||
border-radius: 2px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
.icon-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
/* === PRINT / PDF EXPORT === */
|
||||
@media print {
|
||||
.slide {
|
||||
page-break-after: always;
|
||||
display: flex !important;
|
||||
position: relative;
|
||||
}
|
||||
.nav-hint,
|
||||
.slide-counter {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="slide-deck" id="deck">
|
||||
<!-- SLIDE 1: COVER -->
|
||||
<div
|
||||
class="slide cover active"
|
||||
style="background: linear-gradient(135deg, var(--bg-primary), #1a1a2e);"
|
||||
>
|
||||
<div class="badge">Topic</div>
|
||||
<h1 style="font-size: 3.8rem; margin-top: 20px;">Main Title</h1>
|
||||
<p
|
||||
style="color: var(--text-secondary); font-size: 1.3rem; margin-top: 12px;"
|
||||
>
|
||||
Short subtitle description
|
||||
</p>
|
||||
<div class="divider" style="margin: 20px auto;"></div>
|
||||
<p style="color: var(--text-secondary); font-size: 1rem;">
|
||||
Author — Date
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- SLIDE 2+: CONTENT -->
|
||||
<div class="slide">
|
||||
<h2>Slide Title</h2>
|
||||
<div class="divider"></div>
|
||||
<ul>
|
||||
<li>Key point 1</li>
|
||||
<li>Key point 2</li>
|
||||
<li>Key point 3</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- ... more slides ... -->
|
||||
</div>
|
||||
|
||||
<div class="slide-counter">
|
||||
<span id="current">1</span> / <span id="total"></span>
|
||||
</div>
|
||||
<div class="nav-hint">← → or click to navigate</div>
|
||||
|
||||
<script>
|
||||
const slides = document.querySelectorAll(".slide");
|
||||
let currentSlide = 0;
|
||||
document.getElementById("total").textContent = slides.length;
|
||||
|
||||
function showSlide(n) {
|
||||
slides[currentSlide].classList.remove("active");
|
||||
currentSlide = (n + slides.length) % slides.length;
|
||||
slides[currentSlide].classList.add("active");
|
||||
document.getElementById("current").textContent = currentSlide + 1;
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", (e) => {
|
||||
if (e.key === "ArrowRight" || e.key === " ")
|
||||
showSlide(currentSlide + 1);
|
||||
if (e.key === "ArrowLeft") showSlide(currentSlide - 1);
|
||||
if (e.key === "f") document.documentElement.requestFullscreen?.();
|
||||
if (e.key === "Escape") document.exitFullscreen?.();
|
||||
});
|
||||
|
||||
document.querySelector(".slide-deck").addEventListener("click", (e) => {
|
||||
const x = e.clientX / window.innerWidth;
|
||||
x > 0.5 ? showSlide(currentSlide + 1) : showSlide(currentSlide - 1);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Slide Layout Types
|
||||
|
||||
Each slide should use the layout that best fits its content:
|
||||
|
||||
### 1. Cover Slide
|
||||
|
||||
- Centered, extra-large font, gradient background
|
||||
- Topic badge + main title + subtitle + author
|
||||
|
||||
### 2. Section Divider
|
||||
|
||||
- Only section title + number, accent color background
|
||||
- Used to separate major sections of the presentation
|
||||
|
||||
### 3. Content + Bullets
|
||||
|
||||
- Left-aligned title + list of key points
|
||||
- Use icons/emoji at the start of each bullet instead of plain dots
|
||||
|
||||
### 4. Two-Column
|
||||
|
||||
- `.two-column` layout: text on left, visuals/list/cards on right
|
||||
- Great for comparisons, before-after, text+illustration
|
||||
|
||||
### 5. Cards Grid
|
||||
|
||||
- 2-3 column grid, each card containing icon + title + short description
|
||||
- Great for features, benefits, team members
|
||||
|
||||
### 6. Big Number / Statistic
|
||||
|
||||
- Huge number in the center (font-size: 5rem+) + small label below
|
||||
- Great for data points, KPIs, impact numbers
|
||||
|
||||
### 7. Quote / Highlight
|
||||
|
||||
- Large text, centered, with decorative quotation marks
|
||||
- Different background (light accent color)
|
||||
|
||||
### 8. Timeline / Steps
|
||||
|
||||
- Horizontal or vertical flexbox, dots connecting each step
|
||||
- Great for processes, roadmaps, history
|
||||
|
||||
### 9. Thank You / CTA
|
||||
|
||||
- Centered, simple, contact info or call to action
|
||||
|
||||
---
|
||||
|
||||
## MANDATORY Design Rules
|
||||
|
||||
1. **16:9 aspect ratio**: Always use `width: 100vw; height: 100vh` — each slide fills the entire screen
|
||||
2. **Minimal text**: Maximum 6 lines per slide. If content is long → split into multiple slides
|
||||
3. **Large font sizes**: Heading ≥ 2.4rem, body ≥ 1.3rem — must be readable on a projector
|
||||
4. **High contrast**: Text must be clearly legible against its background. Verify visually
|
||||
5. **Consistency**: Same fonts, same color palette, same spacing throughout the entire deck
|
||||
6. **No placeholder images**: Never use `<img src="placeholder">`. Replace with CSS shapes, gradients, icons (emoji or Lucide for React), or inline SVGs
|
||||
7. **Subtle animation**: Only fadeIn on slide transition. No complex animations that distract
|
||||
8. **Responsive fullscreen**: Must work well at all screen sizes
|
||||
9. **Print-ready**: Include `@media print` rules so each slide becomes one printed page
|
||||
|
||||
---
|
||||
|
||||
## When Using React (.jsx) Instead of HTML
|
||||
|
||||
If creating a React artifact, use this pattern:
|
||||
|
||||
```jsx
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
|
||||
const slides = [
|
||||
{ type: "cover", title: "...", subtitle: "..." },
|
||||
{ type: "content", title: "...", points: ["...", "..."] },
|
||||
{ type: "twoColumn", title: "...", left: "...", right: "..." },
|
||||
// ...
|
||||
];
|
||||
|
||||
export default function SlideDeck() {
|
||||
const [current, setCurrent] = useState(0);
|
||||
|
||||
const next = useCallback(
|
||||
() => setCurrent((c) => (c + 1) % slides.length),
|
||||
[],
|
||||
);
|
||||
const prev = useCallback(
|
||||
() => setCurrent((c) => (c - 1 + slides.length) % slides.length),
|
||||
[],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const handleKey = (e) => {
|
||||
if (e.key === "ArrowRight" || e.key === " ") next();
|
||||
if (e.key === "ArrowLeft") prev();
|
||||
if (e.key === "f") document.documentElement.requestFullscreen?.();
|
||||
};
|
||||
window.addEventListener("keydown", handleKey);
|
||||
return () => window.removeEventListener("keydown", handleKey);
|
||||
}, [next, prev]);
|
||||
|
||||
const renderSlide = (slide) => {
|
||||
switch (slide.type) {
|
||||
case "cover":
|
||||
return /* cover layout */;
|
||||
case "content":
|
||||
return /* content layout */;
|
||||
case "twoColumn":
|
||||
return /* two-column layout */;
|
||||
// ...
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="w-screen h-screen overflow-hidden relative"
|
||||
onClick={(e) => (e.clientX > window.innerWidth / 2 ? next() : prev())}
|
||||
style={{ fontFamily: "'Outfit', sans-serif" }}
|
||||
>
|
||||
{renderSlide(slides[current])}
|
||||
<div className="fixed bottom-5 left-8 text-sm opacity-40">
|
||||
{current + 1} / {slides.length}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Advantages of React: Tailwind CSS utilities, Lucide icons, more complex logic, recharts for charts.
|
||||
|
||||
---
|
||||
|
||||
## Pre-Delivery Checklist
|
||||
|
||||
- [ ] Correct number of slides (cover + content + closing)
|
||||
- [ ] Arrow keys ← → work, click navigates
|
||||
- [ ] Counter displays correct "X / N"
|
||||
- [ ] Press F for fullscreen
|
||||
- [ ] All text is readable with sufficient contrast
|
||||
- [ ] No broken images or placeholders
|
||||
- [ ] Google Fonts load correctly (or good fallback)
|
||||
- [ ] Print/PDF exports properly (`@media print`)
|
||||
- [ ] Consistent style throughout the entire deck
|
||||
- [ ] Each slide has exactly one key idea, not overloaded with text
|
||||
|
||||
---
|
||||
|
||||
## Natural Language Editing
|
||||
|
||||
After initial creation, the user can request modifications:
|
||||
|
||||
- "Switch to a light theme" → update CSS variables
|
||||
- "Add 2 slides about case studies" → insert slides into the array
|
||||
- "Slide 3 has too much text, split it" → refactor content across slides
|
||||
- "Change the font to Playfair Display" → update Google Fonts link + CSS
|
||||
- "Add a chart to slide 5" → use CSS chart or recharts (React)
|
||||
|
||||
On each edit, keep unchanged slides intact and only update what the user requested.
|
||||
Reference in New Issue
Block a user