secondbrain-entity

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Add Custom Entity

添加自定义实体

Create custom entity types with schema validation and VitePress integration.
创建带Schema验证和VitePress集成的自定义实体类型。

Prerequisites

前提条件

Verify secondbrain is initialized:
  1. Check for
    .claude/data/config.yaml
  2. If not found, suggest running
    secondbrain-init
    first
确认secondbrain已初始化:
  1. 检查是否存在
    .claude/data/config.yaml
  2. 若未找到,建议先运行
    secondbrain-init

Workflow

操作流程

Step 1: Gather Entity Information

步骤1:收集实体信息

Collect from user:
  1. Entity Name — Plural name (e.g., "contacts", "projects", "bookmarks")
  2. Singular Name — For display (e.g., "contact", "project", "bookmark")
  3. Fields — Custom fields for the entity:
    • Field name (snake_case)
    • Field type (string, integer, boolean, date, array, enum)
    • Required or optional
    • For enums: allowed values
  4. ID Format — How records are numbered/identified:
    • Sequential (
      PREFIX-XXXX
      )
    • Date-based (
      YYYY-MM-DD-slug
      )
    • UUID
  5. Status Workflow (optional) — If entity has status tracking
向用户收集以下信息:
  1. 实体名称 — 复数形式(例如:"contacts"、"projects"、"bookmarks")
  2. 单数名称 — 用于显示(例如:"contact"、"project"、"bookmark")
  3. 字段 — 实体的自定义字段:
    • 字段名称(蛇形命名法snake_case)
    • 字段类型(string、integer、boolean、date、array、enum)
    • 必填或可选
    • 若为枚举类型:允许的取值
  4. ID格式 — 记录的编号/标识方式:
    • 序列式(
      PREFIX-XXXX
    • 基于日期(
      YYYY-MM-DD-slug
    • UUID
  5. 状态工作流(可选)— 若实体需要状态追踪

Step 2: Generate Schema

步骤2:生成Schema

Create
.claude/data/<entity>/schema.yaml
:
yaml
type: object
required: [records]
properties:
  last_number:
    type: integer
    description: Last assigned sequential number
  records:
    type: array
    items:
      type: object
      required: [id, title, created, file]
      properties:
        id:
          type: string
          description: Unique identifier
        title:
          type: string
          description: Display title
        created:
          type: string
          format: date
        file:
          type: string
          description: Path to markdown file
        status:
          type: string
          enum: [active, archived]
        # ... custom fields
创建
.claude/data/<entity>/schema.yaml
yaml
type: object
required: [records]
properties:
  last_number:
    type: integer
    description: Last assigned sequential number
  records:
    type: array
    items:
      type: object
      required: [id, title, created, file]
      properties:
        id:
          type: string
          description: Unique identifier
        title:
          type: string
          description: Display title
        created:
          type: string
          format: date
        file:
          type: string
          description: Path to markdown file
        status:
          type: string
          enum: [active, archived]
        # ... custom fields

Step 3: Initialize Records File

步骤3:初始化记录文件

Create
.claude/data/<entity>/records.yaml
:
yaml
last_number: 0
records: []
创建
.claude/data/<entity>/records.yaml
yaml
last_number: 0
records: []

Step 4: Create Document Template

步骤4:创建文档模板

Create
templates/entities/<entity>/TEMPLATE.md
:
markdown
---
id: {{id}}
title: {{title}}
created: {{date}}
status: active
创建
templates/entities/<entity>/TEMPLATE.md
markdown
---
id: {{id}}
title: {{title}}
created: {{date}}
status: active

... custom fields

... custom fields



{{title}}

{{title}}

Overview

Overview

[Description]
[Description]

Details

Details

[Content]
undefined
[Content]
undefined

Step 5: Create VitePress Data Loader

步骤5:创建VitePress数据加载器

Create
docs/.vitepress/data/<entity>.data.ts
:
typescript
import { defineLoader } from 'vitepress'
import fs from 'fs'
import yaml from 'js-yaml'

interface Record {
  id: string
  title: string
  created: string
  file: string
  status: string
  // ... custom fields
}

export interface Data {
  records: Record[]
  lastNumber: number
}

declare const data: Data
export { data }

export default defineLoader({
  watch: ['.claude/data/<entity>/*.yaml'],
  async load(): Promise<Data> {
    const recordsPath = '.claude/data/<entity>/records.yaml'

    if (!fs.existsSync(recordsPath)) {
      return { records: [], lastNumber: 0 }
    }

    const content = fs.readFileSync(recordsPath, 'utf-8')
    const parsed = yaml.load(content) as any

    return {
      records: parsed.records || [],
      lastNumber: parsed.last_number || 0
    }
  }
})
创建
docs/.vitepress/data/<entity>.data.ts
typescript
import { defineLoader } from 'vitepress'
import fs from 'fs'
import yaml from 'js-yaml'

interface Record {
  id: string
  title: string
  created: string
  file: string
  status: string
  // ... custom fields
}

export interface Data {
  records: Record[]
  lastNumber: number
}

declare const data: Data
export { data }

export default defineLoader({
  watch: ['.claude/data/<entity>/*.yaml'],
  async load(): Promise<Data> {
    const recordsPath = '.claude/data/<entity>/records.yaml'

    if (!fs.existsSync(recordsPath)) {
      return { records: [], lastNumber: 0 }
    }

    const content = fs.readFileSync(recordsPath, 'utf-8')
    const parsed = yaml.load(content) as any

    return {
      records: parsed.records || [],
      lastNumber: parsed.last_number || 0
    }
  }
})

Step 6: Create Documentation Index

步骤6:创建文档索引

Create
docs/<entity>/index.md
:
markdown
---
title: <Entity> Index
---
创建
docs/<entity>/index.md
markdown
---
title: <Entity> Index
---

<Entity>

<Entity>

<script setup> import { data } from '../.vitepress/data/<entity>.data' import EntityTable from '../.vitepress/theme/components/EntityTable.vue' const columns = [ { key: 'id', label: 'ID', sortable: true }, { key: 'title', label: 'Title', sortable: true }, { key: 'created', label: 'Created', sortable: true }, { key: 'status', label: 'Status', sortable: true } ] </script> <EntityTable :data="data.records" :columns="columns" /> ```
<script setup> import { data } from '../.vitepress/data/<entity>.data' import EntityTable from '../.vitepress/theme/components/EntityTable.vue' const columns = [ { key: 'id', label: 'ID', sortable: true }, { key: 'title', label: 'Title', sortable: true }, { key: 'created', label: 'Created', sortable: true }, { key: 'status', label: 'Status', sortable: true } ] </script> <EntityTable :data="data.records" :columns="columns" /> ```

Step 7: Update Configuration

步骤7:更新配置

Add entity to
.claude/data/config.yaml
:
yaml
entities:
  <entity>:
    enabled: true
    singular: <singular>
    id_format: sequential  # or date-based, uuid
    prefix: PREFIX         # for sequential IDs
    freshness:
      stale_after_days: 30
    fields:
      - name: field_name
        type: string
        required: true
将实体添加至
.claude/data/config.yaml
yaml
entities:
  <entity>:
    enabled: true
    singular: <singular>
    id_format: sequential  # or date-based, uuid
    prefix: PREFIX         # for sequential IDs
    freshness:
      stale_after_days: 30
    fields:
      - name: field_name
        type: string
        required: true

Step 8: Update Sidebar

步骤8:更新侧边栏

Add to
docs/.vitepress/config.ts
sidebar:
typescript
{
  text: '<Entity>',
  collapsed: true,
  items: [
    { text: 'Overview', link: '/<entity>/' }
  ]
}
docs/.vitepress/config.ts
侧边栏中添加:
typescript
{
  text: '<Entity>',
  collapsed: true,
  items: [
    { text: 'Overview', link: '/<entity>/' }
  ]
}

Step 9: Confirm Creation

步骤9:确认创建完成

undefined
undefined

Entity Created

Entity Created

Name: <entity> Singular: <singular> ID Format: sequential (PREFIX-XXXX) Status Tracking: Yes
Name: <entity> Singular: <singular> ID Format: sequential (PREFIX-XXXX) Status Tracking: Yes

Fields

Fields

FieldTypeRequired
titlestringYes
descriptionstringNo
priorityenum (low, medium, high)No
FieldTypeRequired
titlestringYes
descriptionstringNo
priorityenum (low, medium, high)No

Files Created

Files Created

  • .claude/data/<entity>/schema.yaml
  • .claude/data/<entity>/records.yaml
  • docs/.vitepress/data/<entity>.data.ts
  • docs/<entity>/index.md
  • .claude/data/<entity>/schema.yaml
  • .claude/data/<entity>/records.yaml
  • docs/.vitepress/data/<entity>.data.ts
  • docs/<entity>/index.md

Next Steps

Next Steps

  1. Create records using the new entity type
  2. Add entity-specific skills if needed
  3. Customize the index page layout
undefined
  1. Create records using the new entity type
  2. Add entity-specific skills if needed
  3. Customize the index page layout
undefined

Field Types

字段类型

TypeYAML SchemaExample
string
type: string
"Hello world"
integer
type: integer
42
number
type: number
3.14
boolean
type: boolean
true/false
date
type: string, format: date
2026-01-15
datetime
type: string, format: date-time
2026-01-15T10:30:00Z
array
type: array, items: {...}
[tag1, tag2]
enum
type: string, enum: [...]
"active"
TypeYAML SchemaExample
string
type: string
"Hello world"
integer
type: integer
42
number
type: number
3.14
boolean
type: boolean
true/false
date
type: string, format: date
2026-01-15
datetime
type: string, format: date-time
2026-01-15T10:30:00Z
array
type: array, items: {...}
[tag1, tag2]
enum
type: string, enum: [...]
"active"

ID Formats

ID格式

Sequential

序列式

Best for: Tasks, tickets, numbered records
PREFIX-0001, PREFIX-0002, PREFIX-0003
最适合:任务、工单、编号记录
PREFIX-0001, PREFIX-0002, PREFIX-0003

Date-based

基于日期

Best for: Notes, journal entries, time-sensitive content
2026-01-15-meeting-notes
2026-01-15-architecture-review
最适合:笔记、日志条目、时间敏感内容
2026-01-15-meeting-notes
2026-01-15-architecture-review

UUID

UUID

Best for: Globally unique, import/export scenarios
550e8400-e29b-41d4-a716-446655440000
最适合:全局唯一、导入/导出场景
550e8400-e29b-41d4-a716-446655440000

Tips

小贴士

  1. Keep fields minimal — Start with essential fields, add more later
  2. Use enums for fixed values — Better than free-form strings
  3. Consider status workflow — Most entities benefit from status tracking
  4. Plan ID format carefully — Hard to change after records exist
  5. Reuse existing patterns — Look at ADR, Task, Note for inspiration
  1. 字段尽量精简 — 从核心字段开始,后续再逐步添加
  2. 对固定值使用枚举类型 — 比自由格式字符串更优
  3. 考虑状态工作流 — 大多数实体都能从状态追踪中受益
  4. 谨慎规划ID格式 — 记录创建后难以更改
  5. 复用现有模式 — 可参考ADR、Task、Note的实现方式