# Sanity Document Publishing

## Objective

Publish app content into Sanity as valid documents and assets, respecting draft workflows.

A publishing path that creates and updates Sanity documents and their assets from app records, honouring the target schema and draft pairing.

## Before You Begin

This feature is being added to an application that already exists and already
works. Do not scaffold a new project, and do not assume a blank slate.

Inspect the codebase first and establish:

- The existing application structure and where code of this kind already lives.
- The framework and version in use.
- The existing design system — colours, spacing, typography, and component conventions.
- Existing UI components you can reuse instead of writing new ones.
- The existing database structure, if this feature needs to persist anything.
- The existing authentication and authorization system, if this feature is user-scoped.
- Dependencies already installed, so you don't add a library that duplicates one.
- The existing test setup and conventions.

Only start writing code once you understand the above. If the application
already implements part of this feature, extend it rather than replacing it.

## Implementation Instructions

1. Derive each document's identifier deterministically from the app record it represents, so a retried or repeated publish updates the same document rather than scattering near-identical copies through the dataset.
2. Read the target schema and validate the payload against it before sending, rejecting the write locally with a readable error rather than discovering the mismatch as a rejected mutation in a background job.
3. Upload every image and file asset first, wait for the asset to be usable, and only then write the document that references it.
4. Handle the draft and published pair explicitly: decide whether the app writes drafts for a human to publish or publishes directly, prefer writing drafts, and never let a routine sync publish something an editor deliberately left in draft.
5. Do not pass user-authored rich text or references straight through into the document body. Constrain it to the block types, marks, and reference targets the schema allows, because an unconstrained body is a way for one user's input to reach every reader of the published site.

## UI and UX Requirements

Match the application's existing design system exactly. Reuse its components,
spacing, and typography. This feature should look like it was always there.

## Responsive Requirements

Works on mobile, tablet, and desktop. Touch targets are large enough to hit on a
phone, and nothing overflows horizontally at 320px.

## Accessibility Requirements

- Fully keyboard navigable.
- Correct semantic elements and ARIA roles.
- Visible focus states.
- Meets WCAG AA contrast.
- Dynamic changes are announced to screen readers.
- Respects prefers-reduced-motion.

## Edge Cases

- Identifiers must be stable and derived from the source record. Letting the destination assign one, or generating a fresh one per run, produces silent duplicates that are only noticed once the site shows the same item twice.
- A payload that does not match the schema will be rejected wholesale. Validate before sending so the failure is attributable to a named field rather than an opaque mutation error.
- Assets are processed asynchronously. A document written immediately after an upload can reference an asset that is not yet ready, producing a broken image on a page that was reported as published successfully.
- Draft and published documents exist as a pair. Writing to the wrong half either publishes unreviewed content or leaves the app's changes invisible on the live site with nothing to indicate why.
- Portable text and reference fields must be constrained to what the schema permits. Arbitrary block types or references pointing at unexpected documents will either fail validation or render as something nobody designed.
- Multiple mutations belonging to one logical publish should be sent as a single transaction where the destination allows it, so a failure part way through does not leave a document referencing assets that were never linked.
- Rate limits and outages need bounded retries with backoff, and a publish that could not be delivered must be visible in the app as pending rather than reported as done.
- The stored token can be revoked at any time. Distinguish an authentication failure from a transient error, stop retrying, and prompt an operator to reconnect.

## Testing

Exercise the feature end to end in the running application. Cover every edge case
above, then run the existing test suite and confirm nothing regressed.

## Acceptance Criteria

- [ ] Document identifiers are deterministic, so repeat publishes update rather than duplicate.
- [ ] Payloads are validated against the target schema before any write is attempted.
- [ ] Assets are uploaded and confirmed usable before the documents that reference them are written.
- [ ] Draft and published documents are handled as a pair, with the app defaulting to writing drafts.
- [ ] User-supplied rich text and references cannot introduce structures the schema does not allow.
- [ ] A failed publish leaves no half-written document and is shown in the app as pending, not complete.
- [ ] A revoked token stops retries and surfaces a reconnect prompt.
- [ ] The feature matches the existing design system.
- [ ] No existing functionality is broken.

## Adaptation Rules

- Match the existing design system. Do not introduce a new colour palette,
  spacing scale, or component library.
- Reuse existing components and utilities wherever they fit.
- Follow the naming, file layout, and code style already present.
- Do not upgrade, replace, or remove existing dependencies to make this
  feature fit. Adapt the feature to the app, not the app to the feature.
- Do not break existing functionality. If a change is genuinely required in
  existing code, make the smallest one that works and say so.
- If something in these instructions conflicts with how the application is
  built, follow the application and explain the deviation.

## Final Verification

Before you report the work as done:

1. Re-read the acceptance criteria above and check each one against what you
   actually built.
2. Run the application and exercise the feature end to end.
3. Run the existing test suite and confirm you have broken nothing.
4. Check the feature on mobile, tablet, and desktop widths.
5. Check keyboard navigation and focus handling.
6. Summarize what changed: files added, files modified, and anything you
   deliberately did differently because of how this application is built.

If any acceptance criterion is unmet, fix it before reporting completion.
