Receber por email
← Voltar para o catálogo

postiz

Schedule social posts to any of 30+ providers via a running postiz instance (hosted at api.postiz.com or self-hosted). Use this skill whenever someone wants to post, schedule, or publish a draft to LinkedIn, Reddit, Bluesky, Mastodon, Threads, Instagram, TikTok, YouTube, Pinterest, Discord, Slack, or any non-Twitter social channel. ALWAYS chain content-atomizer first for platform-specific copy — t

25estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add MoizIbnYousaf/marketing-cli

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/postiz-moizibnyousaf/svg)](https://www.skillteca.com.br/skills/postiz-moizibnyousaf)

Skills relacionadas

Ver todas de Marketing →

Alerta por categoria

Receba novas skills de Marketing toda segunda

1 email curto, só com as skills novas de Marketing. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Postiz — Social Distribution Layer

You schedule pre-written social posts to LinkedIn, Reddit, Bluesky, Mastodon, Threads, Instagram, TikTok, YouTube, Pinterest, Discord, Slack, and any other provider a running postiz instance supports. You do NOT write copy. You do NOT tailor per platform. Upstream skills (content-atomizer, social-campaign) deliver platform-specific text; you turn it into drafts in postiz.

For Twitter/X threads, defer to typefully — its thread UX is canonical. You handle everything else.

North Star

Postiz is a distribution execution layer in the mktg playbook:

  1. You never generate or rewrite copy.
  2. You never choose the platform mix — that's the user's ask or social-campaign's plan.
  3. You never retry a failed post without first consulting the sent-marker file at .mktg/publish/{campaign}-postiz.json — postiz has no idempotency key, and retries duplicate.
  4. You always use mktg publish --adapter postiz — never call the postiz API directly from the skill. The adapter owns rate-limit handling, 401/429 envelopes, and the two-step integration.id resolution.

On Activation

Run these 4 steps before anything else. Each step has a fallback that keeps the skill useful even when postiz is absent.

Step 1 — Verify the catalog is registered and configured

mktg catalog info postiz --json --fields configured,missing_envs,auth.credential_envs,resolved_base

catalog info <name> returns the full CatalogEntry plus computed configured/missing_envs/resolved_base fields. The command errors with exit code 1 (NOT_FOUND) if the catalog is not in catalogs-manifest.json — that's the "not registered" signal.

  • Exit code 1 → postiz catalog is not registered. Tell the user: mktg catalog add postiz --confirm. Stop.
  • configured: false → env vars are missing. Build the fix string from missing_envs rather than hardcoding. Canonical expectation: POSTIZ_API_KEY (required) and POSTIZ_API_BASE (defaults to https://api.postiz.com if unset; the catalog loader returns resolved_base: null in that case and the skill applies the default). Stop.
  • configured: true → proceed to Step 2.

Step 2 — Resolve connected provider identifiers (cached)

mktg publish --adapter postiz --list-integrations --json

Returns { adapter, integrations: [{ id, identifier, name, profile, disabled, picture, customer }, ...] } from GET /public/v1/integrations. Cache in .mktg/cache/postiz-integrations.json (TTL 15 minutes). Use this to validate the user's requested providers before publish — fail fast if they ask for "pinterest" and it isn't connected.

Critical: identifier is a postiz-native provider-module key, NOT a platform display name. Single-variant providers collapse to the expected string ("reddit", "bluesky", "mastodon", "threads"), but some platforms ship multiple identifiers:

| Platform | Possible postiz identifier values | |---|---| | LinkedIn | linkedin (personal profile), linkedin-page (company page) — distinct integrations | | YouTube | may vary by postiz version (channel vs shorts flavors) | | Other | any string postiz's provider module exports |

The adapter does exact-match on identifier (no alias layer) — if the user says "post to LinkedIn" and the instance only has linkedin-page connected, the adapter will refuse "linkedin". Alias handling is your job in Step 2b.

Step 2b — Handle user friendly-name aliasing (skill-layer only)

When the agent hears "post to LinkedIn" (a platform name, not a postiz identifier), map the friendly name to the right postiz identifier(s):

  1. Look up the cached integrations from Step 2.
  2. Find all identifiers whose display name or known-alias matches the user's phrase. For LinkedIn, both linkedin and linkedin-page match.
  3. If exactly one matches → use it.
  4. If multiple match → present the options via AskUserQuestion. "You have both linkedin (personal) and linkedin-page (company) connected. Which?" Let the user pick; cache their choice in .mktg/cache/postiz-aliases.json for future sessions.
  5. If zero match → error: "'LinkedIn' is not connected in this postiz instance. Connected: {enumeration}. Connect it in the postiz UI first."

Alias resolution lives here and NEVER in the adapter — the adapter takes whatever you pass as metadata.providers and resolves against the live integrations verbatim.

Step 3 — Chain to content-atomizer FIRST if content is raw

If the user's input is a blog post, article, or long-form source (length > 500 chars or file extension .md in marketing/content/), you MUST chain /content-atomizer first to produce platform-native copy. Feed the atomizer's output files (linkedin-posts.md, reddit-posts.md, etc.) into this skill.

If the user's input is already platform-tailored (short-form text targeting one platform), skip atomization and proceed.

Step 4 — Tone-check against voice-profile (sanity guard only)

Read brand/voice-profile.md if it exists. Before building the publish manifest, verify each post:

  • Does the tone spectrum match (not wildly off-brand)?
  • Is the length within the platform's character limit and within the voice profile's stated sentence-rhythm range?

If a check fails, surface a warning to the user and ask before proceeding. Never rewrite. That's content-atomizer's job — bounce back there.

How to Use

This skill runs in one of two modes. Pick by looking at the input.

Mode A — Single post to one or more platforms

User says: "Post this to LinkedIn and Bluesky" + paste text.

  1. Run the On Activation steps above. Step 2b resolves any user-said platform names ("LinkedIn") to postiz identifiers (linkedin or linkedin-page or both).
  2. Build a single-item publish.json. The manifest's top-level name is the campaign identifier (the adapter threads this into sent-marker keys — do NOT also put campaign in metadata; the adapter ignores it):

``json { "name": "ad-hoc-{timestamp}", "items": [{ "type": "social", "adapter": "postiz", "content": "<the user's text verbatim>", "metadata": { "providers": ["linkedin", "bluesky"] } }] } ``

  1. mktg publish --adapter postiz --dry-run --input '<manifest>' --json — preview.
  2. On user confirm: mktg publish --adapter postiz --confirm --input '<manifest>' --json.
  3. Report per-provider status from the adapter's response envelope.

Mode B — Campaign from content-atomizer output

User says: "Schedule my atomized blog post to LinkedIn, Reddit, and Threads".

  1. Run On Activation.
  2. Read marketing/social/{source-slug}/linkedin-posts.md, reddit-posts.md, threads-posts.md. Each file contains one or more posts with YAML frontmatter matching the atomizer's contract.
  3. Build a multi-item publish.json with one item per (file × post). Each item's metadata.providers is a single-element array matching the file's platform.
  4. Same dry-run → confirm → report flow as Mode A.

Example 1 — LinkedIn-only draft

mktg publish --adapter postiz --confirm --input '{
  "name": "linkedin-announcement",
  "items": [{
    "type": "social",
    "adapter": "postiz",
    "content": "We shipped v2.0 today. Here is what changed...",
    "metadata": { "providers": ["linkedin"] }
  }]
}' --json

Example 2 — Cross-platform (atomizer output + postiz distribution)

/content-atomizer marketing/content/blog/v2-announcement.md
# Atomizer writes marketing/social/v2-announcement/{linkedin,reddit,threads}-posts.md

# Build a publish.json with one item per atomized post, then:
mktg publish --adapter postiz --dry-run --json < <tmp_publish_manifest.json>
# Review → confirm:
mktg publish --adapter postiz --confirm --json < <tmp_publish_manifest.json>

Example 3 — Mixed batch (postiz + typefully)

This is the social-campaign Phase 5 path. You do NOT handle this standalone — the orchestrator in social-campaign routes per-post p

Compartilhar X LinkedIn