feat: content strategy, image posts and a posting plan for the films
Adds twelve image posts made the same way as the films: six posters (one picture of each film with its idea in two lines) and six cards that answer a question clients ask before the first call. The answers come from the questions and principles on the website. The posting plan is data (six weeks, film, card and poster per week), and the export writes the library in that order, by language, week and day, with the text to post. All video posts now open with the hook of their film. The reasoning is in plans/content-strategy.md. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+24
-17
@@ -1,27 +1,18 @@
|
||||
import type { FC } from "react";
|
||||
import { Composition } from "remotion";
|
||||
import { FORMATS, FPS, type FormatName } from "./brand/tokens";
|
||||
import { appRescue } from "./compositions/AppRescue";
|
||||
import { automationDocuments } from "./compositions/AutomationDocuments";
|
||||
import { automationEnquiry } from "./compositions/AutomationEnquiry";
|
||||
import { automationOrder } from "./compositions/AutomationOrder";
|
||||
import { productDeveloper } from "./compositions/ProductDeveloper";
|
||||
import { websiteDone } from "./compositions/WebsiteDone";
|
||||
import { IMAGES, IMAGE_IDS } from "./content/images";
|
||||
import { LANGS } from "./content/videos";
|
||||
import { ServiceVideo, videoDuration, type VideoEntry } from "./slides/ServiceVideo";
|
||||
|
||||
/** Register new videos here. Each one is offered as `<id>-<language>-<format>`. */
|
||||
const VIDEOS: readonly VideoEntry[] = [
|
||||
automationOrder,
|
||||
automationDocuments,
|
||||
automationEnquiry,
|
||||
websiteDone,
|
||||
appRescue,
|
||||
productDeveloper,
|
||||
];
|
||||
import { ImagePost } from "./images/ImagePost";
|
||||
import { VIDEOS } from "./registry";
|
||||
import { SHOT_FRAMES } from "./films/shot";
|
||||
import { ServiceVideo, videoDuration } from "./slides/ServiceVideo";
|
||||
|
||||
const FORMAT_NAMES = Object.keys(FORMATS) as FormatName[];
|
||||
/** Images are posted in the feed: 4:5, and square for places that crop. */
|
||||
const IMAGE_FORMATS = ["feed", "square"] as const;
|
||||
|
||||
/** Videos are `<VideoId>-<language>-<format>`, images `<ImageId>-<language>-<feed|square>`. */
|
||||
export const Root: FC = () => (
|
||||
<>
|
||||
{VIDEOS.flatMap((video) =>
|
||||
@@ -39,5 +30,21 @@ export const Root: FC = () => (
|
||||
)),
|
||||
),
|
||||
)}
|
||||
{IMAGE_IDS.flatMap((id) =>
|
||||
LANGS.flatMap((lang) =>
|
||||
IMAGE_FORMATS.map((format) => (
|
||||
// A poster is a film at one of its frames, so it needs the film's length; a card is a single frame.
|
||||
<Composition
|
||||
key={`${id}-${lang}-${format}`}
|
||||
id={`${id}-${lang}-${format}`}
|
||||
component={() => <ImagePost id={id} lang={lang} />}
|
||||
durationInFrames={IMAGES[id].poster ? SHOT_FRAMES : 1}
|
||||
fps={FPS}
|
||||
width={FORMATS[format].width}
|
||||
height={FORMATS[format].height}
|
||||
/>
|
||||
)),
|
||||
),
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user