diff --git a/.replit b/.replit index 04050d4..e1a1709 100644 --- a/.replit +++ b/.replit @@ -47,7 +47,7 @@ localPort = 43245 externalPort = 3001 [[ports]] -localPort = 45149 +localPort = 44509 externalPort = 8000 [[ports]] diff --git a/client/src/pages/new-post.tsx b/client/src/pages/new-post.tsx index 35f2d7e..9b3b4db 100644 --- a/client/src/pages/new-post.tsx +++ b/client/src/pages/new-post.tsx @@ -268,7 +268,7 @@ export default function NewPost() { createPostMutation.mutate({ content: postText, - scheduledFor: scheduledDate || undefined, + scheduledFor: scheduledDate ? new Date(scheduledDate).toISOString() : undefined, mediaIds: selectedMedia.length > 0 ? selectedMedia : undefined, pageIds: selectedPages, postType, diff --git a/replit.md b/replit.md index d067604..f37ed4c 100644 --- a/replit.md +++ b/replit.md @@ -24,12 +24,16 @@ The backend runs on **Node.js** with **Express.js**, fully implemented in **Type ### Media Processing Pipeline -The platform leverages **Cloudinary** for cloud-based image and video storage and transformation. Original files are uploaded to Cloudinary, which then automatically generates transformation URLs for various platform-specific formats: -- **Facebook Feed**: 1080x1080px with intelligent center crop (`crop: fill`) - square format, no borders -- **Instagram Feed**: 1080x1080px with padding (`crop: pad`) - maintains aspect ratio with auto background +The platform leverages **Cloudinary** for cloud-based image and video storage and transformation. Original files are uploaded to Cloudinary and stored in the database. + +**Publishing Strategy**: All publications to Facebook/Instagram use the **original image URL** - the platforms handle cropping and formatting automatically based on the post type (feed/story/carousel). + +**Transformations for Preview Only**: Cloudinary generates transformation URLs for UI preview purposes only: +- **Facebook Landscape**: 1200x630px with intelligent center crop (`crop: fill`) - landscape format +- **Facebook Feed / Instagram Feed**: 1080x1080px with intelligent center crop (`crop: fill`) - square format - **Instagram Story**: 1080x1920px with padding (`crop: pad`) - vertical format -These public IDs and transformation URLs are stored in the database, allowing optimized images to be served via Cloudinary's CDN. +These transformation URLs are stored in the database (`facebookLandscapeUrl`, `facebookFeedUrl`, `instagramFeedUrl`, `instagramStoryUrl`) and displayed in the media library for visual preview, but are NOT used when publishing to social media platforms. ### Authentication & Authorization diff --git a/server/services/facebook.ts b/server/services/facebook.ts index 8980d77..b5ed12f 100644 --- a/server/services/facebook.ts +++ b/server/services/facebook.ts @@ -88,8 +88,8 @@ export class FacebookService { } private async publishPhotoPost(post: Post, page: SocialPage, media: Media): Promise { - // Use the Facebook Feed optimized URL (1200x630) - const photoUrl = media.facebookFeedUrl || media.originalUrl; + // Use original URL - Facebook handles the cropping + const photoUrl = media.originalUrl; const params = new URLSearchParams({ access_token: page.accessToken!, @@ -128,7 +128,8 @@ export class FacebookService { const photoIds: string[] = []; for (const media of imageMedia) { - const photoUrl = media.facebookFeedUrl || media.originalUrl; + // Use original URL - Facebook handles the cropping for carousel + const photoUrl = media.originalUrl; if (!photoUrl) { console.warn(`Skipping media ${media.id} - no valid URL found`); @@ -242,7 +243,8 @@ export class FacebookService { } private async schedulePhotoPost(post: Post, page: SocialPage, scheduledTimestamp: number, media: Media): Promise { - const photoUrl = media.facebookFeedUrl || media.originalUrl; + // Use original URL - Facebook handles the cropping + const photoUrl = media.originalUrl; const params = new URLSearchParams({ access_token: page.accessToken!, @@ -268,8 +270,8 @@ export class FacebookService { } private async publishStory(post: Post, page: SocialPage, media: Media): Promise { - // Use vertical format for stories (Instagram Story URL 1080x1920) - const photoUrl = media.instagramStoryUrl || media.originalUrl; + // Use original URL - Facebook handles the story cropping + const photoUrl = media.originalUrl; const params = new URLSearchParams({ access_token: page.accessToken!, diff --git a/shared/schema.ts b/shared/schema.ts index 2cb6af9..06a6532 100644 --- a/shared/schema.ts +++ b/shared/schema.ts @@ -55,6 +55,7 @@ export const media = pgTable("media", { type: mediaTypeEnum("type").notNull(), cloudinaryPublicId: text("cloudinary_public_id"), originalUrl: text("original_url").notNull(), + facebookLandscapeUrl: text("facebook_landscape_url"), facebookFeedUrl: text("facebook_feed_url"), instagramFeedUrl: text("instagram_feed_url"), instagramStoryUrl: text("instagram_story_url"),