Extended Schema Demo
This page demonstrates how to extend the base tag schema with multiple custom field sets. You can combine educational fields (difficulty, prerequisites) with product fields (planTier) in a single schema.
Product Filtering (Plan Tiers)
Section titled “Product Filtering (Plan Tiers)”Filter tags by pricing tier. Perfect for SaaS documentation:
Plan Tier Badges
Section titled “Plan Tier Badges”Educational Filtering (Difficulty Levels)
Section titled “Educational Filtering (Difficulty Levels)”Filter tags by difficulty level. Great for learning paths and tutorials:
Showing 6 of 6 tags
Difficulty Badges
Section titled “Difficulty Badges”With Prerequisites
Section titled “With Prerequisites” Async JS Advanced
Requires:
- js-functions
Combined Schema
Section titled “Combined Schema”Both field sets can coexist in a single schema:
import { z } from 'astro/zod';import { tagDefinitionSchema } from 'starlight-tags/schemas/tags';
export const extendedTagSchema = tagDefinitionSchema.extend({ // Educational fields difficulty: z.enum(['beginner', 'intermediate', 'advanced']).optional(), contentType: z.enum(['lecture', 'lab', 'tutorial', 'reference']).optional(), prerequisites: z.array(z.string()).optional(),
// Product fields product: z.string().optional(), planTier: z.enum(['free', 'pro', 'enterprise']).optional(),});Example tags.yml
Section titled “Example tags.yml”Tags can have educational fields, product fields, or both:
tags: # Educational only js-basics: label: "JS Basics" difficulty: beginner contentType: lecture
# Product only components: label: "Components" planTier: free
# Both fields! advanced-api: label: "Advanced API" difficulty: advanced planTier: enterprise prerequisites: ["js-basics"]Implementation Details
Section titled “Implementation Details”Educational Component
Section titled “Educational Component”---import type { ProcessedTag } from 'starlight-tags/schemas/tags';import type { ExtendedTag } from '../config/extended-tag-schema';
const { tagId } = Astro.props;
const { tags } = Astro.locals.starlightTags;const tag = tags.get(tagId) as (ProcessedTag & ExtendedTag) | undefined;
const difficultyColors = { beginner: '#22c55e', intermediate: '#f59e0b', advanced: '#ef4444'};---
{tag && ( <span class="tag"> {tag.label} {tag.difficulty && ( <span style={`background: ${difficultyColors[tag.difficulty]}`}> {tag.difficulty} </span> )} </span>)}Product Component
Section titled “Product Component”---import type { ProcessedTag } from 'starlight-tags/schemas/tags';import type { ExtendedTag } from '../config/extended-tag-schema';
const { tagId } = Astro.props;
const { tags } = Astro.locals.starlightTags;const tag = tags.get(tagId) as (ProcessedTag & ExtendedTag) | undefined;
const tierColors = { free: '#22c55e', pro: '#3b82f6', enterprise: '#8b5cf6'};---
<span class="tag"> {tag.label} {tag.planTier && ( <span style={`background: ${tierColors[tag.planTier]}`}> {tag.planTier} </span> )}</span>Filtering by Custom Fields
Section titled “Filtering by Custom Fields”// Filter by difficultyconst beginnerTags = allTags.filter(tag => tag.difficulty === 'beginner');
// Filter by plan tierconst freeTags = allTags.filter(tag => tag.planTier === 'free');
// Filter by both (e.g., beginner + free)const accessibleTags = allTags.filter( tag => tag.difficulty === 'beginner' && tag.planTier === 'free');