Status: π Reference Document Last Updated: November 28, 2025
Overview β
This document tracks the evolution of TendSocial's database schema as new features are implemented. It serves as a reference for understanding how different features integrate at the database level.
Schema Evolution Strategy β
TendSocial uses a unified schema approach where new features extend existing models rather than creating parallel structures. This prevents data fragmentation and enables cross-feature queries (e.g., analytics across all content types).
Core Principles β
- Polymorphic References - Content-agnostic models use
contentType+contentIdinstead of separate tables per type - Unified Metrics - All analytics use
CompanyContentMetricsmodel regardless of source (social, blog, video) - Asset Centralization - All media (images, videos, docs) stored in
CompanyAssetmodel - Multi-Tenancy - All tables scoped by
companyIdwith proper indexes
Major Schema Additions β
November 2025 - Social Media Integration & Analytics Foundation β
New Models:
UserSocialAccount- OAuth credentials for social platformsCompanyContentMetrics- Unified analytics for all content typesCompanyMetricsSnapshot- Time-series metrics for trend chartsCompanyAnalyticsConnection- GA4 and third-party analytics connectionsCompanyAnalyticsSyncJob- Background sync job tracking
Enhanced Models:
CompanyPost- AddedremoteId,remoteUrl,socialAccountId,publishedAtCompany- Added relations to new modelsUser- Added social post creation tracking
Migration: 20251128045023_schema_enhancements_and_super_admin
Key Features Enabled:
- Multi-platform social publishing
- Automatic token refresh
- Unified analytics dashboard
- Cross-platform performance comparison
Planned - Asset Library (Q3 2025) β
New Models:
CompanyAsset- Centralized media storageCompanyAssetFolder- Hierarchical organizationCompanyAssetTag- Categorization systemCompanyAssetUsage- Track where assets are usedPlatformAsset- Track uploads to destination platforms
Enhanced Models:
CompanyBlogPost- Link to cover image assetCompanyVideoScript- Link to thumbnail assetCompanyPost- Reference media assets
Features Enabled:
- Duplicate detection (content hashing)
- AI Vision auto-tagging
- Asset lineage tracking (regenerated images)
- Storage quota management
- Multi-platform asset tracking
Planned - Blog Publishing (Q2 2025) β
New Models:
CompanyBlogDestination- WordPress, Ghost, 11ty connectionsCompanyBlogPublishLog- Audit trail per destinationRemotePostRef- Track remote post IDs and URLs
Enhanced Models:
CompanyBlogPost- Add destination configurationCompanyAsset- Platform-specific upload tracking
Features Enabled:
- Multi-destination publishing
- Git-based publishing (11ty, Astro)
- Image upload to platform asset stores
- Canonical URL management
Model Relationships β
Content β Metrics Flow β
CompanyBlogPost βββ
ββββΊ CompanyContentMetrics βββΊ CompanyMetricsSnapshot
CompanyPost βββββββ€ (polymorphic) (time-series)
β
CompanyVideoScriptβ
β²
β
ββββ CompanyAnalyticsSyncJob (updates metrics)Asset β Content Flow β
CompanyAsset βββ
ββββΊ CompanyAssetUsage βββΊ CompanyBlogPost
β CompanyPost
β CompanyVideoScript
β
ββββΊ PlatformAsset (WordPress, LinkedIn, etc.)
(tracks where uploaded)Social Publishing Flow β
User βββΊ UserSocialAccount βββΊ CompanyPost βββΊ CompanyContentMetrics
(OAuth tokens) (published) (analytics)Schema Design Patterns β
1. Polymorphic References β
Instead of:
model BlogMetrics { blogPostId String }
model SocialMetrics { postId String }We use:
model CompanyContentMetrics {
contentType ContentType // BLOG_POST, SOCIAL_POST, VIDEO_SCRIPT
contentId String // ID of any content type
}Benefits:
- Single query for all content analytics
- Unified dashboard code
- Easier to add new content types
2. Multi-Destination Tracking β
Content published to multiple platforms uses destinationKey to differentiate:
model CompanyContentMetrics {
contentType ContentType
contentId String
platform String // "wordpress", "linkedin"
destinationKey String? // "vulpine-wp", "personal-linkedin"
@@unique([contentType, contentId, platform, destinationKey])
}Example: A blog post published to WordPress and Ghost = 2 CompanyContentMetrics records.
3. Encrypted Sensitive Data β
OAuth tokens and API keys encrypted at rest:
model UserSocialAccount {
accessToken String @db.Text // Encrypted before storage
refreshToken String? @db.Text // Encrypted before storage
}Encryption handled in application layer (AES-256).
4. Cascading Deletes β
Proper cleanup on deletion:
model CompanyAsset {
companyId String
company Company @relation(fields: [companyId], references: [id], onDelete: Cascade)
}When a company is deleted, all assets, posts, metrics are automatically deleted.
Index Strategy β
Indexes optimized for common query patterns:
| Query Pattern | Index |
|---|---|
| List company's assets | @@index([companyId]) |
| Get post metrics | @@index([contentType, contentId]) |
| Find stale metrics | @@index([lastSyncedAt]) |
| Filter by platform | @@index([platform]) |
| Social account lookup | @@unique([userId, platform, profileType]) |
Migration Best Practices β
Adding New Fields β
- Make new fields nullable initially
- Backfill data if needed
- Make required after data populated
Adding New Tables β
- Create table with indexes
- Set up foreign keys with proper
onDeletebehavior - Update seed data
- Generate new Prisma client
Deprecating Models β
- Create migration path (e.g.,
SocialAnalyticsβCompanyContentMetrics) - Run data migration script
- Verify data integrity
- Drop old table in separate migration
Data Retention β
| Model | Retention Policy |
|---|---|
| CompanyPost, CompanyBlogPost, CompanyVideoScript | Indefinite (user content) |
| CompanyContentMetrics | Current state always kept |
| CompanyMetricsSnapshot | 18 months minimum |
| CompanyAsset | Until deleted by user or archived |
| CompanyAnalyticsSyncJob | 30 days (rolling cleanup) |
| UserSocialAccount | Until user disconnects |
Future Considerations β
Potential Additions β
- Content Versioning - Track revisions of blog posts and scripts
- A/B Testing - Store test variants and results
- Team Collaboration - Comments, approvals, assignments
- Workflow States - Draft β Review β Approved β Published
- Content Templates - Reusable post/blog templates
Scaling Considerations β
- Partitioning MetricsSnapshot - By date range for faster queries
- Archiving old AnalyticsSyncJob records - Move to cold storage after 30 days
- Caching frequently accessed data - Popular posts, account settings
- Read replicas - For analytics dashboards
Related Documentation β
Source Documents β
This document synthesizes information from:
docs/planning/Schema_Evolution_Plan.mddocs/planning/schema-enhancements.mddocs/planning/social-media-integration-plan.mddocs/planning/Analytics_Foundation.md