← back to Dw Launches

README.md

82 lines

# DW Launches — Multi-Channel Social Composer

Designer Wallcoverings' own social "launches" workspace, modeled on Postiz `/launches`.
A **local build tool** — no real OAuth, no live publish, no deploy.

## Run

```sh
cd ~/Projects/dw-launches
npm install        # express only
npm start          # → http://127.0.0.1:9764
```

`PORT=9764` by default; override with `PORT=xxxx npm start`.

## What it does

A full **command center** (CNCP-style chrome): a persistent top bar with the
serif Designer Wallcoverings wordmark + a **view switcher**, and six working
sections. Compose one post, fan it across 7 DW channels (Instagram, Facebook,
LinkedIn, Pinterest, TikTok, X/Twitter, YouTube), override per-channel
copy/media/fields, preview each platform live, schedule with a staggered
cadence, view a calendar, watch a Hootsuite-style streams board, work an
approvals queue, and route everything through the sign-off gate.

### The views (toggle in the top-bar switcher; choice persists in localStorage)

- **Dashboard** — overview landing: scheduled-today / pending-approval /
  published-this-week / approved / drafts / total counts + a per-channel tile grid.
- **Compose** — the original single-pane composer (unchanged).
- **Streams** — Hootsuite-style board: one column per channel, each a vertical
  stream segmented **Scheduled → Pending approval → Published → Drafts**. A
  **density slider** above it drives `--cols` (2–7 columns); value persists.
- **Calendar** — month grid of scheduled per-channel slots, color-coded.
- **Drafts & Queue** — card grid of every launch; a density slider drives card
  width (`--chanmin`); each card shows created date+time; click to open as a modal.
- **Approvals** — queue of pending-sign-off + approved-awaiting-publish, with
  inline sign-off (STEVE-GO) and simulated publish.

### Movable / resizable modals (modal-rig)

Clicking a launch card (Drafts or Streams) or "Open" in Approvals opens it as a
**modal-rig** panel: drag by the header, `resize:both` corner handle, `⤢`
maximize, collapsible "Per-channel" section, closes on backdrop/×/Esc — position,
size and section state all persisted to `localStorage`. Drop-in is
`public/modal-rig.js` (served statically, loaded via `<script src>`).

### The 9 Compose components
1. **Channel rail** — avatar chips, toggle targets; YouTube renders greyed with a `connect` stub.
2. **Global editor** — master title + body + media inherited by selected channels.
3. **Per-channel tabs** — unlock at 2+ channels; override copy/media/schedule.
4. **Media attach** — drag-drop / file pick / URL ref (image · carousel · video).
5. **Live preview** — per-platform mock: IG square, X 280 thread w/ counter, Pinterest tall pin, YouTube title+thumb.
6. **Platform fields** — IG first comment, YouTube title+thumbnail, Pinterest board+destination link, X thread split.
7. **Scheduling** — Post now / Schedule / Add to queue (preset PT slots) / Draft.
8. **Calendar** — month grid of every scheduled per-channel slot, color-coded by channel.
9. **State & approval** — Save draft → Submit for approval → **Steve sign-off** → publish (gated stub).

## Hard rules enforced

- **"Wallpaper" is banned** — server returns 422 on any saved copy containing it.
- **Publish is gated** — `/publish` returns 403 unless the approval flag is set,
  which requires the `STEVE-GO` sign-off token. Even then the publish is a
  **simulation only** — no live social API is ever called.

## Storage

`data/launches.json` (gitignored is NOT applied — it's a seed artifact; the
pristine seed lives in `data/seed-launches.json` and is copied on first boot).

## Seed content

`Trending Wallcoverings Collection 2026 — Weekly Arrivals`, all 7 channels,
staggered same-day PT cadence: 9:00 IG · 10:30 Pinterest · 12:00 LinkedIn ·
1:30 FB · 4:00 X · 6:00 TikTok · 7:30 YouTube. Status `pending_approval`.

## Stubs needing Steve's go

- Live publish (currently simulated behind the approval flag)
- Real OAuth / channel connections (all faked; YouTube shown unconnected)
- Deploy to Kamatera (intentionally not done — local tool)