Skip to content

feat(core): support dynamic function and field placeholders in collection path (#340) - #1651

Open
Saik2789 wants to merge 1 commit into
Thinkmill:mainfrom
Saik2789:feat/bounty-340
Open

Saik2789 wants to merge 1 commit into
Thinkmill:mainfrom
Saik2789:feat/bounty-340

Conversation

@Saik2789

@Saik2789 Saik2789 commented Oct 30, 2026 •

Copy link
Copy Markdown

Resolves #340
@algora-pbc /claim #340

Summary

Collection entry paths were previously static except for the single wildcard segment derived from slugField. Projects requiring paths partitioned by schema fields (such as locales or publication dates) could not configure dynamic collection paths while maintaining static directory discovery for GitHub and local filesystem storage.

Changes

  • Config & Type Definitions (config.tsx, form/api.tsx): Extended Collection['path'] with CollectionPath supporting dynamic function callbacks (e.g. ({ locale }) => \content/blog/${locale}/`) as well as {field} segment placeholders (content/blog/{locale}/`).
  • Path Parsing & Template Normalization (path-utils.ts): Added createPathProxy and parseCollectionPath to resolve function callbacks and placeholder strings into deterministic segment patterns (slugPattern, prefix, glob, suffix). Added schema validation ensuring placeholders map to valid form fields.
  • Slug Resolution & Uniqueness Validation (utils.ts, validateText.tsx, errors.ts, slugs.tsx): Updated getSlugFromState to compose composite slugs from field values (string, number, boolean, and Date instances), and updated slug validation to enforce composite slug uniqueness while allowing identical slug segments across distinct partitions (e.g. en/post vs fr/post).
  • Storage & Reader Listing (reader/generic.ts, utils.ts): Updated getEntriesInCollectionWithTreeKey and collectionReader's list and read methods to traverse matching segment depths, preventing wrong-depth matches and extracting the primary slug segment for form parsing.
  • Admin UI Integration (CollectionPage.tsx, ItemPage.tsx, create-item.tsx, entry-clipboard.ts, useHasChanged.ts, useItemData.ts): Threaded pathInfo through preview props, clipboard deserialization, change detection, and entry creation/renaming.
  • Unit Tests & Changeset (path-utils.test.ts, .changeset/configurable-collection-path.md): Added comprehensive test suite with 22 tests covering path parsing, function evaluation, date fields, error boundaries, tree listing, and reader integration.

Testing

  1. Unit tests:
pnpm exec vitest run packages/keystatic/src/app/path-utils.test.ts

Output:

 ✓ |keystatic| packages/keystatic/src/app/path-utils.test.ts (22 tests) 44ms
 Test Files  1 passed (1)
      Tests  22 passed (22)
  1. Full test suite:
pnpm test

Output:

 Test Files  147 passed | 2 skipped (149)
      Tests  1273 passed | 37 skipped (1310)
  1. Typechecking & Linting:
pnpm check:types
pnpm check:lint

Both passed cleanly with 0 errors and 0 warnings.

Payout Details

  • Payout Address: Wallet (USDC on Base network): 0x20A0525b47f087f1Cc498cda257A0feB78D2320B
  • Contact: saik2789@proton.me

…tion path (Thinkmill#340)

Signed-off-by: Saik2789 <220439327+Saik2789@users.noreply.github.com>
@Saik2789
Saik2789 requested a review from emmatown as a code owner October 30, 2026 16:43
@changeset-bot

changeset-bot Bot commented Oct 30, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: fb4407a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@keystatic/core Minor
@keystatic/templates-astro Patch
@keystatic/templates-nextjs Patch
@keystatic/templates-remix Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: more configurable collection path

1 participant