# Publishing

The Publish Panel lets you send, schedule, or manually log generated posts from Content Forge and Video Forge. No copy-paste, no leaving the platform.

### Requirements

* A connected account for the target platform; see [Social Connections](/thecontentforge-docs/feature-guides/social-connections.md)
* The profile must be marked as **Publish** on the Social Connections page
* If your org has the **Approval Workflow** enabled, posts route through approval before publishing

Manual logging does not require an active OAuth profile. It records that you already posted the item elsewhere.

### Who can send immediately

* **Owners/Admins** manage the connections and decide which profiles are publishable
* If approval workflow is **off**, any user can publish through an already-connected publishable profile
* If approval workflow is **on**, whether a user can send immediately depends on the configured minimum approver role

### Publish, schedule, or log

After generating in Content Forge or Video Forge:

1. Open the Publish Panel on the output card
2. Pick the platform and connected profile when publishing or scheduling
3. Edit the final text if needed
4. Optionally attach media (images or videos)
5. Choose **Post now**, **Schedule post**, or **Already posted it yourself**
6. Submit

Scheduled posts appear on the [Calendar](/thecontentforge-docs/feature-guides/calendar.md) and publish automatically at the specified time via a background job.

If you post manually outside TheContentForge, the next analytics sync can fetch or match it. You can also log it manually from the Publish Panel after generating in either studio so it appears on the Calendar immediately.

### Media attachments

* Click the attach button below the textarea to pick an image or video
* Uploads run **on submit**, not when you pick the file, so nothing is uploaded unnecessarily
* If a submit fails, the retry reuses the already-uploaded asset; you do not re-upload
* Attached media is stored in a private `assets` bucket with org-scoped access and resolved via signed URLs at publish time
* Ephemeral uploads are cleaned up 24 hours after the post publishes

### Threads (X)

When Content Forge returns an X thread (Thread mode or **Summarize the project**), the Publish Panel switches to a per-tweet editor. Every tweet in the thread is available for all orgs, not just Web3 projects.

* Edit each tweet in place — edits are preserved while the Publish Panel is open and never reverted by background re-renders
* Add or remove tweets with the **+ Add tweet** / trash buttons
* Each tweet has its own media controls:
  * **Attach** — upload an image or video for that specific tweet
  * **Generate** — create a headline image for that tweet via Gemini 3.1 Flash
  * **Brand asset** — (Web3 Project orgs) pick a logo, icon, template, or any asset you marked **Safe for content** in the [Asset Library](/thecontentforge-docs/feature-guides/asset-library.md)
* On submit, the panel inserts one `scheduled_posts` row per tweet, sharing a `thread_group_id` and ordered by `thread_position`
* Publishing chains the replies via the X `reply.in_reply_to_tweet_id` field; if any tweet in the chain fails, later tweets do not publish
* Instagram and Facebook receive a single concatenated post (thread semantics do not apply on those platforms) with the first tweet's media attached

**Platform specifics:**

* **X** - images and video via the v2 media endpoint
* **Facebook** - routes to `/photos` or `/videos` based on media type
* **Instagram** - image and video posts via Meta's graph API

### Approval workflow

When approval is enabled in Settings:

1. A scheduled or publish-now post enters `approval_pending`
2. A user at or above the configured min role (Editor, Admin, or Owner) approves or rejects it from the [Calendar](/thecontentforge-docs/feature-guides/calendar.md)
3. Approved posts move to `queued` and publish at the scheduled time
4. Rejected posts are marked accordingly and do not send

### Failure handling

If a publish attempt fails (platform error, expired token, media rejected), the event's status flips to `failed` and the error message surfaces on the event drawer. Non-fatal warnings, such as a platform caveat after publishing, land in **Publish notes** so they do not get confused with hard errors.

### Related

* [Content Forge](/thecontentforge-docs/feature-guides/content-studio.md) - Where text posts are generated
* [Video Forge](/thecontentforge-docs/feature-guides/video-studio.md) - Where video-derived posts are generated
* [Social Connections](/thecontentforge-docs/feature-guides/social-connections.md) - Connect accounts to publish through
* [Calendar](/thecontentforge-docs/feature-guides/calendar.md) - Track scheduled, pending, manual, and published posts


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://thecontentforge.gitbook.io/thecontentforge-docs/feature-guides/publishing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
