Communitygithub.com

kyjongSNSoft/landing-page-skill

Utilisez lorsque l'utilisateur fournit un lien/fichier Figma et souhaite générer une page d'atterrissage promotionnelle/marketing (SNSoft 活动落地页) — produit du HTML + CSS + JS statique prêt à déployer, avec mise en page rem, images exportées découpées, et le runtime fixe d'analytique/postMessage. Déclencheurs - /figma-landing-page, 'figma 落地页', '把这个 Figma 做成落地页', lien Figma + demande de page d'atterrissage.

Qu'est-ce que landing-page-skill ?

Cette compétence transforme une conception Figma en une page d'atterrissage promotionnelle statique et déployable. Elle génère un ensemble de fichiers comprenant `index.html`, `css/main.css`, plusieurs fichiers JavaScript (`tool.js`, `pm_main.js`, `main.js`), et des images WebP. La compétence respecte un contrat fixe avec trois espaces réservés (`__PAGE_TITLE__`, `__FUNCTION_NAME__`, `__PC_BASE__`), des éléments CTA marqués avec la classe `.join-btn`, et un point de rupture standard à 576px. Elle utilise un système de rem basé sur la largeur de la maquette (375px pour mobile, 1920px pour desktop). Le processus est divisé en sept étapes : analyse de l'entrée et vérification de l'environnement (connexion Figma MCP, disponibilité de `cwebp` et de Playwright), inventaire de la conception (identification des sections, textes, images et composants interactifs), une porte de confirmation unique pour valider les paramètres et les décisions, l'exportation des images avec quatre niveaux de repli (MCP, REST Render, REST Images, export manuel par l'utilisateur), la génération du code à partir de modèles, l'itération de comparaison par captures d'écran (jusqu'à 3 cycles), et enfin la livraison avec un rapport détaillé. La compétence est conçue pour fonctionner avec les APIs Figma (MCP et REST) et utilise Playwright pour les captures d'écran et la vérification.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/kyjongSNSoft/landing-page-skill/tree/main/skill

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Aperçu

Depuis le README du skill

landing-page-skill preview

Documentation

Figma → Landing Page

Génère une page d'atterrissage promotionnelle statique et déployable à partir d'une maquette Figma : index.html + css/main.css + js/{tool,pm_main,main}.js + images/*.webp.

Commande : /figma-landing-page <lien Figma> [nom de la campagne] [répertoire de sortie]

Contrat fixe (à ne pas déroger en aucun cas) :

  • Espaces réservés du modèle : exactement 3 : __PAGE_TITLE__, __FUNCTION_NAME__ (tous deux dans main.js, le titre apparaît également dans index.html), __PC_BASE__ (dans tool.js ; 375 = uniquement image mobile ; 1920 = images mobile et PC).
  • Les éléments CTA doivent obligatoirement avoir la classe supplémentaire .join-btn (contrat de sélecteur pour le JS fixe), en plus des classes BEM.
  • Point de rupture 576px unifié à trois endroits : branche JS rem, CSS @media (min-width: 576px), détermination de la plateforme.
  • Normalisation px : mobile px × 375 ÷ largeur image mobile ÷ 100 = rem ; PC px × 1920 ÷ largeur image PC ÷ 100 = rem.
  • Les trois fichiers JS du modèle (tool.js pour l'adaptation rem, pm_main.js pour le pont postMessage, main.js pour la couche métier de la campagne, chargés dans cet ordre) ne doivent pas être modifiés d'un seul mot ; les interactions de la page ne doivent être insérées que sous le commentaire // === Page-specific interactions === dans main.js (à l'intérieur de l'IIFE, vous pouvez utiliser directement $p/pm/track/Date.prototype.format).
  • Règles détaillées (limites de découpe d'images, noms de classes, table d'inférence des interactions) dans references/patterns.md, critères de livraison dans references/checklist.md — à lire avant la génération.

Étape 1 — Analyse de l'entrée et vérification de l'environnement

  1. Extraire la clé de fichier et l'ID de nœud du lien. Convertir les traits d'union en deux-points dans l'ID de nœud (123-456 → 123:456) avant d'appeler toute API Figma ; si l'appel API renvoie une erreur 404 ou un résultat vide, vérifier d'abord cette étape.
  2. Trois vérifications de l'environnement (si elles échouent, les corriger d'abord avant de continuer) :
    • Figma MCP est connecté (sinon, guider l'utilisateur pour l'authentification, celle-ci ne compte pas comme l'interruption unique de la porte de confirmation). Appeler d'abord whoami (exempté du quota) pour confirmer le siège : les sièges Viewer/Collaborator ou Starter n'ont que 6 appels MCP par mois — en cas de budget serré, ignorer MCP et passer directement à la route REST des étapes 2/4 (PAT stocké dans ~/.figma_token, demander à l'utilisateur d'en générer un dans Figma Settings → Security, et de l'écrire dans un fichier sur son terminal pour éviter d'être conservé dans l'historique de discussion).
    • which cwebp — si absent, informer l'utilisateur avec brew install webp ; si l'utilisateur refuse l'installation, toute la page utilise des images PNG en repli, et le mentionner dans le rapport de livraison.
    • node -e "require('playwright-core')" — si absent, installer dans le répertoire scratchpad avec npm i playwright-core ; réutiliser le Chrome du système (channel: 'chrome'), ne pas télécharger le binaire du navigateur.
  3. Répertoire de sortie par défaut : ./output/<slug-nom-campagne>/ (tous les artefacts de la compétence sont placés sous output/ ; si le nom de la campagne n'est pas fourni, l'inférer à partir du nom de la page/image Figma, et le vérifier à la porte de confirmation). Si le répertoire existe et n'est pas vide, ne pas interrompre maintenant — la confirmation d'écrasement fait partie du contenu de la porte de confirmation.

Étape 2 — Inventaire de la conception

  • Utiliser un outil de métadonnées clairsemées (type get_metadata) pour lire l'arborescence des nœuds ; ne pas récupérer l'intégralité du contexte de conception de l'image racine en une seule fois.
  • Lorsque MCP est indisponible/le budget est épuisé : REST GET /v1/files/<key>/nodes?ids=<node> (sans profondeur = JSON complet de l'arborescence, comprenant le texte intégral, les polices, les valeurs originales des dégradés de remplissage, le bbox précis — plus d'informations que get_metadata). Stocker localement pour une analyse répétée, un seul appel suffit pour l'ensemble du processus ; les valeurs CSS (couleurs, dégradés, textes) sont directement extraites de ce JSON, sans utiliser get_code.
  • Identification des images : largeur ≤ 480 → image mobile ; ≥ 1200 → image PC ; les images non déterminables sont listées dans la porte de confirmation. Une seule image mobile → __PC_BASE__ = 375 ; images mobile et PC → __PC_BASE__ = 1920.
  • Produire une liste d'actifs : liste des sections (hero, bannière, étapes, conditions…); chaque nœud est annoté comme image découpée / texte véritable / composant interactif (règles de détermination dans references/patterns.md).
  • Marquer tous les CTA (boutons "Rejoindre maintenant" / "S'inscrire" / "Sign Up") — ils doivent recevoir la classe .join-btn.

Étape 3 — Porte de confirmation (unique interruption avant la génération dans le flux normal)

Lister tout le contenu suivant dans un seul message pour obtenir la confirmation de l'utilisateur en une fois ; ne plus interrompre jusqu'à la livraison :

  • Nom de la campagne, valeur de __PAGE_TITLE__, valeur de __FUNCTION_NAME__ (par exemple WinsdayBillionDropLandingPage)
  • Répertoire de sortie (confirmer l'écrasement si le répertoire n'est pas vide)
  • Liste des images découpées (nœud → images/<nom>.webp)
  • Liste des nœuds CTA
  • Liste des interactions : chaque élément avec sa base d'inférence et les paramètres requis (compte à rebours → heure limite/comportement à l'expiration ; carrousel → lecture automatique/intervalle ; popup → moment de déclenchement ; voir references/patterns.md). Si la maquette ne permet pas de déduire les paramètres, demander à l'utilisateur de les remplir ici ; les nœuds non classifiables sont marqués comme "statiques".
  • Éléments douteux concernant l'identification des images

Étape 4 — Exportation des images découpées (chaîne de repli à quatre niveaux, dégradation en fonction de la disponibilité)

  1. MCP download_assets (lorsque le budget du siège est suffisant) : maximum 20 nœuds par lot, échelle 2x, format png ; télécharger les URL temporaires avec curl.
  2. Rendu REST GET /v1/images/<key>?ids=…&format=png&scale=2 : ids en lots séparés par des virgules mais maximum 4 grands nœuds par lot (au-delà, signalement "Render timeout") ; 429 = budget de rendu du siège épuisé (les sièges Viewer déclenchent environ 12 images, fenêtre horaire), passer au niveau suivant, ne pas attendre inutilement.
  3. Point de terminaison REST des images originales GET /v1/files/<key>/images : renvoie la correspondance imageRef → URL de l'image originale pour tout le fichier, utilise le budget du fichier, presque jamais limité. Idéal pour tous les nœuds de remplissage d'image (photos/autocollants/icônes — le fills[].imageRef dans le JSON du nœud correspond à l'URL, obtenant une résolution originale souvent bien supérieure à 2x, à recadrer selon le mode d'échelle du remplissage/alpha, puis à redimensionner). Ne convient pas aux nœuds composites vectoriels (panneaux/bandeaux).
  4. Exportation manuelle par l'utilisateur (zéro quota) : demander à l'utilisateur de sélectionner le nœud dans Figma et d'exporter. Privilégier le format SVG — les parties vectorielles sont infiniment nettes, les bitmaps sont intégrés en base64 à leur résolution originale (on peut extraire l'image <image> par regex, ce qui est la meilleure source pour les éléments transparents). Pipeline de rastérisation SVG → bitmap 2x : copier le SVG dans un répertoire temporaire (nom de fichier kebab sécurisé, les noms originaux contiennent souvent &/espaces), écrire une enveloppe HTML <img src="./x.svg"> dans le même répertoire (ouvrir directement un SVG avec file:// ou une référence file:// cross-directory sera refusée par Chrome), prendre une capture d'écran avec playwright en deviceScaleFactor:2 + omitBackground:true pour obtenir un PNG transparent.
  • Général : convertir en webp avec cwebp -q 80 ; nommer en kebab-case sémantique, sans hash ; pour les nœuds purement dégradés/couleur unie, écrire directement le CSS à partir du JSON, sans générer d'image.
  • Attention : le viewBox d'un SVG exporté par Figma peut contenir des ombres portées/débordement (plus grand que le cadre du nœud) ; lors du positionnement du conteneur basé sur le cadre du nœud, laisser l'image déborder proportionnellement, ne pas l'écraser.
  • Échec de l'exportation d'une image unique : réessayer 2 fois → passer au niveau inférieur de la chaîne ; sauter uniquement en cas d'échec de toute la chaîne, et l'enregistrer dans le rapport de livraison.

Étape 5 — Génération du code

  • Démarrer à partir de assets/template/ : le contenu de base.css sert de squelette initial pour css/main.css (le seul fichier CSS produit, pas de base.css séparé).
  • index.html : remplacer <title> ; changer le lien de police pour la police de la maquette (si Google Fonts ne trouve pas de correspondance exacte, choisir la plus proche et l'enregistrer dans le rapport) ; générer une structure sémantique par section dans #app, avec des classes BEM (.hero__bg, .banner__headline), et les éléments CTA avec la classe supplémentaire join-btn.
  • css/main.css : valeurs extraites des tailles/couleurs/dégradés précis de Figma (la sortie HTML+CSS simple de get_code peut aider à obtenir les valeurs), normaliser d'abord les px en rem ; arrière-plan avec background-image, images de contenu avec <img>. Pour les pages à double image : règles mobiles d'abord, couverture PC dans @media (min-width: 576px).
  • js/ : copier les trois fichiers du modèle (tool.js / pm_main.js / main.js), remplacer les 3 espaces réservés (__PC_BASE__ dans tool.js, les deux autres dans main.js) ; insérer le code d'interaction confirmé sous le marqueur dans main.js.
  • Les éléments dont le débordement dépasse le bord de l'image (bbox dépasse la largeur de l'image) doivent avoir un conteneur avec overflow: hidden pour reproduire le recadrage de l'image, sinon la page déborde horizontalement.
  • Auto-contrôle : node --check js/*.js doit réussir pour les trois fichiers.

Étape 6 — Itération de comparaison par captures d'écran (par sections, maximum 3 cycles)

  • Démarrer un serveur local dans le répertoire de sortie : python3 -m http.server <port>.
  • Écrire le script de capture suivant dans le scratchpad et l'utiliser pour capturer par sections (coordonnées de découpage obtenues depuis le DOM : page.evaluate pour chaque élément de section avec getBoundingClientRect) :
// shot.mjs <url> <out.png> <width> <dsf> [clipY clipH]
import { chromium } from 'playwright-core';
const [url, out, width, dsf, clipY, clipH] = process.argv.slice(2);
const browser = await chromium.launch({ channel: 'chrome' });
const page = await browser.newPage({
  viewport: { width: +width, height: 800 },
  deviceScaleFactor: +dsf,
});
await page.goto(url, { waitUntil: 'networkidle' });
await page.screenshot(clipY === undefined
  ? { path: out, fullPage: true }
  : { path: out, clip: { x: 0, y: +clipY, width: +width, height: +clipH } });
await browser.close();
  • Comparaison mobile : local width 375, dsf 2 ; côté Figma, utiliser download_assets pour exporter par section en 2x png comme image de comparaison (les images de comparaison sont mises dans le scratchpad, pas dans images/).
  • Comparer côte à côte section par section, corriger chaque différence ; maximum 3 cycles, si des différences persistent, les enregistrer dans le rapport de livraison.
  • Une fois la convergence atteinte, faire une rapide régression sur l'ensemble de la page à width 414 (dsf 2) pour confirmer l'absence de décalage/débordement (le checklist exige les deux tailles 375/414).
  • Les captures d'écran de l'image entière ne sont utilisées que pour l'apparence du rapport de livraison, en aucun cas comme base de décision de différence (une longue page entière serait sous-échantillonnée, rendant les tailles de police/différences de couleur invisibles).
  • Pour les pages à double image : répéter la comparaison par sections ci-dessus avec width 1920, dsf 1 pour la mise en page PC (sur l'image exportée en 1x pour l'image PC) ; faire une rapide régression sur l'ensemble de la page à width 1280 (le checklist pour double image exige 1280/1920).
  • Vérifier au passage : aucune erreur dans la console du navigateur (page.on('console') ou les outils de développement).

Étape 7 — Livraison

Le rapport de livraison contient :

  1. L'arborescence du répertoire de sortie
  2. Les résultats du references/checklist.md, point par point
  3. Les différences connues restantes (non résolues en 3 cycles)
  4. Les chemins des captures d'écran de comparaison par sections
  5. Les replis utilisés (png au lieu de webp, polices approximatives, images découpées ignorées)

Aide-mémoire pour la gestion des erreurs

ScénarioTraitement
Figma MCP non connecté / authentification invalideGuider l'utilisateur pour l'authentification, puis reprendre à l'étape interrompue (ne compte pas comme interruption de la porte de confirmation)
node-id appel API 404 / videVérifier la conversion trait d'union → deux-points
Échec d'exportation d'image / limitation 429Réessayer 2 fois → passer au niveau inférieur de la chaîne (voir Étape 4) → si toujours en échec, sauter + enregistrer dans le rapport
cwebp manquant et utilisateur refuse l'installationRepli vers les artefacts images/*.png + enregistrer dans le rapport
Structure d'image non identifiableInclure dans la porte de confirmation et demander à l'utilisateur (ID de nœud spécifique requis)
Répertoire de sortie non videConfirmer l'écrasement lors de la porte de confirmation

Skills associés