# Repository configuration

Describe a Content Space explicitly with .prosefly/config.yaml when automatic discovery is not enough.

Prosefly discovers supported framework configuration automatically during a repository scan. Most Astro, Starlight, Fumadocs, Lotus, and Dahlia sites do not need another configuration file.

Use `.prosefly/config.yaml` when your repository uses a custom loader, a monorepo layout, generated configuration, or another structure that cannot be identified safely from static files. The file is committed with your repository and becomes the source of truth for the Space settings it defines.

## When to add a configuration file

Try an ordinary scan first. Add a configuration file when the scan cannot find the right content directory or when you need to declare details that are not visible in a static schema, such as:

- a Space nested below an application directory;
- multiple Markdown Collections with different profiles or file formats;
- localized content stored in separate directories;
- custom frontmatter fields that should be editable in Prosefly; or
- a supported native navigation file that automatic discovery cannot associate with a Collection.

The editor never executes repository code. A dynamic loader can therefore require an explicit definition even when the site builds successfully.

## File location and lifecycle

Create the file at the repository root:

```text
.prosefly/config.yaml
```

After adding or changing it, run **Scan repository** again. Prosefly validates the file before creating or updating the Space. A Space loaded from this file is configuration-managed: change its name, paths, profile, framework, or publish mode in Git, then scan again. Drafts and content edits still remain in Prosefly until you publish them.

## Minimal configuration

The top-level document requires `version: 1` and at least one Space. Paths are relative to the repository root, except Collection directories, which are relative to their Space `root`.

```yaml
version: 1
spaces:
  - name: Documentation
    root: apps/docs
    publicDir: public
    profile: starlight
    framework: astro
    publishMode: pull-request
    collections:
      - name: Docs
        directory: src/content/docs
        extensions: [md, mdx]
        fields:
          - name: title
            label: Title
            type: string
            required: true
```

### Space options

Each item under `spaces` can define:

- `name`: the Space name shown in Prosefly;
- `root`: the application directory, or `.` for the repository root;
- `publicDir`: the directory for published public files (defaults to `public`);
- `publicImageDir`: the image directory inside `publicDir` (defaults to `images`);
- `profile`: `prosefly`, `fumadocs`, `starlight`, or `generic`;
- `framework`: `astro`, `nextjs`, `react-router`, `tanstack-start`, `waku`, `hugo`, or `unknown`;
- `publishMode`: `commit` or `pull-request`; and
- `collections`: one or more content definitions.

`framework` and the Space-level `profile` describe the default editing behavior. A Collection can override the profile when different directories use different component syntax.

## Collection options

Each Collection requires `name`, `directory`, `extensions`, and `fields`:

```yaml
collections:
  - name: Blog
    directory: src/content/blog
    extensions: [md, mdx]
    profile: prosefly
    fields:
      - { name: title, label: Title, type: string, required: true }
      - { name: date, label: Date, type: string, format: iso-date }
      - name: tags
        label: Tags
        type: array
        items:
          type: string
        widget: tags
```

Supported extensions are `md`, `mdx`, `yaml`, `yml`, and `json`. Markdown Collections and resource Collections use separate definitions; do not mix document and resource extensions in one Collection. Resource files use the `generic` profile and do not have document navigation.

For localized Markdown, keep language directories inside the Collection and declare both the included directories and their locale codes:

```yaml
collections:
  - name: Docs
    directory: content
    includeDirectories: [en, zh-cn, ja]
    locales:
      - { locale: en, directory: en }
      - { locale: zh-CN, directory: zh-cn }
      - { locale: ja, directory: ja }
    extensions: [md, mdx]
    fields: []
```

### Field syntax

Each item in `fields` describes one frontmatter or resource property. `name` must match the key in the source file; `label` is the name shown in the editor. Keep field names stable so existing drafts and indexed entries continue to match.

| Option        | Purpose                                                                                                             |
| ------------- | ------------------------------------------------------------------------------------------------------------------- |
| `name`        | Source key for the property. Required for named fields.                                                             |
| `type`        | Value shape: `string`, `number`, `boolean`, `date`, `object`, `array`, `reference`, `enum`, or `union`.             |
| `label`       | Optional editor label.                                                                                              |
| `required`    | Requires the key to be present. It does not require non-empty text or lists.                                        |
| `default`     | Value used when creating a new entry. It does not rewrite existing source files.                                    |
| `nullable`    | Allows an explicit `null` value.                                                                                    |
| `format`      | String format such as `iso-date`, `iso-datetime`, `url`, `email`, or `uuid`.                                        |
| `validations` | Type-specific limits such as `min`, `max`, `integer`, or datetime options.                                          |
| `widget`      | Compatible editor control such as `textarea`, `tags`, `select`, or `image-src`; it does not change the stored type. |

Use `fields` for named children of an `object`, `items` for an `array`, `values` for an `enum`, `collection` for a `reference`, and `variants` for a `union`:

```yaml
fields:
  - name: title
    label: Title
    type: string
    required: true
    validations:
      min: 1
  - name: publishedAt
    label: Published at
    type: string
    format: iso-datetime
  - name: tags
    label: Tags
    type: array
    items:
      type: string
    widget: tags
```

`required` checks whether a key exists, while `validations.min` can require a non-empty string or list. Defaults must match the field definition and are only used for new entries. A widget changes the editing control, not the accepted source value.

## Declaring navigation

Leave `navigation` out when the site has no writable native navigation or when content-only publication is enough. The binding belongs to the target Collection inside a Space. For a JSON navigation file, associate the file and the object key with that Collection:

```yaml
collections:
  - name: Docs
    directory: src/content/docs
    extensions: [md, mdx]
    fields: []
    navigation:
      provider: json
      configPath: theme.config.json
      key: docsNav
```

For a supported native integration, declare the provider, its configuration path, and the version used by the site. These paths are relative to the Space `root`, so a new Space does not need a separate application-root field. Starlight uses the Astro config and the Collection directory already declared above:

```yaml
collections:
  - name: Docs
    directory: src/content/docs
    extensions: [md, mdx]
    fields: []
    navigation:
      provider: starlight
      configPath: astro.config.mjs
      version: 0.37.0
```

The provider must match the site’s actual configuration. Prosefly reviews navigation changes together with document changes; it does not rewrite the framework configuration while scanning.

## Scan and troubleshoot

1. Commit `.prosefly/config.yaml` to the branch Prosefly scans.
2. Run **Scan repository** and inspect the detected Space and Collections.
3. Confirm the profile, paths, fields, and navigation binding.
4. Open a document and rebuild the index if the Space was already created.

If validation fails, check indentation, relative paths, unique Space roots, supported extensions, and the required `publishMode`. A configuration error does not execute repository code and does not change Git files.

If the site uses a navigation format that Prosefly cannot edit, keep the Collection definition and use content-only publication. See [Repositories and Spaces](/docs/repositories-and-spaces/) for navigation behavior and [publication review](/docs/publishing/#review-content-and-navigation-together) for the final diff.
