Skip to content

Status: ✅ Implemented (Phase 2) Last Updated: November 28, 2025

Overview ​

TendSocial's social media publishing feature enables users to create, schedule, and publish content across multiple social platforms from a single interface. The system handles OAuth authentication, token management, media uploads, and provides detailed analytics.

Supported Platforms & Capabilities ​

PlatformCapabilitiesNotes
Facebook PagesPublish, Schedule, Comments, Messages, Analytics, First CommentPages only, no personal profiles
Instagram BusinessPublish, Schedule, Comments, Stories (Reminder), Analytics, ReelsBusiness accounts only
LinkedIn PagesPublish, Schedule, Comments, AnalyticsCompany and Personal Pages
Twitter / XPublish, Schedule, Comments, Analytics, Threads
YouTubePublish, Schedule, Comments, Analytics, Shorts
TikTok BusinessPublish, AnalyticsBusiness accounts only
PinterestPublish, Schedule, Analytics, Boards
Google BusinessPublish, Reviews, Analytics
ThreadsPublish, Comments
BlueskyPublish, Comments
MastodonPublish, Comments
RedditPublish, Comments, Subreddits

Architecture ​

Core Components ​

┌──────────────────────────────────────────────────────────┐
│                    Frontend (React App)                   │
│  - Platform authentication flows                          │
│  - Post composition interface                             │
│  - Scheduling UI                                          │
└────────────────┬──────────────────────────────────────────┘
                 │ HTTP/REST
┌────────────────▼──────────────────────────────────────────┐
│              Fastify API (Backend)                         │
├──────────────────────────────────────────────────────────┤
│  Routes:                                                  │
│  - POST /api/social/posts                                │
│  - GET  /api/social/accounts                             │
│  - DELETE /api/social/accounts/{id}                      │
└────────────────┬──────────────────────────────────────────┘
                 │
    ┌────────────┼────────────┐
    │            │            │
    ▼            ▼            ▼
┌─────────┐ ┌──────────┐ ┌──────────┐
│Platform │ │  Token   │ │Analytics │
│Services │ │ Refresh  │ │ Service  │
│(4x)     │ │ Worker   │ │          │
└─────────┘ └──────────┘ └──────────┘
    │
    └────────────┬────────────────────────────┐
                 │                            │
                 ▼                            ▼
        ┌─────────────────┐        ┌──────────────────┐
        │ Prisma ORM /DB  │        │ Platform APIs    │
        │ (OAuth tokens,  │        │ (LinkedIn, X,    │
        │  posts, logs)   │        │  FB, IG)         │
        └─────────────────┘        └──────────────────┘

Database Schema ​

UserSocialAccount ​

Stores OAuth credentials and connection details for each platform.

prisma
model UserSocialAccount {
  id           String   @id @default(uuid())
  userId       String
  platform     Platform  // LINKEDIN, TWITTER, INSTAGRAM, FACEBOOK
  profileType  String   @default("personal") // "personal" or "business"

  accessToken  String   @db.Text  // Encrypted
  refreshToken String?  @db.Text  // Encrypted
  expiresAt    DateTime?

  scopes       String[]  // Granted OAuth scopes
  metadata     Json?     // Platform-specific data

  isActive     Boolean  @default(true)
  lastUsedAt   DateTime?
  createdAt    DateTime @default(now())
  updatedAt    DateTime @updatedAt

  posts        CompanyPost[]

  @@unique([userId, platform, profileType])
}

CompanyPost ​

Stores social media posts with publish tracking.

prisma
model CompanyPost {
  id              String   @id @default(uuid())
  companyId       String
  userId          String
  platform        String
  content         String   @db.Text

  published       Boolean  @default(false)
  remoteId        String?  // Platform's post ID
  remoteUrl       String?  // Public URL
  publishedAt     DateTime?

  socialAccountId String?
  socialAccount   UserSocialAccount? @relation(...)

  createdAt       DateTime @default(now())
  updatedAt       DateTime @updatedAt
}

Features ​

OAuth Authentication ​

Each platform requires specific OAuth scopes:

PlatformRequired Scopes
LinkedInw_member_social, r_liteprofile
Twittertweet.write, users.read
Instagraminstagram_basic, instagram_content_publish
Facebookpages_manage_posts, pages_read_engagement

Flow:

  1. User clicks "Connect [Platform]"
  2. Redirect to platform OAuth page
  3. User grants permissions
  4. Platform redirects to callback URL with auth code
  5. Exchange code for access/refresh tokens
  6. Store encrypted tokens in database

Token Management ​

Automatic Token Refresh:

  • Background worker checks token expiration every 6 hours
  • Refreshes tokens within 7 days of expiration
  • Logs refresh attempts and failures
  • Notifies user if manual re-authentication required

Security:

  • Tokens encrypted at rest using AES-256
  • Decrypted in-memory only for API calls
  • Never logged or exposed in responses

Post Creation & Publishing ​

Direct Publishing:

User creates post → Validate content → Call platform API → Store result

Scheduled Publishing:

User schedules post → Create ScheduledPost → Cloud Tasks triggers at time → Publish → Update status

Media Handling:

  • Images uploaded to platform's media library
  • Videos uploaded with platform-specific requirements
  • Media validated for format, size, dimensions

Error Handling ​

Standardized error responses across all platforms:

typescript
interface PlatformError {
  code: string;            // RATE_LIMITED, AUTH_FAILURE, etc.
  message: string;         // User-friendly message
  retryable: boolean;      // Should auto-retry?
  requiresUserAction?: boolean;  // Needs re-auth/config?
}

Retry Strategy:

  • Transient errors (rate limit, timeout): Exponential backoff
  • Permanent errors (invalid auth, scope issues): Notify user, don't retry
  • Max retries: 3 attempts per post per platform

API Reference ​

POST /api/social/posts ​

Create and publish a social media post.

Request:

json
{
  "content": "Check out our latest blog post!",
  "platforms": ["linkedin", "twitter"],
  "mediaUrls": ["https://cdn.example.com/image.png"],
  "scheduledAt": "2025-12-01T10:00:00Z" // Optional
}

Response:

json
{
  "posts": [
    {
      "platform": "linkedin",
      "status": "published",
      "remoteId": "urn:li:share:...",
      "remoteUrl": "https://linkedin.com/feed/update/..."
    },
    {
      "platform": "twitter",
      "status": "published",
      "remoteId": "1234567890",
      "remoteUrl": "https://twitter.com/user/status/1234567890"
    }
  ]
}

GET /api/social/accounts ​

List all connected social accounts.

Response:

json
{
  "accounts": [
    {
      "id": "uuid",
      "platform": "linkedin",
      "profileType": "personal",
      "isActive": true,
      "lastUsedAt": "2025-11-28T12:00:00Z"
    }
  ]
}

DELETE /api/social/accounts/ ​

Disconnect a social account.

Response:

json
{
  "success": true
}

Analytics Integration ​

Social post metrics are stored in the unified CompanyContentMetrics model, enabling cross-platform comparison and trend analysis.

Tracked Metrics:

  • Impressions
  • Reach
  • Engagement (likes, comments, shares)
  • Clicks
  • Engagement rate

Sync Schedule:

  • New posts (<24h): Every 2 hours
  • Active posts (1-7 days): Every 6 hours
  • Older posts (7-30 days): Daily
  • Archive (>30 days): Weekly

See Analytics Foundation for details.

Future Enhancements ​

Tracked issue: #211

Phase 2:

  • Advanced media handling (video transcoding, carousel posts)
  • Platform-specific analytics (beyond basic metrics)

Phase 3 (Under Consideration):

  • Multi-image carousel posts
  • Thread/story support
  • A/B testing
  • Best time to post recommendations

TendSocial Documentation