Current state, 26/09/2026 (read first).
- Cadence halved, AL 26/09/2026 (translated: "we must halve the number of EO posts per day, on every planner"), for every new scheduling, posts already scheduled kept as they are: the day counters use the halved values from Sunday 27/09/2026 and the former ones before (Rules).
- Every date on this page reads Vietnam time (Asia/Ho_Chi_Minh, +07:00); since 22/09/2026 nothing stays on Paris time, Pinterest included (AL).
- V16: 50 shorts posted or scheduled until 27/09/2026, after 19 duplicates were pulled. D1 content_posts still held the 69 V16 short rows on 25/09/2026 (40 posted, 29 scheduled, none deleted), so the planning mode still draws the 19 pulled ones.
- The V16 rows exist in content_posts since the evening of 20/09/2026: the V16 preview mode, meant to disappear on that day, is still on the page.
Rules and mutable values.
- This page is a read-only mirror of D1 content_posts through GET /api/content-posts, the same source as the publication tracker. It posts nothing, schedules nothing, never calls PostFast, never writes to Notion and never writes to D1.
- Four phones, one per platform: Instagram profile grid (3 columns, 4:5), TikTok full screen vertical feed, Facebook page feed, YouTube with a Shorts tab and a Videos tab. One week at a time, from ?from=YYYY-MM-DD (default: Monday of the current Vietnam week), arrows move it by seven days.
- A row appears only when it carries a date. Rows of content_posts with an empty date are counted in the banner and shown nowhere. Content that exists as a file but was never filed in a planner is not in content_posts at all, so it is invisible here by construction: the banner says so.
- Day counters compare the posts shown that day with the cadence of that day. Up to 26/09/2026: the cadence set by AL on 17/09/2026, YouTube 3 a day, TikTok 3, Instagram 2 reels plus cards, Facebook 2. From Sunday 27/09/2026 (first day of week A): the cadence halved by AL on 26/09/2026, YouTube and TikTok 2 then 1 on alternate days (2 on 27/09/2026, then 1, then 2...), Instagram 1 reel a day plus cards, Facebook 1. The column head gives the week total of those day values. The counter counts every row shown for that platform that day, cards included; hover a counter for the codes.
- Status filter: posted, scheduled and planned are on by default. Backup (a spare, retired as a planner status on 18/09/2026 but still carried by legacy rows) and invalid (the legacy Q code type, superseded by Q-TT / Q-IG / Q-FB on 17/09/2026) are off by default and one click away. A backup row is not a planned publication, so it does not belong in a feed preview by default.
- Soft-deleted rows are hidden by the API and filtered a second time in the page, like the tracker.
- The manifest /assets/content-system/feed-covers.json carries one entry per file with its edit id, video, platform, ordinal, slug and code. A cover is drawn on a cell only when the manifest gives it the exact content code of that cell, never by position or by ordinal, so a cell never carries another content's image. The codes were paired on 20/09/2026 from the Notion Shorts planner: the planner property Titre is matched to the cover title, exactly, inside the same platform, both coming from the same 05-meta file. Source of the pairs: feed-covers.json.
- The second switch at the top of the page changes the images of both modes, planning and preview; the URL keeps it as ?covers=test. Codes are carried over from feed-covers.json by edit id, so the pairing stays the one made on the exact planner title. The switch only changes which image a cell shows, never which cells exist.
- Rebuild the manifest the same way after any new run; never copy the plan into the counter.
- Second mode, V16 preview (20/09/2026). The mode switch at the top of the page leaves the planning mode untouched. In preview, the four phones are filled from /assets/content-system/feed-v16-preview.json: the 69 covers already rendered for V16, split by their platform (YouTube 21, TikTok 20, Instagram 14, Facebook 14), in edit order, each with its idea code, its title and its short type. It shows the production, not the planning, and it is meant to disappear the day the V16 rows exist in content_posts. The URL keeps it as ?mode=preview.
- Cover image type: under the phones of the preview mode, the share of face / diagram / b-roll per platform and in total, read from cover.stream of the per short meta files; AL aims at 40 / 40 / 20. Rebuild the file by rerunning that measurement, never by hand. The measurement and its method are in History, 20/09/2026.
- Endpoint. GET /api/content-posts, whole table, filtered by week in the browser (748 rows on 20/09/2026, one call per page load). Auth: browser CF Access session, or a service token for a script. Fields used: code_type, n, code, date, platform, status, url, video, deleted_at.
- Status mapping. posted / published / done / live read as posted; scheduled as scheduled; backup / cancelled / canceled as backup; invalid / failed as invalid; anything else (planned, in progress, ready, not started, empty) as planned. Same families as the tracker, with invalid split out of the backup bucket because the legacy Q rows are numerous and are not spares.
- Layout. Four columns above 1180 device pixels, two below, one under 760. Each phone clips its own content and scrolls vertically inside its screen; the page never scrolls sideways at any width. The page keeps the intranet body zoom of 1.25.
- Design. Type B of the Notion page "Data pages design, Type A vs Type B": colours allowed, real visual rendering, vertical scroll allowed. Colours go through the EO tokens only (--c-*, --n-*), never through raw platform brand hexes, like the Shorts planner page does.
History, oldest first. Older decisions, measurements and superseded values, kept verbatim, never deleted. Where a line below disagrees with the current state or the rules above, the current state and the rules win.
20/09/2026, the page is built (reads D1 content_posts, writes nothing); the first current state, kept verbatim:
- Covers: 69 V16 short covers were copied into /assets/content-system/feed-covers/ on 20/09/2026 with AL's go, resized to 405x720 (sips -Z 720), 3.6 MB in total.
- Codes paired, 20/09/2026 evening, 69 of 69. The V16 shorts landed in the Notion Shorts planner and the hourly sync wrote them to D1 (787 rows written, run 14:26 UTC): S-YT3 to S-YT23, S-TT14 to S-TT33, S-IG14 to S-IG27, S-FB6 to S-FB19, dated 21 to 27/09/2026, Notion status Ready which the tracker reads as planned. content_posts carries no title column, so the pairing was made against the planner itself (data source 0bd28224-6571-827b-8a89-07fed5b4cd84, Associated LF = V16, read only): the property Titre matched to the cover title, exactly, inside the same platform, both strings coming from the same 05-meta file. Measured: 69 of 69 paired, zero duplicate title inside a platform on either side, zero cover left over, zero planner row left over, and the planner Short type agreed with the meta Short type on all 69. Nothing was matched by order.
- Test cover set, published and switchable (20/09/2026). The 69 files of V16/B1-shorts/_COVERS-TEST-20-09/{YT,TT,IG,FB}/ are published under /assets/content-system/feed-covers-test/, resized the same way, with the manifest feed-covers-test.json.
- Test set type, measured not read off the plan. choices.json (written 21:33) plans 38 face / 26 diagram / 5 b-roll, which is 55 / 38 / 7, and its covers list names only 3 as built. The folder was finished later, so both are stale. What is actually published was measured file by file: a file whose bytes differ from the delivered cover of the same edit id was rebuilt by the run, and its kind comes from run-used.json (written 23:04, the freshest record): 22 rebuilt files, 18 schema and 4 b-roll, matching the 22 run-used entries one for one; the other 47 files are the delivered face frame, unchanged. So the published test set measures 47 face / 18 diagram / 4 b-roll, that is 68 / 26 / 6, not the 55 / 38 / 7 of the plan: 9 of the 31 planned non-face covers are still faces. Per platform: YouTube 52 / 43 / 5, Facebook 57 / 36 / 7, Instagram 79 / 14 / 7, TikTok 85 / 10 / 5.
- Cover image type, measured not estimated. Under the phones of the preview mode, the share of face / diagram / b-roll per platform and in total, read from cover.stream of the per short meta files V16/B1-shorts/v16-*/05-meta/V16-mNN.json. Measured 20/09/2026 on the 69 published covers: 100 % face on all four platforms, zero diagram, zero b-roll, against the 40 / 40 / 20 AL aims at. Note the distinction the numbers make visible: 17 of those shorts are of short type Schema vertical and 2 are B-roll, yet their cover frame is a face. The build resolves each cover file to the meta that declares its edit_id; 6 edit ids are declared by two or three runs (V16-FB-R13, V16-IG-R03, V16-TT-S14, V16-YT-S07, V16-YT-S16, V16-YT-S21) and were settled by comparing the byte size of the delivered file with the published one, which put all six on the lot runs, not on the temoin runs. The three temoin YouTube covers carrying stream: asset were never published, so they are not counted.
- Known gaps on 20/09/2026, measured: url is empty on every row, so no cell links out; the Long-form planner rows mostly carry no date, so the YouTube Videos tab is empty on most weeks; 197 rows carry no date at all. Content other than shorts (carousels, lifestyle, quotes) has no cover of its own, so those cells show their flat tile: on the week of 21 to 27/09/2026 that is 5 cells on Instagram, 4 on Facebook, 2 on TikTok, 0 on YouTube.
26/09/2026, AL: cadence halved; posts already scheduled kept as they are. (translated: "we must halve the number of EO posts per day, on every planner") What the counters used until that day, kept verbatim: cadence:2 Instagram ("2 reels a day plus cards"), cadence:3 TikTok ("3 a day"), cadence:2 Facebook ("2 a day"), cadence:3 YouTube ("3 shorts a day"), one flat value for every day, and the rule line "Day counters compare the posts shown that day with the cadence set by AL on 17/09/2026: YouTube 3 a day, TikTok 3, Instagram 2 reels plus cards, Facebook 2." Since 26/09/2026 the value depends on the day (cadFor), so a past week still reads against the cadence it was planned under.