# Sveltia CMS configuration for Weekly American.
# Field rules MUST match src/content/schemas.ts; `npm test` fails on drift.
backend:
  name: github
  repo: jkhan-elevate/weekly-american
  branch: main
  # Sign-in is a Weekly American username/password form (cms-auth worker), not GitHub OAuth.
  # The worker also proxies the GitHub API with a GitHub App token, so editors need no GitHub account.
  # It is served on our own domain: the site Worker forwards /cms-auth/* to it (service binding).
  base_url: https://weeklyamerican.org/cms-auth
  api_root: https://weeklyamerican.org/cms-auth/github/api/v3
  graphql_api_root: https://weeklyamerican.org/cms-auth/github/api/graphql
  auth_methods: [oauth] # hide "Sign In Using Access Token"
  squash_merges: true
  commit_messages:
    create: 'content({{collection}}): create "{{slug}}"'
    update: 'content({{collection}}): update "{{slug}}"'
    delete: 'content({{collection}}): delete "{{slug}}"'
    uploadMedia: 'media: upload "{{path}}"'
    deleteMedia: 'media: delete "{{path}}"'

# Draft -> In Review -> Ready -> Publish, one pull request per entry.
# Drafts must be complete so a draft PR never fails the build.
publish_mode:
  type: editorial_workflow
  stages: [draft, pending_review, pending_publish]
  direct_publish: false
  allow_incomplete_drafts: false

# Empty optional fields (e.g. Updated date) are omitted instead of written as '',
# which Astro's date/image schema rejects.
output:
  omit_empty_optional_fields: true

app_title: Weekly American CMS
logo:
  # Full Weekly American wordmark (same artwork as the sign-in popup; 2x file for sharp rendering).
  src: /brand/logo-header-1040.webp
  # The app-bar slot is a 24px square, too small for the wordmark.
  show_in_header: false
site_url: https://weeklyamerican.org
display_url: https://weeklyamerican.org

# Article web addresses (and draft branch names) are built from the headline.
# ascii encoding turns punctuation such as "." into "-", so a headline ending in a
# period no longer produces an invalid git branch name ("...zone.").
slug:
  encoding: ascii
  clean_accents: true
  sanitize_replacement: '-'

# Inline images in article bodies.
media_folder: public/uploads
public_folder: /uploads

collections:
  - name: articles
    label: Articles
    label_singular: Article
    description: Opinion and analysis pieces. Saving opens a draft for review; nothing goes live until it is published.
    folder: src/content/articles
    extension: md
    format: frontmatter
    create: true
    slug: '{{slug}}'
    slug_length: 80
    identifier_field: title
    summary: '{{title}} ({{section}}, {{published | date("YYYY-MM-DD")}})'
    sortable_fields: [published, title, section]
    preview_path: 'articles/{{slug}}/'
    # Hero images live next to the Astro image pipeline (src/assets/heroes).
    # media_folder must be repo-absolute (leading /): Sveltia's publish check only
    # recognises files in an entry-relative folder ("../..") when they sit inside
    # the collection folder, so a relative value made every hero upload look like
    # an unknown change and blocked Publish. public_folder stays relative because
    # Astro's image() resolves the stored path from the article file.
    media_folder: /src/assets/heroes
    public_folder: ../../assets/heroes
    fields:
      - { name: title, label: Headline, widget: string, required: true, maxlength: 120 }
      - { name: summary, label: Dek / summary, widget: text, required: true, maxlength: 280, hint: 'One or two sentences shown under the headline and in share previews.' }
      - name: section
        label: Section
        widget: select
        required: true
        options:
          - { label: Politics, value: politics }
          - { label: Economy, value: economy }
          - { label: Foreign Affairs, value: foreign-affairs }
          - { label: Tech, value: tech }
          - { label: Opinion, value: opinion }
      - name: kind
        label: Article type (not shown on the site)
        hint: 'Only tells search engines whether this is an opinion piece. The site shows just the section label.'
        widget: select
        required: false
        default: opinion
        options:
          - { label: Opinion (signed argument), value: opinion }
          - { label: Analysis (explanatory), value: analysis }
      - { name: author, label: Author, widget: relation, required: true, collection: authors, value_field: '{{slug}}', search_fields: [name], display_fields: [name] }
      - { name: published, label: Publish date, widget: datetime, required: true, input_timezone: America/New_York, output_utc: false }
      - { name: updated, label: Updated date, widget: datetime, required: false, input_timezone: America/New_York, output_utc: false }
      - { name: tags, label: Tags, widget: list, required: false, default: [] }
      - { name: hero, label: Hero image, widget: image, required: false, hint: 'Use only photos you have the rights to. 1600x900 or larger.' }
      - { name: heroAlt, label: Hero image description (alt text), widget: string, required: false, maxlength: 200, hint: 'Describe the photo for screen readers. Required in practice whenever there is a hero image.' }
      - { name: heroCredit, label: Hero image credit, widget: string, required: false }
      - { name: heroFit, label: Hero display, widget: select, options: [{ label: 'Crop to 16:9 (default)', value: cover }, { label: 'Show full image (text in image)', value: full }], required: false }
      - { name: lead, label: Front-page lead story, widget: boolean, required: false, default: false }
      - { name: featured, label: Feature on front page, widget: boolean, required: false, default: false, hint: 'Shows this story in the front-page carousel (up to 5 stories). With fewer than 3 featured, the newest stories fill the rest.' }
      - { name: featured_order, label: Front-page order, widget: number, value_type: int, min: 1, max: 99, required: false, hint: 'Optional. 1 shows first. Featured stories without a number follow, newest first.' }
      - { name: draft, label: Hide from site, widget: boolean, required: false, default: false }
      - name: corrections
        label: Corrections
        widget: list
        required: false
        default: []
        fields:
          - { name: date, label: Date, widget: datetime, required: true, input_timezone: America/New_York, output_utc: false }
          - { name: note, label: What was corrected, widget: text, required: true }
      - { name: body, label: Body, widget: markdown, required: true, hint: 'Photo captions: when you insert an image, type the caption in the Title box. It shows under the photo. Use the Alt text box to describe the photo for screen readers.' }

  - name: authors
    label: Writers
    label_singular: Writer
    folder: src/content/authors
    extension: json
    format: json
    create: true
    identifier_field: name
    slug: '{{name}}'
    publish_mode: simple   # writer profiles commit straight to main
    fields:
      - { name: name, label: Name, widget: string, required: true }
      - { name: role, label: Role, widget: string, required: true }
      - { name: bio, label: Bio, widget: text, required: true, maxlength: 600 }
