Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions context/skills/integration/config.yaml
Original file line number Diff line number Diff line change
@@ -1,46 +1,55 @@
# Integration skills - example-based (code + docs)
# `framework` = the detection id a variant serves; `default: true` marks the family default. Both are emitted into skill-menu.json.
type: skill
template: description.md
description: PostHog integration for {display_name} applications
shared_docs:
- https://posthog.com/docs/getting-started/identify-users.md
variants:
- id: nextjs-app-router
framework: nextjs
default: true
example_paths: example-apps/next-app-router
display_name: Next.js App Router
tags: [nextjs, react, ssr, app-router, javascript, javascript_web, javascript_node]
docs_urls:
- https://posthog.com/docs/libraries/next-js.md

- id: nextjs-pages-router
framework: nextjs
example_paths: example-apps/next-pages-router
display_name: Next.js Pages Router
tags: [nextjs, react, ssr, pages-router, javascript, javascript_web, javascript_node]
docs_urls:
- https://posthog.com/docs/libraries/next-js.md

- id: react-react-router-6
framework: react-router
default: true
example_paths: example-apps/react-react-router-6
display_name: React Router v6
tags: [react, react-router, v6, spa, javascript, javascript_web]
docs_urls:
- https://posthog.com/docs/libraries/react-router/react-router-v6.md

- id: react-react-router-7-framework
framework: react-router
example_paths: example-apps/react-react-router-7-framework
display_name: React Router v7 - Framework mode
tags: [react, react-router, v7, framework, ssr, javascript, javascript_node, javascript_web]
docs_urls:
- https://posthog.com/docs/libraries/react-router/react-router-v7-framework-mode.md

- id: react-react-router-7-data
framework: react-router
example_paths: example-apps/react-react-router-7-data
display_name: React Router v7 - Data mode
tags: [react, react-router, v7, data, spa, javascript, javascript_web]
docs_urls:
- https://posthog.com/docs/libraries/react-router/react-router-v7-data-mode.md

- id: react-react-router-7-declarative
framework: react-router
example_paths: example-apps/react-react-router-7-declarative
display_name: React Router v7 - Declarative mode
tags: [react, react-router, v7, declarative, spa, javascript, javascript_web]
Expand All @@ -56,6 +65,8 @@ variants:
- https://posthog.com/docs/libraries/react.md

- id: nuxt-3-6
framework: nuxt
default: true
example_paths: example-apps/nuxt-3-6
display_name: Nuxt 3.6
description: PostHog integration for Nuxt versions 3.0 to 3.6
Expand All @@ -64,6 +75,7 @@ variants:
- https://posthog.com/docs/libraries/nuxt-js-3-6.md

- id: nuxt-4
framework: nuxt
example_paths: example-apps/nuxt-4
display_name: Nuxt 4
description: PostHog integration for Nuxt 4 applications
Expand All @@ -72,6 +84,7 @@ variants:
- https://posthog.com/docs/libraries/nuxt-js.md

- id: vue-3
framework: vue
example_paths: example-apps/vue-3
display_name: Vue 3
description: PostHog integration for Vue 3 applications
Expand All @@ -80,20 +93,23 @@ variants:
- https://posthog.com/docs/libraries/vue-js.md

- id: django
framework: django
example_paths: example-apps/django
display_name: Django
tags: [django, python]
docs_urls:
- https://posthog.com/docs/libraries/django.md

- id: flask
framework: flask
example_paths: example-apps/flask
display_name: Flask
tags: [flask, python]
docs_urls:
- https://posthog.com/docs/libraries/flask.md

- id: fastapi
framework: fastapi
example_paths: example-apps/fastapi
display_name: FastAPI
description: PostHog integration for FastAPI applications
Expand All @@ -102,6 +118,7 @@ variants:
- https://posthog.com/docs/libraries/python.md

- id: react-tanstack-router-file-based
framework: tanstack-router
example_paths: example-apps/react-tanstack-router-file-based
display_name: React with TanStack Router (file-based)
description: PostHog integration for React applications using TanStack Router with file-based routing
Expand All @@ -110,6 +127,8 @@ variants:
- https://posthog.com/docs/libraries/tanstack-start.md

- id: react-tanstack-router-code-based
framework: tanstack-router
default: true
example_paths: example-apps/react-tanstack-router-code-based
display_name: React with TanStack Router (code-based)
description: PostHog integration for React applications using TanStack Router with code-based routing
Expand All @@ -118,6 +137,7 @@ variants:
- https://posthog.com/docs/libraries/tanstack-start.md

- id: tanstack-start
framework: tanstack-start
example_paths: example-apps/tanstack-start
display_name: TanStack Start
description: PostHog integration for TanStack Start full-stack applications
Expand All @@ -126,6 +146,7 @@ variants:
- https://posthog.com/docs/libraries/tanstack-start.md

- id: laravel
framework: laravel
example_paths: example-apps/laravel
display_name: Laravel
tags: [laravel, php]
Expand All @@ -141,6 +162,7 @@ variants:
- https://posthog.com/docs/libraries/php.md

- id: ruby-on-rails
framework: rails
example_paths: example-apps/ruby-on-rails
display_name: Ruby on Rails
tags: [ruby-on-rails, ruby]
Expand All @@ -149,6 +171,7 @@ variants:
- https://posthog.com/docs/libraries/ruby.md

- id: android
framework: android
example_paths: example-apps/android
display_name: Android
description: PostHog integration for Android applications
Expand All @@ -157,6 +180,7 @@ variants:
- https://posthog.com/docs/libraries/android.md

- id: sveltekit
framework: sveltekit
example_paths: example-apps/sveltekit
display_name: SvelteKit
description: PostHog integration for SvelteKit applications
Expand All @@ -166,6 +190,7 @@ variants:

# Language fallback skills, used when no specific framework is detected
- id: python
framework: python
example_paths: example-apps/python
display_name: Python
description: PostHog integration for any Python application using the Python SDK
Expand All @@ -175,6 +200,7 @@ variants:
- https://posthog.com/docs/references/posthog-python.md

- id: javascript_node
framework: javascript_node
example_path: example-apps/javascript-node
display_name: JavaScript Node
description: PostHog integration for server-side Node.js applications using posthog-node
Expand All @@ -184,6 +210,7 @@ variants:
- https://posthog.com/docs/references/posthog-node.md

- id: javascript_web
framework: javascript_web
example_path: example-apps/javascript-web
display_name: JavaScript Web
description: PostHog integration for client-side web JavaScript applications using posthog-js
Expand All @@ -193,6 +220,7 @@ variants:
- https://posthog.com/docs/references/posthog-js.md

- id: ruby
framework: ruby
example_paths: example-apps/ruby
display_name: Ruby
description: PostHog integration for any Ruby application using the Ruby SDK
Expand All @@ -217,6 +245,7 @@ variants:
- https://posthog.com/docs/libraries/go.md

- id: swift
framework: swift
example_paths:
- example-apps/swift
- example-apps/swift-xcodegen
Expand All @@ -237,6 +266,8 @@ variants:
- https://posthog.com/docs/libraries/flutter.md

- id: react-native
framework: react-native
default: true
example_paths: example-apps/react-native
display_name: React Native
description: PostHog integration for React Native applications
Expand All @@ -245,6 +276,7 @@ variants:
- https://posthog.com/docs/libraries/react-native.md

- id: expo
framework: react-native
example_paths: example-apps/expo
display_name: Expo
description: PostHog integration for Expo applications
Expand All @@ -253,6 +285,7 @@ variants:
- https://posthog.com/docs/libraries/react-native.md

- id: astro-static
framework: astro
example_paths: example-apps/astro-static
display_name: Astro (Static)
description: PostHog integration for static Astro sites using SSG
Expand All @@ -261,6 +294,7 @@ variants:
- https://posthog.com/docs/libraries/astro.md

- id: astro-view-transitions
framework: astro
example_paths: example-apps/astro-view-transitions
display_name: Astro (View Transitions)
description: PostHog integration for Astro with ClientRouter view transitions
Expand All @@ -269,6 +303,7 @@ variants:
- https://posthog.com/docs/libraries/astro.md

- id: astro-ssr
framework: astro
example_paths: example-apps/astro-ssr
display_name: Astro (SSR)
description: PostHog integration for server-rendered Astro applications with API routes
Expand All @@ -277,6 +312,8 @@ variants:
- https://posthog.com/docs/libraries/astro.md

- id: astro-hybrid
framework: astro
default: true
example_paths: example-apps/astro-hybrid
display_name: Astro (Hybrid)
description: PostHog integration for Astro hybrid rendering with both static and server-rendered pages
Expand All @@ -285,6 +322,7 @@ variants:
- https://posthog.com/docs/libraries/astro.md

- id: angular
framework: angular
example_paths: example-apps/angular
display_name: Angular
description: PostHog integration for Angular applications
Expand Down
11 changes: 8 additions & 3 deletions scripts/lib/agent-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,19 @@ export function loadAgentEntries(agentsSourceDir) {
}

/**
* A prompt's frontmatter `flow:` must match its folder — the folder is the
* registry scope, the frontmatter keeps the file self-describing on disk.
* A prompt's frontmatter `flow:` must be present and match its folder
* consumers filter by it, so a missing key would silently drop the prompt.
*/
function assertFlowMatches(sourcePath, flow) {
const text = fs.readFileSync(sourcePath, 'utf8');
const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---/);
const declared = match?.[1].match(/^flow:\s*(.+?)\s*$/m)?.[1];
if (declared && declared !== flow) {
if (!declared) {
throw new Error(
`Agent prompt ${sourcePath} is missing the "flow:" frontmatter key — declare flow: ${flow}`,
);
}
if (declared !== flow) {
throw new Error(
`Agent prompt ${sourcePath} declares flow "${declared}" but lives in agents/${flow}/`,
);
Expand Down
9 changes: 7 additions & 2 deletions scripts/lib/build-phases.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,11 +190,16 @@ function writeManifestAndMenu({ allSkills, docContents, distDir, configDir, vers
for (const skill of allSkills) {
const cat = skill.group;
if (!skillsByCategory[cat]) skillsByCategory[cat] = [];
skillsByCategory[cat].push({
// group/framework/default let consumers resolve a bare skill id + framework by exact match.
const entry = {
id: skill.id,
name: skill.name,
group: skill.group.replace(/\//g, '-'),
downloadUrl: manifest.resources.find(r => r.id === skill.id)?.downloadUrl,
});
};
if (skill.framework) entry.framework = skill.framework;
if (skill.default) entry.default = true;
skillsByCategory[cat].push(entry);
}

// The CLI entries are the lookup table the wizard's runtime resolver uses
Expand Down
33 changes: 24 additions & 9 deletions scripts/lib/skill-generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,15 +228,19 @@ function normalizeExamplePaths(value) {
/**
* Resolve `variants_from` references: a group may borrow another group's
* variant matrix instead of duplicating it. Only the framework identity comes
* across — id, display_name, tags, docs_urls — never example paths, templates,
* cli blocks, or shared docs, which stay the borrowing group's own concern.
* One level only; a source group must declare its variants literally.
* across — id, display_name, tags, docs_urls, framework, default — never
* example paths, templates, cli blocks, or shared docs, which stay the
* borrowing group's own concern. One level only; a source group must declare
* its variants literally. Pure — returns a new config, never mutates the input.
*/
function resolveVariantsFrom(config) {
const resolved = {};
for (const [key, group] of Object.entries(config)) {
if (!group.variants_from) continue;
if (!group.variants_from) {
resolved[key] = group;
continue;
}
if (group.variants) {
if (group._variantsResolved) continue;
throw new Error(`Skill group "${key}": declare either variants or variants_from, not both`);
}
const source = config[group.variants_from];
Expand All @@ -246,14 +250,19 @@ function resolveVariantsFrom(config) {
if (source.variants_from) {
throw new Error(`Skill group "${key}": variants_from cannot chain ("${group.variants_from}" also uses variants_from)`);
}
group.variants = source.variants.map(v => {
const variants = source.variants.map(v => {
const variant = { id: v.id, display_name: v.display_name };
if (v.tags) variant.tags = [...v.tags];
if (v.docs_urls) variant.docs_urls = [...v.docs_urls];
if (v.framework) variant.framework = v.framework;
if (v.default) variant.default = v.default;
return variant;
});
group._variantsResolved = true;
// Drop the reference key — the resolved copy declares variants literally.
const { variants_from: _from, ...rest } = group;
resolved[key] = { ...rest, variants };
}
return resolved;
}

/**
Expand All @@ -263,9 +272,9 @@ function resolveVariantsFrom(config) {
*/
function expandSkillGroups(config, configDir) {
const skills = [];
resolveVariantsFrom(config);
const resolvedConfig = resolveVariantsFrom(config);

for (const [key, group] of Object.entries(config)) {
for (const [key, group] of Object.entries(resolvedConfig)) {
if (key === 'shared_docs') continue;
if (!group.variants) continue;

Expand Down Expand Up @@ -796,6 +805,12 @@ function serializeSkill(s) {
description: s.description,
tags: s.tags || [],
};
if (s.framework) {
result.framework = s.framework;
}
if (s.default) {
result.default = true;
}
if (s._cli) {
result.cli = s._cli;
}
Expand Down
Loading
Loading