Overview
This issue defines the canonical schema for every asset type in the OpenConduit marketplace registry (OpenConduit/marketplace). It serves as the implementation reference for the registryStore, marketplace UI components, and the CI build pipeline.
Each asset lives as a single .yaml file in registry/<type>/. A CI step compiles all files in a folder into a flat index.json served at registry.openconduit.ai/v1/<type>/index.json.
Shared fields (all asset types)
Every entry must include these top-level fields:
| Field |
Type |
Description |
id |
string |
Unique kebab-case identifier. Must be stable — used as a key in local stores. |
name |
string |
Display name shown in the marketplace card. |
type |
string |
Asset type discriminator (see per-type values below). |
author |
string |
GitHub handle of the author. openconduit for official entries. |
verified |
boolean |
Set to true by maintainers after review. Community submissions use false. |
description |
string |
One-line description shown in the marketplace card. |
content |
object |
Type-specific payload (see per-type schemas below). |
Asset types
1. Persona — type: persona
Stored in registry/personas/.
Installed into personasStore via addPersona(content).
id: code-reviewer
name: Code Reviewer
type: persona
author: openconduit
verified: true
description: Senior engineer reviewing code for correctness, security, and style.
content:
name: Code Reviewer # string — display name (can differ from top-level name)
color: "#6366f1" # string — hex colour for the avatar dot
systemPrompt: | # string — injected as the system message
You are a senior software engineer...
TypeScript type (content):
interface PersonaContent {
name: string;
color: string;
systemPrompt: string;
}
Install behaviour: calls usePersonasStore().addPersona(entry.content) — assigns a new UUID unless the entry id matches an existing starter-* ID (those use fixed IDs to prevent duplicates).
2. Prompt Template — type: prompt-template
Stored in registry/prompts/.
Installed into templatesStore (new store, see #21).
id: blog-post-draft
name: Blog Post Draft
type: prompt-template
author: openconduit
verified: true
description: Draft a blog post from a topic and key points.
content:
template: | # string — prompt body with {{variable}} placeholders
Write a blog post about {{topic}}.
Key points: {{key_points}}
Tone: {{tone}}.
Length: {{word_count}} words.
variables: # array — defines the fill-in form
- name: topic # string — matches {{placeholder}} in template
label: Topic # string — form field label
type: text # enum: text | textarea | select | number
- name: key_points
label: Key Points
type: textarea
- name: tone
label: Tone
type: select
options: [professional, casual, technical] # required when type is select
- name: word_count
label: Word Count
type: number
default: 800 # optional — pre-filled value
TypeScript types (content):
type VariableType = 'text' | 'textarea' | 'select' | 'number';
interface TemplateVariable {
name: string;
label: string;
type: VariableType;
options?: string[]; // required when type === 'select'
default?: string | number;
}
interface PromptTemplateContent {
template: string;
variables: TemplateVariable[];
}
Render behaviour: replace all {{name}} occurrences with the filled-in values, then insert the rendered string into InputBar.
3. Routing Profile — type: routing-profile
Stored in registry/profiles/.
Installed into settingsStore routing config.
id: cost-optimised
name: Cost Optimised
type: routing-profile
author: openconduit
verified: true
description: Routes simple tasks to cheap models, complex reasoning to premium.
content:
tiers: # object — model IDs per tier
fast: gpt-4o-mini # string — model ID for fast/simple tasks
balanced: gpt-4o # string — model ID for balanced tasks
powerful: claude-opus-4-5 # string — model ID for complex tasks
taskOverrides: # object — optional per-task tier overrides
code: balanced # task key → tier name
research: powerful
summary: fast
TypeScript types (content):
type RoutingTier = 'fast' | 'balanced' | 'powerful';
type TaskKey = 'code' | 'research' | 'summary' | 'chat' | 'creative' | string;
interface RoutingProfileContent {
tiers: Record<RoutingTier, string>; // tier → model ID
taskOverrides: Partial<Record<TaskKey, RoutingTier>>;
}
Install behaviour: saves the profile to settingsStore.routingProfiles[]; user selects the active profile separately.
4. Theme — type: theme
Stored in registry/themes/.
Installed into themesStore (new store, see #22).
id: midnight-navy
name: Midnight Navy
type: theme
author: openconduit
verified: true
description: Deep navy dark theme with cyan accents.
content:
colors: # object — CSS variable overrides
--color-primary: "#22d3ee" # accent / interactive colour
--color-surface: "#0f1729" # card / panel background
--color-background: "#0a1120" # app background
--color-muted: "#1e2d45" # subtle backgrounds / dividers
--color-text: "#e2e8f0" # primary text
--color-border: "#1e3a5f" # borders and outlines
Required CSS variables (all must be present):
| Variable |
Purpose |
--color-primary |
Accent, buttons, active states |
--color-surface |
Cards, panels, sidebar background |
--color-background |
App background |
--color-muted |
Subtle fills, dividers, hover states |
--color-text |
Primary text |
--color-border |
Borders and outlines |
TypeScript types (content):
interface ThemeContent {
colors: {
'--color-primary': string;
'--color-surface': string;
'--color-background': string;
'--color-muted': string;
'--color-text': string;
'--color-border': string;
[key: string]: string; // allow additional variables
};
}
Apply behaviour: Object.entries(content.colors).forEach(([k, v]) => document.documentElement.style.setProperty(k, v)) — no rebuild required.
5. Provider — type: provider
Stored in registry/providers/.
Integrated with the existing provider marketplace (currently uses provider-registry.json in core).
Schema TBD — will be migrated from the existing in-app registry format when the hosted registry ships (#23).
6. MCP Server — type: mcp
Stored in registry/mcp/.
Integrated with the existing MCP marketplace (currently uses mcp-registry.json in core).
Schema TBD — will be migrated from the existing in-app registry format when the hosted registry ships (#23).
RegistryEntry union type
type RegistryEntry =
| { type: 'persona'; content: PersonaContent } & SharedFields
| { type: 'prompt-template'; content: PromptTemplateContent } & SharedFields
| { type: 'routing-profile'; content: RoutingProfileContent } & SharedFields
| { type: 'theme'; content: ThemeContent } & SharedFields
| { type: 'provider'; content: unknown } & SharedFields
| { type: 'mcp'; content: unknown } & SharedFields;
interface SharedFields {
id: string;
name: string;
author: string;
verified: boolean;
description: string;
}
CI schema validation
A GitHub Actions workflow in OpenConduit/marketplace should validate each .yaml file on PRs:
- All shared fields present and correctly typed
type matches the folder it's in
content matches the schema for the declared type
id is kebab-case and unique within the folder
color fields (personas, themes) are valid hex strings
Related
Overview
This issue defines the canonical schema for every asset type in the OpenConduit marketplace registry (
OpenConduit/marketplace). It serves as the implementation reference for theregistryStore, marketplace UI components, and the CI build pipeline.Each asset lives as a single
.yamlfile inregistry/<type>/. A CI step compiles all files in a folder into a flatindex.jsonserved atregistry.openconduit.ai/v1/<type>/index.json.Shared fields (all asset types)
Every entry must include these top-level fields:
idstringnamestringtypestringauthorstringopenconduitfor official entries.verifiedbooleantrueby maintainers after review. Community submissions usefalse.descriptionstringcontentobjectAsset types
1. Persona —
type: personaStored in
registry/personas/.Installed into
personasStoreviaaddPersona(content).TypeScript type (content):
Install behaviour: calls
usePersonasStore().addPersona(entry.content)— assigns a new UUID unless the entryidmatches an existingstarter-*ID (those use fixed IDs to prevent duplicates).2. Prompt Template —
type: prompt-templateStored in
registry/prompts/.Installed into
templatesStore(new store, see #21).TypeScript types (content):
Render behaviour: replace all
{{name}}occurrences with the filled-in values, then insert the rendered string intoInputBar.3. Routing Profile —
type: routing-profileStored in
registry/profiles/.Installed into
settingsStorerouting config.TypeScript types (content):
Install behaviour: saves the profile to
settingsStore.routingProfiles[]; user selects the active profile separately.4. Theme —
type: themeStored in
registry/themes/.Installed into
themesStore(new store, see #22).Required CSS variables (all must be present):
--color-primary--color-surface--color-background--color-muted--color-text--color-borderTypeScript types (content):
Apply behaviour:
Object.entries(content.colors).forEach(([k, v]) => document.documentElement.style.setProperty(k, v))— no rebuild required.5. Provider —
type: providerStored in
registry/providers/.Integrated with the existing provider marketplace (currently uses
provider-registry.jsonin core).Schema TBD — will be migrated from the existing in-app registry format when the hosted registry ships (#23).
6. MCP Server —
type: mcpStored in
registry/mcp/.Integrated with the existing MCP marketplace (currently uses
mcp-registry.jsonin core).Schema TBD — will be migrated from the existing in-app registry format when the hosted registry ships (#23).
RegistryEntryunion typeCI schema validation
A GitHub Actions workflow in
OpenConduit/marketplaceshould validate each.yamlfile on PRs:typematches the folder it's incontentmatches the schema for the declared typeidis kebab-case and unique within the foldercolorfields (personas, themes) are valid hex stringsRelated
registry.openconduit.ai)OpenConduit/marketplace— registry source of truth