composing-grid-canvases

Par posthog · skills

Composez des canevas en grille PostHog — des grilles de widgets (y compris le canevas d'accueil de l'utilisateur) construites à partir de canevas de composants réutilisables. À utiliser lorsqu'une tâche demande d'ajouter, remplir, déplacer, redimensionner ou supprimer un widget sur une grille ou un canevas d'accueil, de composer un canevas complet de widgets à partir d'une seule demande, de construire un widget/composant réutilisable, ou lorsqu'un identifiant de placement ou un identifiant de canevas en grille est la cible. Couvre la chaîne component store search → configure → fork → build, le contrat de placement de composant (size, configSchema), le cycle de vie du placement (pending/generating/live/failed), la boucle de correction de mise en page protégée, et la lecture des fils de commentaires du canevas.

npx skills add https://github.com/posthog/skills --skill composing-grid-canvases

Composer des grid canvases

Un grid canvas est une composition, non une app : une grille de placements, chacun rendant un component canvas (un widget réutilisable avec sa propre source, build et contrat de placement). Le home canvas de l'utilisateur est un grid canvas ordinaire dans son canal personnel. La layout est une donnée — publier ou patcher une layout est immédiat et en direct, sans build.

Trois types de canvas partagent un même lifecycle :

  • freeform — une app standalone (le skill building-canvases les possède).
  • component — un widget réutilisable. Même pipeline source/build qu'un freeform, plus un contrat de placement. La visibilité suit son canal : canal personnel = privé, canal d'équipe = partagé.
  • grid — une layout de placements référençant des components. Aucune source fichier ; layout uniquement.

L'échelle de résolution : configurer, forker, builder

Quand un placement de grid a besoin de contenu (« un widget météo ici », « un kanban de mes tâches »), résous dans cet ordre — placer un component existant surpasse l'authoring d'un doublon :

  1. Chercher le store : canvas-list avec kind=component et search=<ce que le widget affiche>. Un component est placeable quand component_meta et published_build_id sont définis. Si son configSchema peut exprimer la demande (« météo pour Lisbonne » → component météo existant avec config: {"location": "Lisbonne"}), place et configure — n'écris pas de code.
  2. Fork quand un component est proche mais son config ne peut pas exprimer la demande : lis sa source (canvas-source-retrieve), crée un nouveau component (canvas-create avec kind=component), adapte, publie. Nomme la différence dans la description du nouveau component.
  3. Builder nouveau quand rien ne convient — voir « Building a component » ci-dessous.

Les nouveaux components arrivent dans le canal où tu les crées. Crée-les dans le même canal que le grid qu'ils servent sauf si l'utilisateur demande à les partager plus largement.

Building a component

Un component s'authors exactement comme un freeform canvas — charge building-react-quill-canvases (ou building-html-canvases) plus querying-canvas-data et validating-and-publishing-canvases — avec trois additions. Un component affichant des données PostHog suit la même règle de vérifiabilité que tout canvas : une figure adossée à un insight lie son insight sauvegardé, une query ad-hoc expose la query exacte qui s'est exécutée (voir « Verifiability » dans querying-canvas-data). Démarre du projet complet et buildable dans references/component-example.md ; son envelope, son contrat de placement, ses déclarations de capability et son accès défensif à ph.state sont les parts qui cassent quand c'est improvisé.

  • Crée avec kind=component et une description écrite pour la recherche en store : dis ce que le widget affiche et ce que son config contrôle. Les placements futurs sont trouvés par ce texte.

  • Déclare le contrat de placement dans la clé component de top-level du projet :

    {
      "component": {
        "size": { "defaultW": 2, "defaultH": 1, "minW": 1, "minH": 1, "maxW": 4 },
        "configSchema": {
          "type": "object",
          "properties": { "location": { "type": "string", "description": "Ville pour afficher la météo" } }
        }
      }
    }

    La taille est en unités de grid (largeurs 1–12, hauteurs 1–40) ; minW <= defaultW <= maxW. La plage est informelle : les utilisateurs peuvent redimensionner un placement à n'importe quelle taille, elle informe les defaults et les avertissements, jamais les rejets. Le vocabulaire du config schema est un allowlist — type, title, description, default, properties, required, additionalProperties, items, enum, const, minimum, maximum, minLength, maxLength, minItems, maxItems, format. Pas de $ref, pas de pattern — la validation les rejette.

  • Designs responsively. Donne au root du component h-screen pour qu'il remplisse la viewport de l'iframe du placement, et adapte la layout à n'importe quelle taille que l'utilisateur drag : un placement 2×1 est une tile jetable ; un 6×4 est une surface d'app complète. N'utilise pas h-full sur le root : la shell artifact d'un component publié ne donne à ses éléments html, body et #root aucune hauteur explicite, donc height: 100% s'effondre à la hauteur du contenu. Rends utilement à minW×minH, et traite config comme le seul input par-placement.

Publie et attends le build comme tout canvas — un component sans build prêt ne peut pas aller en direct sur un grid.

Composing a whole canvas

Un whole-canvas ask (« un home canvas qui résume mon work in progress ») signifie habituellement plusieurs widgets, pas un. Planifie l'ensemble complet d'abord — un placement par concern — puis résous chacun avec l'échelle ci-dessus. Mets-les en layout ensemble : pas de chevauchements, tailles matchées à ce que chaque widget affiche, la grid remplie délibérément plutôt que des tiles disséminées dans un coin. Batch les écritures de layout (une publish pour une layout initiale, des patches chirurgicales après) au lieu d'une write par widget, et termine avec chaque placement en direct ou échoué — ne generant jamais.

Canvas comments

Les utilisateurs laissent du feedback sous forme de comment threads sur le canvas, ancrés à sa task de conversation. Liste-les avec les task comment tools (tasks-comments-list, tasks-comments-retrieve) sur ta task avant et après changer le canvas, et adresse les ouverts — un comment nommant un widget cassé est ton brief pour le fixer.

Editing a grid

La boucle est read → patch, gardée exactement comme validating-and-publishing-canvases le décrit pour les source publishes — avec canvas-layout-get à la place de canvas-source-retrieve, et canvas-layout-patch (ops chirurgicales, guard requis) ou canvas-layout-publish (document complet, pour une layout initiale ou full restructure) comme la write. Sur un 409, relis la layout, réapplique ton changement, et patch à nouveau.

Operations :

  • add_placement — une nouvelle box : {id, status, x, y, w, h, ...}. Les placements ne doivent pas se chevaucher ou dépasser grid.columns.
  • update_placement — merge changes dans le placement avec id. Remplir une box dessinée est {"op": "update_placement", "id": "p1", "changes": {"status": "live", "component": "<component canvas id>", "config": {...}}}.
  • remove_placement, set_grid.

The placement lifecycle

Le status d'un placement dit au renderer ce qu'il faut afficher :

  • pending — l'utilisateur a dessiné une box mais ne l'a pas décrite (ou le prompt attend dispatch).
  • generating — une agent task la remplit ; generationTaskId lie la task et prompt enregistre l'ask. Définis ceci quand tu commences à travailler sur un placement depuis une task.
  • live — rend son component à version ("latest" par défaut ; un pinned version id est permis). Requiert que le component soit publié et visible pour l'acting user.
  • failed — la generation a échoué ; garde le prompt pour que l'utilisateur puisse retry ou re-décrire.

Quand une task te demande de remplir un placement, son prompt et la taille de la box sont ton brief : honore le w×h dessiné et garde le prompt du placement intact pour la provenance.

Validation you will hit

Les layout publishes valident atomiquement ; chaque error nomme son placement. Les courantes :

  • component_not_found — l'id est mauvais, supprimé, pas un component, ou pas visible pour l'acting user (un component dans le canal personnel de quelqu'un d'autre n'est pas placeable).
  • component_not_published — le component n'a jamais publié un contrat de placement.
  • placement_config_invalid — config ne matche pas le configSchema du component.
  • placement_size_out_of_contract — un warning, pas une error : le w/h de la box est en dehors de la plage suggérée du component. La publish réussit quand même ; le component doit rendre responsively.
  • placements_overlap / invalid_placement — géométrie ; fixe les coordonnées plutôt que de retirer l'autre widget.

Termine ta réponse en linquant le grid canvas avec le champ url que les canvas tools retournent — ne construis jamais une canvas URL toi-même.

Skills similaires