Skip to content

Add PostingCapabilities interface for centralized provider configuration #1268

@rohansx

Description

@rohansx

Problem

Provider capabilities (character limits, media validation, comment support) are currently scattered across the codebase:

  1. Backend provider classes define maxLength(), optional comment(), analytics(), and mediaCapabilities — but these are only accessible server-side.
  2. 30+ frontend provider components each hardcode maximumCharacters and checkValidity in their withProvider() calls — duplicating what the backend already knows.
  3. No single source of truth — when a limit changes (e.g. X raising character limits for premium users), both backend and frontend must be updated independently.

This makes adding new providers tedious, updating limits error-prone, and the architecture harder to reason about.

Solution

Introduce a PostingCapabilities interface — a unified, server-computed descriptor that each provider generates once via introspection, and the frontend consumes from the API.

What PostingCapabilities captures

type PostingCapabilities = {
  media: MediaCapabilities;
  maxLength: number;
  editor: 'none' | 'normal' | 'markdown' | 'html';
  supportsComments: boolean;
  supportsAnalytics: boolean;
  supportsMentions: boolean;
  commentsMediaSupport: boolean | 'no-media';
};

How it works

  • SocialAbstract.getPostingCapabilities() introspects the provider instance at runtime — checks for comment(), analytics(), mention() methods, reads mediaCapabilities, calls maxLength() with the integration's settings (resolving dynamic limits like X premium vs regular).
  • /integrations/list endpoint now includes postingCapabilities per integration, computed with the user's actual settings.
  • withProvider() HOC gains resolvedMaxChars, resolvedComments, and resolvedCheckValidity — each falls back to API-provided capabilities when the provider component doesn't explicitly override them.
  • validateMediaFromCapabilities() — a new frontend utility that performs generic media validation (image/video counts, mixing rules, required media) from the capabilities object, replacing 25 identical or trivial checkValidity implementations.

What changes across the codebase

Backend (6 files):

  • PostingCapabilities type + commentsMediaSupport added to SocialProvider interface
  • getPostingCapabilities() method on SocialAbstract
  • getSocialIntegration() return type updated to expose the method
  • /integrations/list controller resolves and includes postingCapabilities
  • Instagram providers annotated with commentsMediaSupport = 'no-media'

Frontend (33 files):

  • Integrations type extended with mediaCapabilities and postingCapabilities
  • withProvider() HOC updated with capability-aware fallbacks
  • New validateMediaFromCapabilities() utility
  • 25 simple providers — removed both maximumCharacters and checkValidity (now derived from API)
  • 5 complex providers (X, Instagram, YouTube, TikTok, Pinterest) — removed maximumCharacters only, retained checkValidity for platform-specific validation (video duration, cover images, trial reels, etc.)

Design decisions

  • Introspection over declaration: getPostingCapabilities() checks typeof self.comment === 'function' rather than requiring each provider to manually declare supportsComments: true. This means existing and future providers get correct capabilities automatically.
  • Opt-in overrides: The HOC still accepts explicit maximumCharacters and checkValidity — capabilities are a fallback, not a mandate. Complex providers keep their custom validation.
  • Server-side resolution: Dynamic limits (X's 280 vs 4000 based on Verified setting) are resolved per-integration-instance on the server, so the frontend never needs to know the business logic.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions