sanity-io/sanity

repository·main·Indexed 27 days ago

https://github.com/sanity-io/sanity

A Composable Content Cloud featuring Sanity Studio, an open-source customizable CMS, and Content Lake, a real-time hosted data store for structured content. The repository includes documentation for eFPS performance benchmarking, End-to-End (E2E) testing with Playwright, and @repo/debug-proxy, an internal tool for simulating adverse network conditions and API behaviors.

Tokens
59.8K
Snippets
112
Records
446
Agent score
90%

What's inside sanity

  1. Overview of @repo/debug-proxy

    main

    The @repo/debug-proxy is an internal development tool designed for simulating adverse network conditions and API behaviors when working with Sanity Studio. It acts as a local proxy between the client and the Sanity API to test scenarios such as:

    • SSE Issues: Connection latency, dropped, duplicated, or reordered mutation events.
    • Network Flakiness: Simulating partial service outages or connectivity flapping.
    • Access Control: Forcing 401 errors (expired or revoked tokens) to test re-authentication flows.
    • API Response Modification: Verifying client responses to backend changes by intercepting and modifying responses.
  2. Overview of Sanity Studio and Content Cloud

    main

    Sanity is a Composable Content Cloud consisting of:

    • Sanity Studio: An open-source, single-page application (SPA) used as a real-time CMS. It is highly customizable using JavaScript and React, featuring a plugin architecture, custom components, and advanced block editors for structured content.
    • Content Lake: A real-time, hosted data store where your content is stored.

    Key capabilities include:

    • Structured Content: Real-time distribution from a single source of truth, including an asset pipeline for on-demand image transformation and metadata querying.
    • Developer APIs: Support for reading, writing, importing, exporting, and listening for updates, alongside GROQ (Graph Oriented Query Language) and GraphQL APIs.
  3. Understand Sanity Studio Data Flow

    main

    Sanity Studio operates using a reactive data flow between the UI and the Content Lake (Sanity's hosted backend).

    Query Flow

    1. Components request data using hooks like useDocumentStore or useClient.
    2. The Document Store manages subscriptions and caching.
    3. The Client sends GROQ queries to the Content Lake.
    4. Real-time listeners push updates back to the Studio via RxJS Observables.

    Mutation Flow

    1. User edits trigger changes in the Form Builder.
    2. The Form Builder generates patches.
    3. The Mutator applies these patches optimistically in the UI.
    4. Mutations are sent to the Content Lake for persistence.
    5. The system handles confirmation and conflict resolution.
  4. Understand Sanity schema terminology

    main

    Sanity uses specific terminology to define data structures:

    • Schema: A collection of types.
    • Type: A specification of a data structure that is available through schema lookup.
    • Member type: A type contained within a schema type. For example, an array specifies its allowed item types via member types. A reference to other types is also a member type. Unlike standard types, member types are not added to the schema and are not available via schema lookup; they exist only as a property of the owner type.
  5. Understand @sanity/diff concepts and architecture

    main

    The @sanity/diff library is used for calculating and presenting differences between two versions of content.

    Core Concepts

    • Diff: The primary data structure representing the difference between two versions. It is a nested structure; for example, an ObjectDiff contains child Diff objects.
    • Primitives: Diffs are built using unchanged, added, and removed primitives. Because the diff contains both versions simultaneously, you can recreate the old or new version by filtering these primitives.
    • Shallow Comparison: For arrays and objects, unchanged/added/removed status is shallow. An ObjectDiff marks a field as unchanged if it exists in both versions, even if the internal content of that field has changed.
    • Annotations: Diff supports annotations, which store metadata about when a change occurred and who made it.
    • Input Types: To construct a diff, you must represent versions as Input types. This allows for passing annotations and enables optimizations based on object equality.
    • Presentation: The library does not provide UI components. Instead, it provides helper functions to transform diff data for different presentation needs (e.g., showing only changed fields vs. showing the full document with changes interspersed).
  6. Understand Member Types in Sanity Schema

    main

    In Sanity, a member type refers to a type that is not explicitly defined as a top-level schema type, but instead exists as a component or specialization within another type.

    For example, when you define an object type in your schema, the individual fields within that object are considered member types because they are specializations of schema types used to compose the parent object.

  7. Understand the Metrics-studio dashboard architecture

    main

    The Metrics-studio dashboard is a specialized tool within Sanity Studio designed to monitor studio performance trends, specific run details, and performance drift.

    Key Architectural Principles:

    • Realtime Data: All views use useDocumentStore().listenQuery and useObservable instead of one-shot client.fetch. This ensures new performance data from cron runs appears automatically without a page reload.
    • Data Projections: Because benchRun documents contain heavy per-session sample arrays, dashboard queries must always project summaries and never fetch the full sessions array to maintain performance.
    • Calibration: Performance metrics are host-relative. To distinguish between actual code regressions and slower runner environments, the dashboard includes a calibration overlay using runner.calibrationMs.
    • Tool Registration: The dashboard is implemented as a custom tool using defineTool. It is registered as the first tool in the studio to ensure 'Trends' is the default landing view.
    • Visualization: Charts are built using @visx primitives to ensure compatibility with @sanity/ui layouts.
  8. Manage Content Releases

    main

    Releases allow grouping document changes for coordinated publishing. They can be of type asap (publish when ready), scheduled (publish at a specific time), or undecided.

    Releases are stored as system.release documents. Documents belonging to a release follow the ID pattern: versions.<releaseId>.<publishedDocumentId>.

  9. Use Performance Studio for performance testing

    main

    Performance Studio is a specialized version of Sanity Studio designed specifically for capturing and analyzing various performance cases.

    When using Performance Studio for testing, follow this best practice to ensure consistent results:

    • Create new, separate schema types instead of modifying existing ones. This ensures that when running performance tests against older deployments, the schema remains identical and does not introduce side effects from changes made to production schemas.
  10. Understand the Sanity Schema Hierarchy

    main

    Schemas define the structure of your content and are compiled at runtime. The hierarchy follows this pattern:

    1. Schema: The root definition.
    2. Types: The collection of all definitions.
    3. Document Types: Top-level content entities.
    4. Fields: The properties within a document, which can be:
      • Primitive: string, number, boolean, etc.
      • Complex: array, object, reference.
      • Special: image, file, slug, etc.
    5. Object Types: Reusable groups of fields used within documents.
  11. Understand Variant Document Editing Architecture

    main

    Sanity Studio handles variant documents by leveraging the existing IdPair.versionId slot, treating them similarly to release versions. This allows the base publishedId and draftId semantics to remain untouched while the versionId points to the specific variant document.

    IdPair Mapping for Variants

    When a variant is selected and the target document exists, the IdPair is structured as follows:

    SlotContent
    publishedIdBase published ID (the group ID)
    draftIdBase draft ID
    versionIdversions.<scopeId>.<groupId> (the variant document for the current bundle)

    Note: editState.draft and editState.published describe the base pair, whereas editState.version and value describe the specific variant being edited.

  12. Understand Variant Definitions and Variant Documents

    main

    In Sanity, content can be organized into variants based on specific conditions (e.g., locale: fr).

    Variant Definition

    A system document of type system.variant that describes the conditions for a variant.

    • ID Path: _.variants.<suffix>
    • Fields: conditions (Record<string, string>), priority, and optional metadata.title.
    • Discovery: Use the useAllVariants hook to fetch definitions studio-wide.

    Variant Document

    A version document containing alternative content for a base document.

    • ID Shape: versions.<scopeId>.<groupId>
    • groupId: The base published ID.
    • scopeId: An opaque, server-generated hash. You cannot compute or guess this ID; you must discover it via lookup.

    Document Metadata (_system field)

    Every variant document contains authoritative metadata in the _system field:

    FieldMeaning
    variantReference to the system.variant definition (_.variants.*)
    groupReference to the base published ID
    bundleIdThe bundle: 'drafts', a release ID, or unset for a variant-of-published
    scopeIdThe opaque hash from the document's own ID
    releaseReference to the release document (for release-scoped versions)
    deleteSoft-unpublish marker set by variant.unpublish

    Document Siblings

    For one base document and one variant, up to three sibling documents can exist:

    1. Variant-of-published: versions.<hashA>.<groupId> (bundleId is unset)
    2. Variant-of-drafts: versions.<hashB>.<groupId> (bundleId is 'drafts')
    3. Variant-of-release: versions.<hashC>.<groupId> (bundleId is <releaseId>)

    Note: The base published and drafts. documents are separate and are never touched by variants.