Takazudo Modular Docs

Type to search...

to open search from anywhere

Product Series

Product Series Specification

Overview

The product series system provides RDB-like relationships for grouping product variants under a common series. This allows proper organization of related products while maintaining distinct product names for each variant.

Architecture

Data Files

  • src/data/product-master-data.mjs: Contains product catalog with seriesId foreign key
  • src/data/product-series.mjs: Contains series master data (series metadata)

Relationship Structure

graph LR
    A[product-master-data.mjs]
    B[product-series.mjs]

    A1["zudo-stand-40<br/>seriesId: 'zudo-stand'"]
    A2["zudo-stand-60<br/>seriesId: 'zudo-stand'"]
    A3["zudo-stand-40x2<br/>seriesId: 'zudo-stand'"]

    B1["'zudo-stand'<br/>name: 'zudo-stand'<br/>detailHref: '/notes/...'<br/>description: '...'"]

    A1 -->|references| B1
    A2 -->|references| B1
    A3 -->|references| B1

    style A1 fill:#2d3748,stroke:#4a5568,color:#fff
    style A2 fill:#2d3748,stroke:#4a5568,color:#fff
    style A3 fill:#2d3748,stroke:#4a5568,color:#fff
    style B1 fill:#1a365d,stroke:#2c5282,color:#fff

Product Series Data Structure

Series Object Schema

Each series is defined as an object property, where the key is the series ID:

'series-id': {
  name: 'Series Name',      // Display name for the series
  detailHref: '/notes/...',  // URL to series introduction page
  description: 'Brief description of the series'
}

Example: zudo-stand Series

'zudo-stand': {
  name: 'zudo-stand',
  detailHref: '/products/zudo-stand-intro/',
  description: 'zudo-blockシリーズを支えるスタンド',
}

Product Data Integration

Adding seriesId to Products

In product-master-data.mjs:

{
  slug: 'zudo-stand-40',
  name: 'zudo-stand-40',
  seriesId: 'zudo-stand',  // References series in product-series.mjs
  brand: 'takazudo',
  // ... other fields
}

Field Distinction

  • name: Full product identifier (e.g., “zudo-stand-40”)
  • subtitle: Optional secondary text (e.g., “Hybrid Oscillator”)
  • seriesId: Optional reference to product series (e.g., “zudo-stand”)

Helper Functions

getSeriesById(seriesId)

Retrieves complete series metadata by ID.

import { getSeriesById } from '../data/product-series.mjs';

const series = getSeriesById('zudo-stand');
// Returns: { name: 'zudo-stand', detailHref: '/notes/...', description: '...' }

getSeriesName(seriesId)

Retrieves only the series name (useful for breadcrumbs).

import { getSeriesName } from '../data/product-series.mjs';

const name = getSeriesName('zudo-stand');
// Returns: 'zudo-stand'

seriesExists(seriesId)

Checks if a series exists.

import { seriesExists } from '../data/product-series.mjs';

if (seriesExists('zudo-stand')) {
  // Series exists
}

Usage in Components

The series system automatically resolves breadcrumbs in article-page-layout.tsx:

import { getSeriesName } from '../data/product-series.mjs';

// In BreadBlock component
if (seriesId) {
  const seriesName = getSeriesName(seriesId);
  breadcrumbText = seriesName || productName;
}

Result: Product detail pages for series members (e.g., zudo-stand-40) display the series name (“zudo-stand”) in breadcrumbs, not the individual variant name.

GraphQL Queries

Products with series metadata:

query {
  allProduct {
    nodes {
      slug
      name
      subtitle
      seriesId
      # ... other fields
    }
  }
}

Adding a New Series

Step 1: Define Series Metadata

Add to product-series.mjs:

const productSeries = {
  'my-new-series': {
    name: 'My New Series',
    detailHref: '/products/my-new-series-intro/',
    description: 'Description of my new series',
  },
  // ... existing series
};

Step 2: Add seriesId to Products

Update products in product-master-data.mjs:

{
  slug: 'my-new-series-variant-a',
  name: 'my-new-series-variant-a',
  seriesId: 'my-new-series',
  // ... other fields
}

Step 3: Create Series Introduction Page

Create MDX file at the detailHref path with information about the series and its variants.

Behavior & Display

Product Listings

  • Top page: Shows full product names (e.g., “zudo-stand-40”, “zudo-stand-60”)
  • Brand pages: Shows full product names
  • No changes to how product names appear in listings
  • With seriesId: Displays series name (e.g., “zudo-stand”)
  • Without seriesId: Displays product name + subtitle
  • No MDX overrides needed: productNameBread frontmatter is no longer required for series products

Example Comparison

Before (without series system)

  • Product: name: "zudo-stand 40HP版"
  • Breadcrumb: Requires manual productNameBread: "zudo-stand" in MDX frontmatter
  • Problem: Product name mixing with display text

After (with series system)

  • Product: name: "zudo-stand-40", seriesId: "zudo-stand"
  • Breadcrumb: Automatically resolves to “zudo-stand” from series metadata
  • Benefit: Clean separation of data and presentation

Best Practices

When to Use Series

Use series grouping when:

  • Multiple product variants belong to the same family
  • Variants share the same introduction page
  • Breadcrumbs should show the series name, not individual variant names

When NOT to Use Series

Do not use series when:

  • Product is standalone with no variants
  • Products are related but distinct (use relatedProductIds instead)
  • Different product lines from same brand

Naming Conventions

  • Series ID: Use kebab-case (e.g., “zudo-stand”, “oxi-one”)
  • Series Name: Can use any format (e.g., “zudo-stand”, “OXI ONE”)
  • Product Name: Full identifier with variant (e.g., “zudo-stand-40”, “oxi-one-mk2-black”)

TypeScript Types

export interface ProductSeries {
  name: string;
  detailHref: string;
  description: string;
}

export interface Product {
  slug: string;
  name: string;
  subtitle?: string | null;
  seriesId?: string | null;  // References ProductSeries by object key
  // ... other fields
}