mirror of
https://github.com/coreyhaines31/marketingskills.git
synced 2026-09-14 16:48:11 +08:00
feat: partners.json single source + sync script
partners.json is now the canonical partner registry. scripts/sync-partners.mjs regenerates the README Partners section and the tools/REGISTRY.md Verified Partners table (between PARTNERS:START/END markers) from it — run after editing partners.json, or 'node scripts/sync-partners.mjs --check' in CI. The marketing-skills.com site reads the same partners.json directly (raw GitHub), so one edit updates every surface. Deactivate a lapsed partner with active:false. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,9 +14,11 @@ Run into a problem or have a question? [Open an issue](https://github.com/coreyh
|
||||
|
||||
The library is free and MIT-licensed. [Verified Partners](tools/REGISTRY.md#verified-partners) fund the work — vetted, disclosed tool integrations, listed alongside the neutral options and never influencing what the core skills recommend. [Become a partner →](https://marketing-skills.com/sponsorship)
|
||||
|
||||
<!-- PARTNERS:START -->
|
||||
> ◆ **[Converly](https://converly.io?ref=marketingskills)** — *Conversion tracking / attribution.* Server-side conversion tracking that fires when someone submits a form, books a meeting, or starts a chat — passing click IDs and identifiers for Enhanced Conversions (Google) and high EMQ match rates (Meta), across 100+ tools. CLI + MCP so your agent sets it up in minutes. → [Integration guide](tools/integrations/converly.md)
|
||||
<!-- PARTNERS:END -->
|
||||
|
||||
<!-- Featured logo goes here once Converly provides an SVG/PNG asset. -->
|
||||
<!-- The Partners block above is generated from partners.json — run `node scripts/sync-partners.mjs` after editing it. -->
|
||||
|
||||
## What are Skills?
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"_comment": "Canonical partner registry — single source of truth. Fill one object per partner from their onboarding packet, then run `node scripts/sync-partners.mjs` to regenerate the README Partners section and the Verified Partners table in tools/REGISTRY.md. The marketing-skills.com site fetches this file directly (raw GitHub). Deactivate a lapsed partner with active:false (keeps history, removes it everywhere).",
|
||||
"partners": [
|
||||
{
|
||||
"id": "converly",
|
||||
"name": "Converly",
|
||||
"url": "https://converly.io",
|
||||
"category": "Marketing analytics & attribution",
|
||||
"categoryShort": "Conversion tracking / attribution",
|
||||
"tier": "skill-partner",
|
||||
"tagline": "Server-side conversion tracking",
|
||||
"blurb": "Server-side conversion tracking that fires when someone submits a form, books a meeting, or starts a chat — passing click IDs and identifiers for Enhanced Conversions (Google) and high EMQ match rates (Meta), across 100+ tools. CLI + MCP so your agent sets it up in minutes.",
|
||||
"logoUrl": "",
|
||||
"integration": "tools/integrations/converly.md",
|
||||
"active": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
// Regenerate every partner surface from the canonical partners.json.
|
||||
//
|
||||
// node scripts/sync-partners.mjs # write the generated blocks
|
||||
// node scripts/sync-partners.mjs --check # fail if anything is out of date (CI)
|
||||
//
|
||||
// Owns the marked blocks in:
|
||||
// - README.md → the Partners section list
|
||||
// - tools/REGISTRY.md → the Verified Partners table
|
||||
// Everything outside the <!-- PARTNERS:START --> / <!-- PARTNERS:END --> markers
|
||||
// is left untouched. The marketing-skills.com site reads partners.json directly.
|
||||
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { resolve, dirname } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const HERE = dirname(fileURLToPath(import.meta.url));
|
||||
const ROOT = resolve(HERE, "..");
|
||||
const REPO = "https://github.com/coreyhaines31/marketingskills/blob/main";
|
||||
const REF = "?ref=marketingskills";
|
||||
|
||||
const START = "<!-- PARTNERS:START -->";
|
||||
const END = "<!-- PARTNERS:END -->";
|
||||
const check = process.argv.includes("--check");
|
||||
|
||||
const { partners } = JSON.parse(readFileSync(resolve(ROOT, "partners.json"), "utf8"));
|
||||
const active = partners.filter((p) => p.active);
|
||||
|
||||
const readmeBlock = active.length
|
||||
? active
|
||||
.map(
|
||||
(p) =>
|
||||
`> ◆ **[${p.name}](${p.url}${REF})** — *${p.categoryShort || p.category}.* ${p.blurb} → [Integration guide](${p.integration})`
|
||||
)
|
||||
.join("\n\n")
|
||||
: "_No active partners yet. [Become a partner →](https://marketing-skills.com/sponsorship)_";
|
||||
|
||||
const registryBlock = [
|
||||
"| Partner | Category | Guide |",
|
||||
"|---------|----------|-------|",
|
||||
...active.map(
|
||||
(p) =>
|
||||
`| ◆ ${p.name} | ${p.categoryShort || p.category} | [${p.integration.split("/").pop()}](${p.integration.replace(/^tools\//, "")}) |`
|
||||
),
|
||||
].join("\n");
|
||||
|
||||
const targets = [
|
||||
{ file: "README.md", block: readmeBlock },
|
||||
{ file: "tools/REGISTRY.md", block: registryBlock },
|
||||
];
|
||||
|
||||
let stale = false;
|
||||
for (const { file, block } of targets) {
|
||||
const path = resolve(ROOT, file);
|
||||
const src = readFileSync(path, "utf8");
|
||||
const i = src.indexOf(START);
|
||||
const j = src.indexOf(END);
|
||||
if (i === -1 || j === -1 || j < i) {
|
||||
console.error(`✗ ${file}: missing ${START} / ${END} markers`);
|
||||
process.exitCode = 1;
|
||||
continue;
|
||||
}
|
||||
const next = src.slice(0, i + START.length) + "\n" + block + "\n" + src.slice(j);
|
||||
if (next === src) {
|
||||
console.log(`✓ ${file} up to date`);
|
||||
continue;
|
||||
}
|
||||
if (check) {
|
||||
console.error(`✗ ${file} is out of date — run: node scripts/sync-partners.mjs`);
|
||||
stale = true;
|
||||
continue;
|
||||
}
|
||||
writeFileSync(path, next);
|
||||
console.log(`↻ ${file} updated (${active.length} partner${active.length === 1 ? "" : "s"})`);
|
||||
}
|
||||
|
||||
if (check && stale) process.exitCode = 1;
|
||||
@@ -17,9 +17,13 @@ Quick reference for AI agents to discover tool capabilities and integration meth
|
||||
- **Disclosed + vetted for fit.** Each carries a disclosure header in its integration guide and is marked ◆ in the index below.
|
||||
- **Additive, never biasing.** A partner is listed *alongside* the neutral options for the same job, never instead of them. Partner status never removes or demotes another tool and **never changes what any skill recommends** — if a non-partner is the right answer, that's the answer. The badge means "paid, disclosed, vetted for fit," not "best in category."
|
||||
|
||||
<!-- PARTNERS:START -->
|
||||
| Partner | Category | Guide |
|
||||
|---------|----------|-------|
|
||||
| ◆ Converly | Conversion tracking / attribution | [converly.md](integrations/converly.md) |
|
||||
<!-- PARTNERS:END -->
|
||||
|
||||
<!-- The table above is generated from partners.json — run `node scripts/sync-partners.mjs`. -->
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user