name: docs-data-type-ref description: Use when the user asks to write a reference page for a ZIO Blocks data type, API documentation, or class/trait/object documentation. argument-hint: "[fully-qualified-type-name or simple-type-name]" allowed-tools: Read, Glob, Grep, Bash(sbt:), Bash(sbt gh-query)
Write Data Type Reference Page
REQUIRED BACKGROUND: Use docs-writing-style for prose conventions and docs-mdoc-conventions for code block syntax throughout.
Target Type
$ARGUMENTS
Step 1: Deep Source Code Research
Before writing anything, build a complete mental model of the type:
Find the source file: Use Glob to find the primary source file for the type. Check all Scala version directories (
*/src/main/scala*/). The type may have platform-specific or version-specific variants.Read the full source: Read the entire source file. Identify:
- The type signature (class/trait/object, type parameters, variance, extends clauses)
- All public methods, their signatures, and what they do
- Companion object methods (factory methods, smart constructors, predefined instances)
- Nested types and type aliases
- Implicit instances and extension methods
Find tests: Search
*/src/test/scala/for test files referencing the type. Tests reveal:- Intended usage patterns and idioms
- Edge cases and expected behavior
- Real-world examples
Find existing examples: Use Glob and Grep to locate examples in
schema-examples/or any directory with "examples" in its name.Find usages: Grep for the type name across the codebase to find how it's used by other modules — this reveals integration points and relationships.
Read related docs: Check
docs/anddocs/reference/for pages that reference this type.Search GitHub history: Run
sbt "gh-query --verbose <TypeName>"to search GitHub issues, PRs, and comments for discussions about the type. Use the results to:- Understand design decisions and rationale behind the API
- Find known caveats, gotchas, or non-obvious behavior surfaced in issues
- Discover common user questions or pain points to address in the docs
- Identify changelog entries or breaking changes worth noting
- Surface examples or idioms shared by contributors in PRs
Run multiple queries as needed (e.g., the simple type name, the fully-qualified name, related feature keywords) to get thorough coverage.
Step 2: Write the Documentation
File Location and Frontmatter
Place the file in docs/reference/<type-name-kebab-case>.md:
---
id: <kebab-case-id>
title: "<TypeName>"
---
The id must match the filename (without .md).
Document Structure
Follow this structure precisely. Every section below marked (required) must appear. Sections marked (if applicable) should only appear when relevant.
1. Opening Definition (required)
NO HEADING FOR THIS SECTION. Start with a concise, technical definition immediately after the frontmatter—do NOT add any heading (## or otherwise). This content forms the natural opening of the document.
Use inline code for the type signature. Explain the type parameters. State the core purpose in 1-3 sentences.
Pattern:
`TypeName[A]` is a **key concept in two or three words** that does X. The fundamental operations are `op1` and `op2`.
Then list key properties as bullet points if applicable:
`TypeName`:
- is purely functional and referentially transparent
- is concurrent-safe and lock-free
- updates and modifies atomically
The definition should be concise but informative, with enough detail about type parameters and variance. For example, the Chunk[A] is an immutable, indexed sequence of elements of type A, optimized for high-performance operations.
After the definition paragraph, include the source definition of the data type in a Scala code block (using plain ```scala without mdoc, since this is for illustration):
- Show only the structural shape — the trait/class declaration with type parameters, variance annotations, and extends clauses
- Strip method bodies, private members, and extra keywords like
final; show only the structural shape of the type
After the structural definition, follow immediately with a section header (e.g., ## Overview, ## Introduction) to continue the document.
2. Motivation / Use Case (if applicable)
Answer: What problem does it solve? Why use it over alternatives? Include ASCII art for structure, bullet points for advantages, and a "hello world" example.
3. Installation (if applicable)
Only include this for top-level module types (e.g., Chunk, Context, TypeId). Skip for internal types that come as part of a larger module.
libraryDependencies += "dev.zio" %% "zio-blocks-<module>" % "<version>"
For cross-platform (Scala.js):
libraryDependencies += "dev.zio" %%% "zio-blocks-<module>" % "<version>"
Note supported Scala versions: 2.13.x and 3.x.
4. Construction / Creating Instances (required)
Document all ways to create values of the type, organized by method:
- Factory methods on the companion object (
apply,empty,from*,of,derived) - Smart constructors
- Builder patterns
- Conversion from other types
- Predefined instances (if any)
Each method gets its own ### subsection with a short explanation and a code example.
5. Predefined Instances (if applicable)
List predefined instances (like TypeId.int, TypeId.string) organized by category in a table or code block.
6. Core Operations (Required)
Document the primary API organized by category. Group related methods under ### subsections:
For example:
- Element Access (get, apply, head, etc.)
- Transformations (map, flatMap, filter, etc.)
- Combining (++, combine, merge, etc.)
- Querying (exists, forall, find, contains, etc.)
- Conversion (toList, toArray, toString, etc.)
For each group:
- List methods with brief descriptions
- Show a code example demonstrating 2-4 methods together
- Note performance characteristics inline when relevant (e.g., "O(1)", "O(n)")
For each method:
a. Use a #### heading with the method name
b. Explain what it does in plain language
c. Show the method signature in a plain scala code block using the simplest trait interface format — just the method name, parameters, and return type, without extra keywords like override, final, sealed. For example:
trait Chunk[+A] {
def map[B](f: A => B): Chunk[B]
}
If the method is in the companion object, show it as a function in the companion object's simplest form:
object Chunk {
def apply[A](as: A*): Chunk[A]
}
d. Show a usage example using the Setup + Evaluated Output pattern:
- Combine setup and output in a single code block using
mdoc:silent:reset(or justmdoc:resetif resetting state) - Setup code goes first (define types/values needed), followed by the method call and output
- This demonstrates both how to call the method AND what it returns
Example pattern:
```scala mdoc:reset
case class Person(name: String)
val p = Person("Alice")
p.name // Shows: val res0: String = Alice
Style rule: Between any two code blocks, include an explanatory paragraph that introduces or describes what the following code demonstrates. Do NOT leave empty lines between code blocks.
✅ Correct:
```scala mdoc
val x = 1
Now let's use x to compute a result:
```scala mdoc val y = x + 1
❌ Wrong:
```scala mdoc
val x = 1
```scala mdoc val y = x + 1
e. Note important caveats using Docusaurus admonitions
7. Subtypes / Variants (if applicable)
Document important subtypes (e.g., NonEmptyChunk for Chunk) with: when to use, how to create, operations that differ, and conversion examples.
8. Comparison Sections (when applicable)
Compare with analogous concepts from Java, Scala stdlib, or theoretical CS when it adds clarity. Examples:
- "Ref vs AtomicReference in Java"
- "Ref vs State Monad"
- "Promise vs Scala's Promise"
- "Chunk vs List vs Array"
- "TypeId vs Scala's TypeTag vs Java's Class"
- "Lazy vs lazy val vs def"
Use padded table columns for readability (see docs-writing-style for table formatting rules).
9. Advanced Usage / Building Blocks (when applicable)
Show how the type composes with other types or how it can be used to build higher-level abstractions.
10. Integration (if applicable)
Show how this type integrates with other ZIO Blocks data types and module. For example:
- How
TypeIdis used inSchema - How
Chunkis used inReflect - How
DynamicValueconnects toSchemaand formats
Add cross-references to related docs (e.g., [Schema](./schema.md), [Reflect](./reflect.md)) after explaining the integration of each related type.
11. Running the Examples (required when examples exist)
Add this section at the very end of the page, after Integration. For each App example, embed the full source using SourceFile.print, then show the command to run it. Use this template verbatim:
## Running the Examples
All code from this guide is available as runnable examples in the `schema-examples` module.
**1. Clone the repository and navigate to the project:**
```bash
git clone https://github.com/zio/zio-blocks.git
cd zio-blocks
2. Run individual examples with sbt:
import docs.SourceFile
SourceFile.print("schema-examples/src/main/scala/<package>/<ObjectName>.scala")
(source)
sbt "schema-examples/runMain <package>.<ObjectName>"
import docs.SourceFile
SourceFile.print("schema-examples/src/main/scala/<package>/<ObjectName2>.scala")
(source)
sbt "schema-examples/runMain <package>.<ObjectName2>"
Rules for this section:
- List every
Appobject written in Step 3, one entry per object. - For each entry: embed the full source with
SourceFile.print, then show description, source link, and run command. - The bolded description must be a short plain-English description of what that specific
Appdemonstrates — not the object name rephrased. - Keep the two numbered steps (clone, run individually) in that order; do not add or remove steps.
- If no example
Appobjects were written (rare), omit this section entirely. - Always embed full source —
SourceFile.printkeeps docs and examples in sync automatically.
Embedding Example Files with SourceFile
Required for "Running the Examples" section: Use SourceFile.print to embed full source from schema-examples/ for each example.
SourceFile.print reads the file at mdoc compile time and emits a fenced code block with the file path shown as the title. This keeps docs and examples in sync automatically.
Pattern:
import docs.SourceFile
SourceFile.print("schema-examples/src/main/scala/<package>/<ExampleFile>.scala")
Important: Import as import docs.SourceFile and call SourceFile.print(...) — do NOT use import docs.SourceFile._ with bare print(...) because print conflicts with Predef.print inside mdoc sessions.
Optional parameters:
lines = Seq((from, to))— include only specific line ranges (1-indexed)showLineNumbers = true— render with line numbersshowTitle = false— suppress the file path title
Writing Rules
- Document every public method on the type and its companion object.
- Use ASCII art for type hierarchies and data structures.
- Link to related docs using relative paths:
[TypeName](./type-name.md).
Step 3: Write Examples
Create focused App objects in schema-examples/src/main/scala/<type-name-lowercase>/. Each demonstrates one use case — one App per concept.
- Package: matches directory name (e.g.,
package intoforinto/) - Object: extends
Appfor independent execution - Output: use
util.ShowExpr.show(expr)to print expression and result - Naming: name files after the scenario, not just the type (e.g.,
IntoSchemaEvolutionExample.scala) - Coverage: happy path + at least one failure/edge case, realistic domain types (
Person,Order) - Self-contained: define all types and imports in the file
Step 4: Format and Verify
Format all Scala files:
sbt scalafmtAll
Verify lint checks pass:
sbt check
Verify mdoc compilation:
sbt "docs/mdoc --in docs/reference/<type-name-kebab-case>.md"
Success criterion: zero formatting violations and zero [error] lines in mdoc output.
Step 5: Integrate
Use the docs-integrate skill for integration checklist (sidebars.js, index.md, cross-references).