Use this file to discover all available pages before exploring further.
The Social Media module bridges the gap between the institutional CMS and the channels the population actually uses. Rather than requiring staff to manually copy-paste content into each social platform, the module lets editors publish or schedule a post to multiple networks in a single action — ensuring authoritative health information reaches people on Facebook, Instagram, X, TikTok, and YouTube without duplication of effort or risk of transcription errors. The adapter architecture means adding a new platform in the future never touches existing publishing logic.
All social platforms are accessed through a shared SocialPublisher interface. The CMS and scheduling layers interact exclusively with this interface; they have no knowledge of any specific platform’s API.
Each supported platform has a concrete adapter injected by NestJS’s dependency injection container:
FacebookAdapter
InstagramAdapter
XAdapter (formerly Twitter)
TikTokAdapter
YouTubeAdapter
Adding a new social platform never requires changes to the CMS module or scheduling logic. Each adapter is an isolated @Injectable() class. This is Clean Architecture’s Open/Closed Principle in action — the system is open for extension but closed for modification.
At runtime the SocialService resolves the correct adapter for each platform in the platforms array of a SocialPost. This lookup is performed through a SocialAdapterRegistry — a map keyed by Platform enum value — so adding a new adapter is a matter of registering it in one place.
A SocialPost carries everything an adapter needs to produce a platform-specific publication. Media assets are resolved from the Multimedia Module before the post object is constructed.
interface SocialPost { contentId: string; // CMS content UUID text: string; // Post caption (may be truncated per-platform by the adapter) mediaUrls: string[]; // Resolved asset URLs from the Multimedia Module platforms: Platform[]; // Target platforms for this publication publishAt?: Date; // If set, the post is scheduled rather than immediate}
Each adapter is responsible for enforcing its platform’s character limit. If the text field exceeds the platform maximum, the adapter truncates it and appends an ellipsis before calling the platform API. The original text is preserved in the database record.
All endpoints require authentication. Scheduling and republishing are privileged operations restricted to users with the social:write permission scope.
POST /social/publishPOST /social/schedulePOST /social/republish/:postIdGET /social/postsGET /social/posts/:postId/status
POST /social/publishContent-Type: application/jsonAuthorization: Bearer <token>
{ "contentId": "uuid-of-cms-content", "text": "Nueva campaña de vacunación disponible en todos los centros de salud de la Jurisdicción. Infórmate aquí.", "mediaUrls": ["https://storage.example.com/uploads/campana-vacunacion.jpg"], "platforms": ["facebook", "instagram"]}
A successful response returns 201 Created with per-platform publish results:
POST /social/republish/:postIdAuthorization: Bearer <token>
Republishes a previously published or failed post using the same content and platforms as the original. Useful for retrying after a platform API outage.
GET /social/posts/:postId/statusAuthorization: Bearer <token>
Returns the current status of a post as reported by the platform adapter. If the post was scheduled, this endpoint reflects whether it has been published or is still pending.
Platform credentials are read from environment variables at startup. No credentials are ever stored in the database or committed to source control.
# FacebookFACEBOOK_PAGE_ID=...FACEBOOK_ACCESS_TOKEN=...# InstagramINSTAGRAM_ACCOUNT_ID=...INSTAGRAM_ACCESS_TOKEN=...# X (Twitter)X_API_KEY=...X_API_SECRET=...X_ACCESS_TOKEN=...X_ACCESS_SECRET=...# TikTokTIKTOK_ACCESS_TOKEN=...# YouTubeYOUTUBE_CLIENT_ID=...YOUTUBE_CLIENT_SECRET=...YOUTUBE_REFRESH_TOKEN=...
Access tokens for Facebook and Instagram expire periodically. Implement a token-refresh job or use a long-lived page token where the platform allows it. Expired tokens will cause publish operations to fail silently if not monitored.
Extending the Social module to support a new platform requires only three steps — no changes to existing adapters, services, or the CMS module.
1
Implement the SocialPublisher interface
Create a new file under src/social/adapters/ and implement all four methods.
// src/social/adapters/new-platform.adapter.ts@Injectable()export class NewPlatformAdapter implements SocialPublisher { async publish(content: SocialPost): Promise<SocialPublishResult> { // Platform-specific API call } async schedule(content: SocialPost, publishAt: Date): Promise<SocialScheduleResult> { // Platform-specific scheduling } async republish(postId: string): Promise<SocialPublishResult> { // Fetch original post and re-publish } async getStatus(postId: string): Promise<SocialPostStatus> { // Query platform API for post status }}
2
Register the adapter in SocialAdapterRegistry
Add the new platform to the Platform enum and register the adapter in SocialAdapterRegistry.
// Add to Platform enumexport enum Platform { FACEBOOK = 'facebook', INSTAGRAM = 'instagram', X = 'x', TIKTOK = 'tiktok', YOUTUBE = 'youtube', NEW_PLATFORM = 'new-platform', // ← new entry}
3
Add environment variables
Document the required credentials in .env.example and your deployment environment. The adapter should read all secrets from ConfigService — never from process.env directly.