Initial commit: The Collective Hub planning documentation
This commit is contained in:
@@ -0,0 +1 @@
|
||||
fatal: not a git repository (or any of the parent directories): .git
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
.pnpm-store/
|
||||
|
||||
# Build output
|
||||
/build/
|
||||
/.svelte-kit/
|
||||
|
||||
# Environment
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
|
||||
# Database
|
||||
*.db
|
||||
*.sqlite
|
||||
|
||||
# Docker
|
||||
.docker/
|
||||
|
||||
# Misc
|
||||
*.local
|
||||
@@ -0,0 +1,491 @@
|
||||
<mode_management_workflow>
|
||||
<overview>
|
||||
This workflow guides you through creating new custom modes or editing existing ones
|
||||
for the Roo Code Software, ensuring comprehensive understanding and cohesive implementation.
|
||||
</overview>
|
||||
|
||||
<mode_scope>
|
||||
<workspace_modes>
|
||||
<location>.roomodes in the workspace root directory</location>
|
||||
<notes>
|
||||
Workspace modes are the default target for project-specific modes and for overrides.
|
||||
</notes>
|
||||
</workspace_modes>
|
||||
|
||||
<global_modes>
|
||||
<location>VS Code globalStorage custom modes settings file (location is environment-specific; open it via the product UI)</location>
|
||||
<notes>
|
||||
Global modes are used system-wide and are created automatically on Roo Code startup.
|
||||
</notes>
|
||||
</global_modes>
|
||||
|
||||
<precedence>
|
||||
<rule>
|
||||
If the same slug exists in both global modes and workspace modes, the workspace (.roomodes) entry wins.
|
||||
</rule>
|
||||
</precedence>
|
||||
|
||||
<schema>
|
||||
<rule>
|
||||
Both files use the same YAML schema: a top-level <code>customModes:</code> list of mode objects.
|
||||
</rule>
|
||||
<format_notes>
|
||||
<note>
|
||||
Mode definitions are YAML objects within <code>customModes:</code>. Use YAML block scalars (e.g., <code>>-</code>) for multi-line text fields when helpful.
|
||||
</note>
|
||||
<note>
|
||||
If you must embed explicit newlines in a quoted string, use <code>\n</code> for newlines and <code>\n\n</code> for blank lines.
|
||||
</note>
|
||||
<note>
|
||||
<code>groups</code> is required and is a YAML array. It may be empty when a mode should not have access to optional permissions.
|
||||
</note>
|
||||
<note>
|
||||
Each <code>groups</code> entry may be:
|
||||
- a simple string (unrestricted permission group), or
|
||||
- a structured entry that restricts the permission to a subset of files (e.g., <code>fileRegex</code> + <code>description</code> for edit restrictions).
|
||||
</note>
|
||||
</format_notes>
|
||||
<required_fields>
|
||||
<field>slug</field>
|
||||
<field>name</field>
|
||||
<field>roleDefinition</field>
|
||||
<field>groups</field>
|
||||
</required_fields>
|
||||
<recommended_fields>
|
||||
<field>description</field>
|
||||
<field>whenToUse</field>
|
||||
</recommended_fields>
|
||||
<optional_fields>
|
||||
<field>customInstructions</field>
|
||||
</optional_fields>
|
||||
<example>
|
||||
<comment>Canonical YAML skeleton (illustrative; keep instructions/tooling details in .roo/rules-[slug]/)</comment>
|
||||
<code>
|
||||
customModes:
|
||||
- slug: example-mode
|
||||
name: Example Mode
|
||||
description: Short five-word summary
|
||||
roleDefinition: >-
|
||||
You are Roo Code, a [specialist type] who...
|
||||
|
||||
Key areas:
|
||||
- Area one
|
||||
- Area two
|
||||
whenToUse: >-
|
||||
Use this mode when...
|
||||
groups:
|
||||
- read
|
||||
- - edit
|
||||
- fileRegex: \\.(md|mdx)$
|
||||
description: Documentation files only
|
||||
customInstructions: >-
|
||||
Optional brief glue text.
|
||||
</code>
|
||||
</example>
|
||||
</schema>
|
||||
</mode_scope>
|
||||
|
||||
<initial_determination>
|
||||
<step number="1">
|
||||
<title>Determine User Intent</title>
|
||||
<description>
|
||||
Identify whether the user wants to create a new mode or edit an existing one
|
||||
</description>
|
||||
<detection_patterns>
|
||||
<pattern type="edit_existing">
|
||||
<indicators>
|
||||
<indicator>User mentions a specific mode by name or slug</indicator>
|
||||
<indicator>User references a mode directory path (e.g., .roo/rules-[mode-slug])</indicator>
|
||||
<indicator>User asks to modify, update, enhance, or fix an existing mode</indicator>
|
||||
<indicator>User says "edit this mode" or "change this mode"</indicator>
|
||||
</indicators>
|
||||
</pattern>
|
||||
<pattern type="create_new">
|
||||
<indicators>
|
||||
<indicator>User asks to create a new mode</indicator>
|
||||
<indicator>User describes a new responsibility not covered by existing modes</indicator>
|
||||
<indicator>User says "make a mode for" or "create a mode that"</indicator>
|
||||
</indicators>
|
||||
</pattern>
|
||||
</detection_patterns>
|
||||
<clarification_question>
|
||||
<ask_user_question>
|
||||
<question>I want to make sure I understand correctly. Are you looking to create a brand new mode or modify an existing one?</question>
|
||||
<follow_up>
|
||||
<suggest>Create a new mode for a specific purpose</suggest>
|
||||
<suggest>Edit an existing mode to add new responsibilities</suggest>
|
||||
<suggest>Fix issues in an existing mode</suggest>
|
||||
<suggest>Enhance an existing mode with better workflows</suggest>
|
||||
</follow_up>
|
||||
</ask_user_question>
|
||||
</clarification_question>
|
||||
</step>
|
||||
|
||||
<step number="2a">
|
||||
<title>Resolve Mode Source (Workspace vs Global)</title>
|
||||
<description>
|
||||
When the user asks about a specific mode by name/slug (including phrases like "global mode"), resolve where that mode is defined
|
||||
before doing broad repository searches.
|
||||
</description>
|
||||
<resolution_order>
|
||||
<step>
|
||||
Check the workspace override first by reading <file>.roomodes</file>.
|
||||
</step>
|
||||
<step>
|
||||
If not present (or the user explicitly requests global scope), inspect the global custom modes settings file.
|
||||
Note: its exact path is determined by the extension at runtime (do not hardcode a machine-specific path).
|
||||
</step>
|
||||
<step>
|
||||
If the mode is workspace-scoped, read its instruction directory <file>.roo/rules-[mode-slug]/</file>.
|
||||
</step>
|
||||
</resolution_order>
|
||||
<early_stop>
|
||||
If the mode entry is found in either <file>.roomodes</file> or the global file, proceed directly to analysis/edits without additional discovery.
|
||||
</early_stop>
|
||||
</step>
|
||||
</initial_determination>
|
||||
|
||||
<workflow_branches>
|
||||
<branch name="create_new_mode">
|
||||
<step number="3.1">
|
||||
<title>Gather Requirements for New Mode</title>
|
||||
<description>
|
||||
Understand what the user wants the new mode to accomplish
|
||||
</description>
|
||||
<actions>
|
||||
<action>Ask about the mode's primary purpose and use cases</action>
|
||||
<action>Identify what types of tasks the mode should handle</action>
|
||||
<action>Determine what repository access and permissions the mode needs</action>
|
||||
<action>Clarify any special behaviors or restrictions</action>
|
||||
</actions>
|
||||
<example>
|
||||
<ask_user_question>
|
||||
<question>What is the primary purpose of this new mode? What types of tasks should it handle?</question>
|
||||
<follow_up>
|
||||
<suggest>A mode for writing and maintaining documentation</suggest>
|
||||
<suggest>A mode for database schema design and migrations</suggest>
|
||||
<suggest>A mode for API endpoint development and testing</suggest>
|
||||
<suggest>A mode for performance optimization and profiling</suggest>
|
||||
</follow_up>
|
||||
</ask_user_question>
|
||||
</example>
|
||||
</step>
|
||||
|
||||
<step number="3.2">
|
||||
<title>Design Mode Configuration</title>
|
||||
<description>
|
||||
Create the mode definition with all required fields
|
||||
</description>
|
||||
|
||||
<scope_selection>
|
||||
<rule>Default to workspace-scoped modes unless the user explicitly requests a global mode.</rule>
|
||||
<global_mode_trigger>
|
||||
User asks for a mode to be available across all workspaces, or explicitly mentions the global modes file.
|
||||
</global_mode_trigger>
|
||||
<workspace_mode_trigger>
|
||||
User asks for a mode for this repo/project only, or wants to commit/share the mode with the repository.
|
||||
</workspace_mode_trigger>
|
||||
</scope_selection>
|
||||
<required_fields>
|
||||
<field name="slug">
|
||||
<description>Unique identifier (lowercase, hyphens allowed)</description>
|
||||
<best_practice>Keep it short and descriptive (e.g., "api-dev", "docs-writer")</best_practice>
|
||||
</field>
|
||||
<field name="name">
|
||||
<description>Display name with optional emoji</description>
|
||||
<best_practice>Use an emoji that represents the mode's purpose</best_practice>
|
||||
</field>
|
||||
<field name="roleDefinition">
|
||||
<description>Detailed description of the mode's role and expertise</description>
|
||||
<best_practice>
|
||||
Start with "You are Roo Code, a [specialist type]..."
|
||||
List specific areas of expertise
|
||||
Mention key technologies or methodologies
|
||||
</best_practice>
|
||||
</field>
|
||||
<field name="groups">
|
||||
<description>Permission groups the mode can access</description>
|
||||
<note>
|
||||
The concrete group names and any nesting structure are runtime-defined and may evolve.
|
||||
Treat these as conceptual categories and map them to the closest available equivalents.
|
||||
</note>
|
||||
<options>
|
||||
<option name="read">File reading and searching</option>
|
||||
<option name="edit">File editing (can be restricted by regex)</option>
|
||||
<option name="command">Command execution</option>
|
||||
<option name="browser">Browser interaction</option>
|
||||
<option name="mcp">MCP servers</option>
|
||||
</options>
|
||||
</field>
|
||||
</required_fields>
|
||||
<recommended_fields>
|
||||
<field name="description">
|
||||
<description>Short human-readable summary (aim ~5 words)</description>
|
||||
<best_practice>Keep it scannable and concrete</best_practice>
|
||||
</field>
|
||||
<field name="whenToUse">
|
||||
<description>Clear description for the Orchestrator</description>
|
||||
<best_practice>Explain specific scenarios and task types</best_practice>
|
||||
</field>
|
||||
</recommended_fields>
|
||||
<important_note>
|
||||
Prefer keeping substantial mode guidance in XML files within <code>.roo/rules-[mode-slug]/</code>.
|
||||
The underlying mode system supports <code>customInstructions</code>, but large instruction blocks there are easier to duplicate/drift.
|
||||
Use <code>customInstructions</code> only for brief "glue" text when needed.
|
||||
|
||||
Note: the underlying mode system supports a <code>customInstructions</code> field,
|
||||
but this repository intentionally keeps detailed instructions in
|
||||
<code>.roo/rules-[mode-slug]/</code> XML files to avoid duplication and drift.
|
||||
</important_note>
|
||||
</step>
|
||||
|
||||
<step number="3.3">
|
||||
<title>Implement File Restrictions</title>
|
||||
<description>
|
||||
Configure appropriate file access permissions
|
||||
</description>
|
||||
<example>
|
||||
<comment>Restrict edit access to specific file types</comment>
|
||||
<code>
|
||||
groups:
|
||||
- read
|
||||
- - edit
|
||||
- fileRegex: \.(md|txt|rst)$
|
||||
description: Documentation files only
|
||||
- command
|
||||
</code>
|
||||
</example>
|
||||
<guidelines>
|
||||
<guideline>Use regex patterns to limit file editing scope</guideline>
|
||||
<guideline>Provide clear descriptions for restrictions</guideline>
|
||||
<guideline>Consider the principle of least privilege</guideline>
|
||||
</guidelines>
|
||||
</step>
|
||||
|
||||
<step number="3.4">
|
||||
<title>Create XML Instruction Files</title>
|
||||
<description>
|
||||
Design structured instruction files in .roo/rules-[mode-slug]/
|
||||
</description>
|
||||
<file_structure>
|
||||
<file name="1_workflow.xml">Main workflow and step-by-step processes</file>
|
||||
<file name="2_best_practices.xml">Guidelines and conventions</file>
|
||||
<file name="3_common_patterns.xml">Reusable code patterns and examples</file>
|
||||
<file name="4_decision_guidance.xml">Decision criteria and guardrails</file>
|
||||
<file name="5_examples.xml">Complete workflow examples</file>
|
||||
</file_structure>
|
||||
<xml_best_practices>
|
||||
<practice>Use semantic tag names that describe content</practice>
|
||||
<practice>Nest tags hierarchically for better organization</practice>
|
||||
<practice>Include code examples in CDATA sections when needed</practice>
|
||||
<practice>Add comments to explain complex sections</practice>
|
||||
</xml_best_practices>
|
||||
</step>
|
||||
</branch>
|
||||
|
||||
<branch name="edit_existing_mode">
|
||||
<step number="4.1">
|
||||
<title>Immerse in Existing Mode</title>
|
||||
<description>
|
||||
Fully understand the existing mode before making any changes
|
||||
</description>
|
||||
<actions>
|
||||
<action>Locate and read the mode configuration in .roomodes</action>
|
||||
<action>When global scope is relevant, locate and read the global custom modes settings file and compare slugs for precedence</action>
|
||||
<action>Read all XML instruction files in .roo/rules-[mode-slug]/</action>
|
||||
<action>Analyze the mode's current scope, permissions, and limitations</action>
|
||||
<action>Understand the mode's role in the broader ecosystem</action>
|
||||
</actions>
|
||||
<questions_to_ask>
|
||||
<ask_user_question>
|
||||
<question>What specific aspects of the mode would you like to change or enhance?</question>
|
||||
<follow_up>
|
||||
<suggest>Adjust permissions or restrictions</suggest>
|
||||
<suggest>Fix issues with current workflows or instructions</suggest>
|
||||
<suggest>Improve the mode's roleDefinition or whenToUse description</suggest>
|
||||
<suggest>Enhance XML instructions for better clarity</suggest>
|
||||
</follow_up>
|
||||
</ask_user_question>
|
||||
</questions_to_ask>
|
||||
</step>
|
||||
|
||||
<step number="4.2">
|
||||
<title>Analyze Change Impact</title>
|
||||
<description>
|
||||
Understand how proposed changes will affect the mode
|
||||
</description>
|
||||
<analysis_areas>
|
||||
<area>Compatibility with existing workflows</area>
|
||||
<area>Impact on file permissions and capability access</area>
|
||||
<area>Consistency with mode's core purpose</area>
|
||||
<area>Integration with other modes</area>
|
||||
</analysis_areas>
|
||||
<review_cleanup_checklist>
|
||||
<item>Role and scope: roleDefinition matches actual scope and permissions; remove scope creep</item>
|
||||
<item>Orchestrator routing: whenToUse/whenNotToUse are explicit and distinct from other modes</item>
|
||||
<item>Permissions: groups and fileRegex follow least-privilege and match instructions</item>
|
||||
<item>Instructions hygiene: no contradictions or duplicates across XML files</item>
|
||||
<item>Naming consistency: tag names and terminology are consistent</item>
|
||||
<item>Deprecated content: remove legacy fields (e.g., customInstructions in .roomodes)</item>
|
||||
<item>Boundaries: clear handoffs to other modes; no overlapping responsibilities</item>
|
||||
</review_cleanup_checklist>
|
||||
<duplication_and_contradiction_scan>
|
||||
<approach>Search for repeated guidance and conflicting directives across files</approach>
|
||||
</duplication_and_contradiction_scan>
|
||||
<validation_questions>
|
||||
<ask_user_question>
|
||||
<question>I've analyzed the existing mode. Here's what I understand about your requested changes. Is this correct?</question>
|
||||
<follow_up>
|
||||
<suggest>Yes, that's exactly what I want to change</suggest>
|
||||
<suggest>Mostly correct, but let me clarify some details</suggest>
|
||||
<suggest>No, I meant something different</suggest>
|
||||
<suggest>I'd like to add additional changes</suggest>
|
||||
</follow_up>
|
||||
</ask_user_question>
|
||||
</validation_questions>
|
||||
</step>
|
||||
|
||||
<step number="4.3">
|
||||
<title>Plan Modifications</title>
|
||||
<description>
|
||||
Create a detailed plan for modifying the mode
|
||||
</description>
|
||||
<planning_steps>
|
||||
<step>Identify which files need to be modified</step>
|
||||
<step>Determine if new XML instruction files are needed</step>
|
||||
<step>Check for potential conflicts or contradictions</step>
|
||||
<step>Plan the order of changes for minimal disruption</step>
|
||||
</planning_steps>
|
||||
<refactor_strategy>
|
||||
<normalize>
|
||||
<rule>Consolidate overlapping instructions into a single source of truth</rule>
|
||||
<rule>Align with XML best practices (semantic tags, hierarchical nesting)</rule>
|
||||
<rule>Standardize whenToUse/whenNotToUse language and boundaries</rule>
|
||||
<rule>Centralize preamble rules and autonomy calibration</rule>
|
||||
</normalize>
|
||||
<permissions>
|
||||
<rule>Tighten fileRegex to least-privilege; add clear descriptions</rule>
|
||||
<rule>Ensure instructions match configured permissions</rule>
|
||||
</permissions>
|
||||
<structure>
|
||||
<rule>Split overly long files; ensure 6_error_handling and 7_communication are present or updated</rule>
|
||||
</structure>
|
||||
<examples_and_tests>
|
||||
<rule>Update 5_examples.xml to reflect new workflows and refactors</rule>
|
||||
<rule>Include before/after diffs where helpful</rule>
|
||||
</examples_and_tests>
|
||||
</refactor_strategy>
|
||||
<artifacts_to_update>
|
||||
<item>.roomodes: roleDefinition and whenToUse</item>
|
||||
<item>.roo/rules-[slug]/ XML instruction files</item>
|
||||
<item>Examples and quick_reference sections</item>
|
||||
</artifacts_to_update>
|
||||
</step>
|
||||
|
||||
<step number="4.4">
|
||||
<title>Silent Self-Reflection Rubric</title>
|
||||
<description>Privately evaluate the planned changes against a 5–7 category rubric before implementation</description>
|
||||
<rubric>
|
||||
<category>Cohesion across files</category>
|
||||
<category>Permissions and file restrictions (least privilege)</category>
|
||||
<category>Orchestrator fit (whenToUse/whenNotToUse clarity)</category>
|
||||
<category>XML structure and naming consistency</category>
|
||||
<category>Mode boundaries and handoff points</category>
|
||||
<category>Examples and testability</category>
|
||||
</rubric>
|
||||
<instruction>Iterate on the plan until it passes the rubric; do not expose the rubric to the user</instruction>
|
||||
</step>
|
||||
|
||||
<step number="4.5">
|
||||
<title>Implement Changes</title>
|
||||
<description>
|
||||
Apply the planned modifications to the mode
|
||||
</description>
|
||||
<implementation_order>
|
||||
<change>Update .roomodes configuration if needed</change>
|
||||
<change>Modify existing XML instruction files</change>
|
||||
<change>Create new XML instruction files if required</change>
|
||||
<change>Update examples and documentation</change>
|
||||
</implementation_order>
|
||||
<cleanup_tasks>
|
||||
<task>Remove duplicate or contradictory instruction blocks across XML files</task>
|
||||
<task>Delete or migrate deprecated fields (e.g., customInstructions in .roomodes)</task>
|
||||
<task>Tighten fileRegex patterns and add clear descriptions</task>
|
||||
<task>Normalize tag names, terminology, and structure</task>
|
||||
<task>Ensure whenToUse/whenNotToUse and handoff rules are explicit</task>
|
||||
</cleanup_tasks>
|
||||
<verification_steps>
|
||||
<step>Validate file restriction patterns against the intended file sets</step>
|
||||
<step>Confirm permissions match instruction expectations</step>
|
||||
<step>Re-run validation (section 5) and testing (section 6)</step>
|
||||
<step>Scan the repository for legacy references and remove/modernize as needed</step>
|
||||
</verification_steps>
|
||||
</step>
|
||||
</branch>
|
||||
</workflow_branches>
|
||||
|
||||
<validation_and_cohesion>
|
||||
<step number="5">
|
||||
<title>Validate Cohesion and Consistency</title>
|
||||
<description>
|
||||
Ensure all changes are cohesive and don't contradict each other
|
||||
</description>
|
||||
<validation_checks>
|
||||
<check type="configuration">
|
||||
<item>Mode slug follows naming conventions</item>
|
||||
<item>File restrictions align with mode purpose (least privilege)</item>
|
||||
<item>Permissions are appropriate</item>
|
||||
<item>whenToUse clearly differentiates from other modes</item>
|
||||
</check>
|
||||
<check type="instructions">
|
||||
<item>All XML files follow consistent structure</item>
|
||||
<item>No contradicting instructions between files; contradiction hierarchy and resolutions documented</item>
|
||||
<item>Examples align with stated workflows</item>
|
||||
<item>Instructions match granted permissions and file restrictions</item>
|
||||
</check>
|
||||
<check type="integration">
|
||||
<item>Mode integrates well with Orchestrator</item>
|
||||
<item>Clear boundaries with other modes</item>
|
||||
<item>Handoff points are well-defined</item>
|
||||
</check>
|
||||
</validation_checks>
|
||||
<cohesion_questions>
|
||||
<ask_user_question>
|
||||
<question>I've completed the validation checks. Would you like me to review any specific aspect in more detail?</question>
|
||||
<follow_up>
|
||||
<suggest>Review the file permission patterns</suggest>
|
||||
<suggest>Check for workflow contradictions</suggest>
|
||||
<suggest>Verify integration with other modes</suggest>
|
||||
<suggest>Everything looks good, proceed to testing</suggest>
|
||||
</follow_up>
|
||||
</ask_user_question>
|
||||
</cohesion_questions>
|
||||
</step>
|
||||
|
||||
<step number="6">
|
||||
<title>Test and Refine</title>
|
||||
<description>
|
||||
Verify the mode works as intended
|
||||
</description>
|
||||
<checklist>
|
||||
<item>Mode appears in the mode list</item>
|
||||
<item>File restrictions work correctly</item>
|
||||
<item>Instructions are clear and actionable</item>
|
||||
<item>Mode integrates well with Orchestrator</item>
|
||||
<item>All examples are accurate and helpful</item>
|
||||
<item>Changes don't break existing functionality (for edits)</item>
|
||||
<item>New behavior works as expected</item>
|
||||
</checklist>
|
||||
</step>
|
||||
</validation_and_cohesion>
|
||||
|
||||
<quick_reference>
|
||||
<action>Create mode in .roomodes for project-specific modes</action>
|
||||
<action>Create mode in the global custom modes settings file for system-wide modes (path is environment-specific)</action>
|
||||
<action>Verify the .roo folder structure contains expected rule directories and XML files</action>
|
||||
<action>Validate file regex patterns against the intended file sets (avoid overbroad matches)</action>
|
||||
<action>Find existing mode implementations and patterns to reuse</action>
|
||||
<action>Read all XML files in a mode directory to understand its structure</action>
|
||||
<action>Always validate changes for cohesion and consistency</action>
|
||||
</quick_reference>
|
||||
</mode_management_workflow>
|
||||
@@ -0,0 +1,240 @@
|
||||
<xml_structuring_best_practices>
|
||||
<overview>
|
||||
XML tags help LLMs parse prompts more accurately, leading to higher-quality outputs.
|
||||
This guide covers best practices for structuring mode instructions using XML.
|
||||
</overview>
|
||||
|
||||
<why_use_xml_tags>
|
||||
<benefit type="clarity">
|
||||
Clearly separate different parts of your instructions and ensure well-structured content
|
||||
</benefit>
|
||||
<benefit type="accuracy">
|
||||
Reduce errors caused by the model misinterpreting parts of your instructions
|
||||
</benefit>
|
||||
<benefit type="flexibility">
|
||||
Easily find, add, remove, or modify parts of instructions without rewriting everything
|
||||
</benefit>
|
||||
<benefit type="parseability">
|
||||
Having the model use XML tags in its output makes it easier to extract specific parts of responses
|
||||
</benefit>
|
||||
</why_use_xml_tags>
|
||||
|
||||
<core_principles>
|
||||
<principle name="consistency">
|
||||
<description>Use the same tag names throughout your instructions</description>
|
||||
<example>
|
||||
Always use <step> for workflow steps, not sometimes <action> or <task>
|
||||
</example>
|
||||
</principle>
|
||||
|
||||
<principle name="semantic_naming">
|
||||
<description>Tag names should clearly describe their content</description>
|
||||
<good_examples>
|
||||
<tag>detailed_steps</tag>
|
||||
<tag>error_handling</tag>
|
||||
<tag>validation_rules</tag>
|
||||
</good_examples>
|
||||
<bad_examples>
|
||||
<tag>stuff</tag>
|
||||
<tag>misc</tag>
|
||||
<tag>data1</tag>
|
||||
</bad_examples>
|
||||
</principle>
|
||||
|
||||
<principle name="hierarchical_nesting">
|
||||
<description>Nest tags to show relationships and structure</description>
|
||||
<example>
|
||||
<workflow>
|
||||
<phase name="preparation">
|
||||
<step>Gather requirements</step>
|
||||
<step>Validate inputs</step>
|
||||
</phase>
|
||||
<phase name="execution">
|
||||
<step>Process data</step>
|
||||
<step>Generate output</step>
|
||||
</phase>
|
||||
</workflow>
|
||||
</example>
|
||||
</principle>
|
||||
</core_principles>
|
||||
|
||||
<common_tag_patterns>
|
||||
<pattern name="workflow_structure">
|
||||
<usage>For step-by-step processes</usage>
|
||||
<template>
|
||||
<workflow>
|
||||
<overview>High-level description</overview>
|
||||
<prerequisites>
|
||||
<prerequisite>Required condition 1</prerequisite>
|
||||
<prerequisite>Required condition 2</prerequisite>
|
||||
</prerequisites>
|
||||
<steps>
|
||||
<step number="1">
|
||||
<title>Step Title</title>
|
||||
<description>What this step accomplishes</description>
|
||||
<actions>
|
||||
<action>Specific action to take</action>
|
||||
</actions>
|
||||
<validation>How to verify success</validation>
|
||||
</step>
|
||||
</steps>
|
||||
</workflow>
|
||||
</template>
|
||||
</pattern>
|
||||
|
||||
<pattern name="examples_structure">
|
||||
<usage>For providing code examples and demonstrations</usage>
|
||||
<template>
|
||||
<examples>
|
||||
<example name="descriptive_name">
|
||||
<description>What this example demonstrates</description>
|
||||
<context>When to use this approach</context>
|
||||
<code language="typescript">
|
||||
// Your code example here
|
||||
</code>
|
||||
<explanation>
|
||||
Key points about the implementation
|
||||
</explanation>
|
||||
</example>
|
||||
</examples>
|
||||
</template>
|
||||
</pattern>
|
||||
|
||||
<pattern name="guidelines_structure">
|
||||
<usage>For rules and best practices</usage>
|
||||
<template>
|
||||
<guidelines category="category_name">
|
||||
<guideline priority="high">
|
||||
<rule>The specific rule or guideline</rule>
|
||||
<rationale>Why this is important</rationale>
|
||||
<exceptions>When this doesn't apply</exceptions>
|
||||
</guideline>
|
||||
</guidelines>
|
||||
</template>
|
||||
</pattern>
|
||||
|
||||
<pattern name="decision_guidance_structure">
|
||||
<usage>For documenting decision criteria and guardrails</usage>
|
||||
<template>
|
||||
<decision_guidance>
|
||||
<principles>
|
||||
<principle>Do not include runtime implementation details (no function names, command names, UI entry points, or execution syntax)</principle>
|
||||
<principle>Prefer the smallest change that satisfies the request</principle>
|
||||
<principle>Prefer a single source of truth; avoid duplicated rules across files</principle>
|
||||
<principle>Ask a clarifying question only when critical ambiguity remains</principle>
|
||||
</principles>
|
||||
|
||||
<constraints>
|
||||
Constraints and guardrails (e.g., permissions, file restrictions, or other limits).
|
||||
</constraints>
|
||||
|
||||
<validation>
|
||||
What to verify after changes (cohesion, examples updated, boundaries clear).
|
||||
</validation>
|
||||
</decision_guidance>
|
||||
</template>
|
||||
</pattern>
|
||||
</common_tag_patterns>
|
||||
|
||||
<formatting_guidelines>
|
||||
<guideline name="indentation">
|
||||
Use consistent indentation (2 or 4 spaces) for nested elements
|
||||
</guideline>
|
||||
<guideline name="line_breaks">
|
||||
Add line breaks between major sections for readability
|
||||
</guideline>
|
||||
<guideline name="comments">
|
||||
Use XML comments <!-- like this --> to explain complex sections
|
||||
</guideline>
|
||||
<guideline name="cdata_sections">
|
||||
Use CDATA for code blocks or content with special characters:
|
||||
<code>your code here</code>
|
||||
</guideline>
|
||||
<guideline name="attributes_vs_elements">
|
||||
Use attributes for metadata, elements for content:
|
||||
<example type="good">
|
||||
<step number="1" priority="high">
|
||||
<description>The actual step content</description>
|
||||
</step>
|
||||
</example>
|
||||
</guideline>
|
||||
<guideline name="verbosity">
|
||||
Keep narrative outputs concise; reserve detailed exposition for code, diffs, and structured outputs. Prefer readable, maintainable code with clear names; avoid one-liners unless explicitly requested.
|
||||
</guideline>
|
||||
</formatting_guidelines>
|
||||
|
||||
<anti_patterns>
|
||||
<anti_pattern name="flat_structure">
|
||||
<description>Avoid completely flat structures without hierarchy</description>
|
||||
<bad>
|
||||
<instructions>
|
||||
|
||||
<item1>Do this</item1>
|
||||
|
||||
<item2>Then this</item2>
|
||||
|
||||
<item3>Finally this</item3>
|
||||
|
||||
</instructions>
|
||||
</bad>
|
||||
<good>
|
||||
<instructions>
|
||||
<steps>
|
||||
<step order="1">Do this</step>
|
||||
<step order="2">Then this</step>
|
||||
<step order="3">Finally this</step>
|
||||
</steps>
|
||||
</instructions>
|
||||
</good>
|
||||
</anti_pattern>
|
||||
|
||||
<anti_pattern name="inconsistent_naming">
|
||||
<description>Don't mix naming conventions</description>
|
||||
<bad>
|
||||
Mixing camelCase, snake_case, and kebab-case in tag names
|
||||
</bad>
|
||||
<good>
|
||||
Pick one convention (preferably snake_case for XML) and stick to it
|
||||
</good>
|
||||
</anti_pattern>
|
||||
|
||||
<anti_pattern name="overly_generic_tags">
|
||||
<description>Avoid tags that don't convey meaning</description>
|
||||
<bad>data, info, stuff, thing, item</bad>
|
||||
<good>user_input, validation_result, error_message, configuration</good>
|
||||
</anti_pattern>
|
||||
<anti_pattern name="over_clarifying_questions">
|
||||
<description>Avoid asking the user to confirm obvious next steps on straightforward tasks</description>
|
||||
<bad>Asking multiple clarifying questions before acting when the task is simple</bad>
|
||||
<good>Proceed when next steps are clear; ask only when critical ambiguity remains; document assumptions</good>
|
||||
</anti_pattern>
|
||||
|
||||
<anti_pattern name="excessive_searching">
|
||||
<description>Avoid repetitive or redundant searches when the relevant target is already identified</description>
|
||||
<bad>Running multiple identical searches instead of acting</bad>
|
||||
<good>Stop once the change is clearly identified; then implement</good>
|
||||
</anti_pattern>
|
||||
|
||||
<anti_pattern name="over_specifying_runtime_behavior">
|
||||
<description>Avoid duplicating runtime behavior that is already defined elsewhere</description>
|
||||
<bad>Documenting execution constraints, operation ordering, or invocation details</bad>
|
||||
<good>Focus on intent, artifacts, decision criteria, and validation expectations</good>
|
||||
</anti_pattern>
|
||||
</anti_patterns>
|
||||
|
||||
<integration_tips>
|
||||
<tip>
|
||||
Reference XML content in instructions:
|
||||
"Using the workflow defined in <workflow> tags..."
|
||||
</tip>
|
||||
<tip>
|
||||
Combine XML structure with other techniques like multishot prompting
|
||||
</tip>
|
||||
<tip>
|
||||
Use XML tags in expected outputs to make parsing easier
|
||||
</tip>
|
||||
<tip>
|
||||
Create reusable XML templates for common patterns
|
||||
</tip>
|
||||
</integration_tips>
|
||||
</xml_structuring_best_practices>
|
||||
@@ -0,0 +1,307 @@
|
||||
<mode_configuration_patterns>
|
||||
<overview>
|
||||
Common patterns and templates for creating different types of modes, with examples from existing modes in the Roo-Code software.
|
||||
</overview>
|
||||
|
||||
<mode_types>
|
||||
<type name="specialist_mode">
|
||||
<description>
|
||||
Modes focused on specific technical domains or tasks
|
||||
</description>
|
||||
<characteristics>
|
||||
<characteristic>Deep expertise in a particular area</characteristic>
|
||||
<characteristic>Restricted file access based on domain</characteristic>
|
||||
<characteristic>Specialized workflows and decision criteria</characteristic>
|
||||
</characteristics>
|
||||
<example_template>
|
||||
- slug: api-specialist
|
||||
name: 🔌 API Specialist
|
||||
roleDefinition: >-
|
||||
You are Roo Code, an API development specialist with expertise in:
|
||||
- RESTful API design and implementation
|
||||
- GraphQL schema design
|
||||
- API documentation with OpenAPI/Swagger
|
||||
- Authentication and authorization patterns
|
||||
- Rate limiting and caching strategies
|
||||
- API versioning and deprecation
|
||||
|
||||
You ensure APIs are:
|
||||
- Well-documented and discoverable
|
||||
- Following REST principles or GraphQL best practices
|
||||
- Secure and performant
|
||||
- Properly versioned and maintainable
|
||||
whenToUse: >-
|
||||
Use this mode when designing, implementing, or refactoring APIs.
|
||||
This includes creating new endpoints, updating API documentation,
|
||||
implementing authentication, or optimizing API performance.
|
||||
groups:
|
||||
- read
|
||||
- - edit
|
||||
- fileRegex: (api/.*\.(ts|js)|.*\.openapi\.yaml|.*\.graphql|docs/api/.*)$
|
||||
description: API implementation files, OpenAPI specs, and API documentation
|
||||
- command
|
||||
- mcp
|
||||
</example_template>
|
||||
</type>
|
||||
|
||||
<type name="workflow_mode">
|
||||
<description>
|
||||
Modes that guide users through multi-step processes
|
||||
</description>
|
||||
<characteristics>
|
||||
<characteristic>Step-by-step workflow guidance</characteristic>
|
||||
<characteristic>Heavy use of focused clarifying questions</characteristic>
|
||||
<characteristic>Process validation at each step</characteristic>
|
||||
</characteristics>
|
||||
<example_template>
|
||||
- slug: migration-guide
|
||||
name: 🔄 Migration Guide
|
||||
roleDefinition: >-
|
||||
You are Roo Code, a migration specialist who guides users through
|
||||
complex migration processes:
|
||||
- Database schema migrations
|
||||
- Framework version upgrades
|
||||
- API version migrations
|
||||
- Dependency updates
|
||||
- Breaking change resolutions
|
||||
|
||||
You provide:
|
||||
- Step-by-step migration plans
|
||||
- Automated migration scripts
|
||||
- Rollback strategies
|
||||
- Testing approaches for migrations
|
||||
whenToUse: >-
|
||||
Use this mode when performing any kind of migration or upgrade.
|
||||
This mode will analyze the current state, plan the migration,
|
||||
and guide you through each step with validation.
|
||||
groups:
|
||||
- read
|
||||
- edit
|
||||
- command
|
||||
</example_template>
|
||||
</type>
|
||||
|
||||
<type name="analysis_mode">
|
||||
<description>
|
||||
Modes focused on code analysis and reporting
|
||||
</description>
|
||||
<characteristics>
|
||||
<characteristic>Read-heavy operations</characteristic>
|
||||
<characteristic>Limited or no edit permissions</characteristic>
|
||||
<characteristic>Comprehensive reporting outputs</characteristic>
|
||||
</characteristics>
|
||||
<example_template>
|
||||
- slug: security-auditor
|
||||
name: 🔒 Security Auditor
|
||||
roleDefinition: >-
|
||||
You are Roo Code, a security analysis specialist focused on:
|
||||
- Identifying security vulnerabilities
|
||||
- Analyzing authentication and authorization
|
||||
- Reviewing data validation and sanitization
|
||||
- Checking for common security anti-patterns
|
||||
- Evaluating dependency vulnerabilities
|
||||
- Assessing API security
|
||||
|
||||
You provide detailed security reports with:
|
||||
- Vulnerability severity ratings
|
||||
- Specific remediation steps
|
||||
- Security best practice recommendations
|
||||
whenToUse: >-
|
||||
Use this mode to perform security audits on codebases.
|
||||
This mode will analyze code for vulnerabilities, check
|
||||
dependencies, and provide actionable security recommendations.
|
||||
groups:
|
||||
- read
|
||||
- command
|
||||
- - edit
|
||||
- fileRegex: (SECURITY\.md|\.github/security/.*|docs/security/.*)$
|
||||
description: Security documentation files only
|
||||
</example_template>
|
||||
</type>
|
||||
|
||||
<type name="creative_mode">
|
||||
<description>
|
||||
Modes for generating new content or features
|
||||
</description>
|
||||
<characteristics>
|
||||
<characteristic>Broad file creation permissions</characteristic>
|
||||
<characteristic>Template and boilerplate generation</characteristic>
|
||||
<characteristic>Interactive design process</characteristic>
|
||||
</characteristics>
|
||||
<example_template>
|
||||
- slug: component-designer
|
||||
name: 🎨 Component Designer
|
||||
roleDefinition: >-
|
||||
You are Roo Code, a UI component design specialist who creates:
|
||||
- Reusable React/Vue/Angular components
|
||||
- Component documentation and examples
|
||||
- Storybook stories
|
||||
- Unit tests for components
|
||||
- Accessibility-compliant interfaces
|
||||
|
||||
You follow design system principles and ensure components are:
|
||||
- Highly reusable and composable
|
||||
- Well-documented with examples
|
||||
- Fully tested
|
||||
- Accessible (WCAG compliant)
|
||||
- Performance optimized
|
||||
whenToUse: >-
|
||||
Use this mode when creating new UI components or refactoring
|
||||
existing ones. This mode helps design component APIs, implement
|
||||
the components, and create comprehensive documentation.
|
||||
groups:
|
||||
- read
|
||||
- - edit
|
||||
- fileRegex: (components/.*|stories/.*|__tests__/.*\.test\.(tsx?|jsx?))$
|
||||
description: Component files, stories, and component tests
|
||||
- browser
|
||||
- command
|
||||
</example_template>
|
||||
</type>
|
||||
</mode_types>
|
||||
|
||||
<autonomy_configuration>
|
||||
<overview>Configuration patterns to keep modes focused, cohesive, and clearly scoped</overview>
|
||||
<defaults>
|
||||
<cohesion>Prefer a single source of truth for each rule; avoid duplicated instructions</cohesion>
|
||||
<scope>Prefer least privilege; keep file restrictions aligned with purpose</scope>
|
||||
<clarity>Define acceptance criteria and validation gates for typical tasks</clarity>
|
||||
<handoffs>Define explicit boundaries and handoff points to other modes</handoffs>
|
||||
<verbosity>Keep narrative brief; reserve detail for structured outputs and diffs</verbosity>
|
||||
</defaults>
|
||||
<per_mode_guidance>
|
||||
<mode type="specialist_mode">
|
||||
<notes>Tight scope, least privilege, clear boundaries; prefer small targeted changes</notes>
|
||||
</mode>
|
||||
<mode type="workflow_mode">
|
||||
<notes>Step-by-step process with validation gates; ask clarifying questions only when necessary</notes>
|
||||
</mode>
|
||||
<mode type="analysis_mode">
|
||||
<notes>Read-heavy; edits typically constrained to reporting or documentation outputs</notes>
|
||||
</mode>
|
||||
<mode type="creative_mode">
|
||||
<notes>Broader creation scope; ensure examples and tests are included when applicable</notes>
|
||||
</mode>
|
||||
</per_mode_guidance>
|
||||
</autonomy_configuration>
|
||||
|
||||
<permission_patterns>
|
||||
<pattern name="documentation_only">
|
||||
<description>For modes that only work with documentation</description>
|
||||
<configuration>
|
||||
groups:
|
||||
- read
|
||||
- - edit
|
||||
- fileRegex: \.(md|mdx|rst|txt)$
|
||||
description: Documentation files only
|
||||
</configuration>
|
||||
</pattern>
|
||||
|
||||
<pattern name="test_focused">
|
||||
<description>For modes that work with test files</description>
|
||||
<configuration>
|
||||
groups:
|
||||
- read
|
||||
- command
|
||||
- - edit
|
||||
- fileRegex: (__tests__/.*|__mocks__/.*|.*\.test\.(ts|tsx|js|jsx)$|.*\.spec\.(ts|tsx|js|jsx)$)
|
||||
description: Test files and mocks
|
||||
</configuration>
|
||||
</pattern>
|
||||
|
||||
<pattern name="config_management">
|
||||
<description>For modes that manage configuration</description>
|
||||
<configuration>
|
||||
groups:
|
||||
- read
|
||||
- - edit
|
||||
- fileRegex: (.*\.config\.(js|ts|json)|.*rc\.json|.*\.yaml|.*\.yml|\.env\.example)$
|
||||
description: Configuration files (not .env)
|
||||
</configuration>
|
||||
</pattern>
|
||||
|
||||
<pattern name="full_stack">
|
||||
<description>For modes that need broad access</description>
|
||||
<configuration>
|
||||
groups:
|
||||
- read
|
||||
- edit # No restrictions
|
||||
- command
|
||||
- browser
|
||||
- mcp
|
||||
</configuration>
|
||||
</pattern>
|
||||
</permission_patterns>
|
||||
|
||||
<naming_conventions>
|
||||
<convention category="slug">
|
||||
<rule>Use lowercase with hyphens</rule>
|
||||
<good>api-dev, test-writer, docs-manager</good>
|
||||
<bad>apiDev, test_writer, DocsManager</bad>
|
||||
</convention>
|
||||
|
||||
<convention category="name">
|
||||
<rule>Use title case with descriptive emoji</rule>
|
||||
<good>🔧 API Developer, 📝 Documentation Writer</good>
|
||||
<bad>api developer, DOCUMENTATION WRITER</bad>
|
||||
</convention>
|
||||
|
||||
<convention category="emoji_selection">
|
||||
<common_emojis>
|
||||
<emoji meaning="testing">🧪</emoji>
|
||||
<emoji meaning="documentation">📝</emoji>
|
||||
<emoji meaning="design">🎨</emoji>
|
||||
<emoji meaning="debugging">🪲</emoji>
|
||||
<emoji meaning="building">🏗️</emoji>
|
||||
<emoji meaning="security">🔒</emoji>
|
||||
<emoji meaning="api">🔌</emoji>
|
||||
<emoji meaning="database">🗄️</emoji>
|
||||
<emoji meaning="performance">⚡</emoji>
|
||||
<emoji meaning="configuration">⚙️</emoji>
|
||||
</common_emojis>
|
||||
</convention>
|
||||
</naming_conventions>
|
||||
|
||||
<integration_guidelines>
|
||||
<guideline name="orchestrator_compatibility">
|
||||
<description>Ensure whenToUse/whenNotToUse are clear for Orchestrator mode</description>
|
||||
<checklist>
|
||||
<item>Specify concrete task types the mode handles</item>
|
||||
<item>Include trigger keywords or phrases</item>
|
||||
<item>Differentiate from similar modes</item>
|
||||
<item>Mention specific file types or areas</item>
|
||||
<item>Define whenNotToUse with negative triggers and explicit handoffs</item>
|
||||
<item>State stop/ask/handoff rules</item>
|
||||
<item>State default verbosity policy (low narrative; verbose diffs)</item>
|
||||
</checklist>
|
||||
</guideline>
|
||||
|
||||
<guideline name="stop_and_handoff_rules">
|
||||
<description>Define explicit stop conditions, confirmation thresholds, and handoff/ask triggers</description>
|
||||
<checklist>
|
||||
<item>Done-ness: acceptance criteria and validation gates are defined</item>
|
||||
<item>Handoff rules to other modes or “ask a clarifying question” conditions are explicit</item>
|
||||
<item>Boundaries, risks, and validation gates are documented</item>
|
||||
</checklist>
|
||||
</guideline>
|
||||
|
||||
<guideline name="verbosity_policy">
|
||||
<description>Set verbosity defaults to keep narrative short and code edits clear</description>
|
||||
<checklist>
|
||||
<item>Low narrative verbosity in status/progress text</item>
|
||||
<item>High detail only inside code/diffs and structured outputs</item>
|
||||
<item>Code clarity over cleverness; avoid code-golf and cryptic names</item>
|
||||
</checklist>
|
||||
</guideline>
|
||||
|
||||
<guideline name="mode_boundaries">
|
||||
<description>Define clear boundaries between modes</description>
|
||||
<checklist>
|
||||
<item>Avoid overlapping responsibilities</item>
|
||||
<item>Make handoff points explicit</item>
|
||||
<item>Switch modes when appropriate (mechanism varies)</item>
|
||||
<item>Document mode interactions</item>
|
||||
</checklist>
|
||||
</guideline>
|
||||
</integration_guidelines>
|
||||
</mode_configuration_patterns>
|
||||
@@ -0,0 +1,293 @@
|
||||
<instruction_file_templates>
|
||||
<overview>
|
||||
Templates and examples for creating XML instruction files that provide
|
||||
detailed guidance for each mode's behavior and workflows.
|
||||
|
||||
Requirements:
|
||||
- Do not reference runtime implementation details (function names, command names, UI entry points, or execution syntax).
|
||||
- Do not duplicate operational policies that are already defined by the runtime/system prompt.
|
||||
- Focus on workflow intent, required artifacts, decision criteria, and validation expectations.
|
||||
</overview>
|
||||
|
||||
<file_organization>
|
||||
<principle>Number files to indicate execution order</principle>
|
||||
<principle>Use descriptive names that indicate content</principle>
|
||||
<principle>Keep related instructions together</principle>
|
||||
<standard_structure>
|
||||
<file>1_workflow.xml - Main workflow and processes</file>
|
||||
<file>2_best_practices.xml - Guidelines and conventions</file>
|
||||
<file>3_common_patterns.xml - Reusable code patterns</file>
|
||||
<file>4_decision_guidance.xml - Decision criteria and guardrails</file>
|
||||
<file>5_examples.xml - Complete workflow examples</file>
|
||||
<file>6_error_handling.xml - Error scenarios and recovery</file>
|
||||
<file>7_communication.xml - User interaction guidelines</file>
|
||||
</standard_structure>
|
||||
</file_organization>
|
||||
|
||||
<workflow_file_template>
|
||||
<description>Template for main workflow files (1_workflow.xml)</description>
|
||||
<template>
|
||||
<workflow_instructions>
|
||||
<mode_overview>
|
||||
Brief description of what this mode does and its primary purpose
|
||||
</mode_overview>
|
||||
|
||||
<initialization_steps>
|
||||
<step number="1">
|
||||
<action>Understand the user's request</action>
|
||||
<details>
|
||||
Parse the user's input to identify:
|
||||
- Primary objective
|
||||
- Specific requirements
|
||||
- Constraints or limitations
|
||||
</details>
|
||||
</step>
|
||||
|
||||
<step number="2">
|
||||
<action>Gather necessary context</action>
|
||||
<details>
|
||||
Review the minimal set of repository materials needed to act safely.
|
||||
Prefer extending existing guidance over introducing duplicated rules.
|
||||
</details>
|
||||
</step>
|
||||
</initialization_steps>
|
||||
|
||||
<main_workflow>
|
||||
<phase name="analysis">
|
||||
<description>Analyze the current state and requirements</description>
|
||||
<steps>
|
||||
<step>Identify affected components</step>
|
||||
<step>Assess impact of changes</step>
|
||||
<step>Plan implementation approach</step>
|
||||
</steps>
|
||||
</phase>
|
||||
|
||||
<phase name="implementation">
|
||||
<description>Execute the planned changes</description>
|
||||
<steps>
|
||||
<step>Create/modify necessary files</step>
|
||||
<step>Ensure consistency across codebase</step>
|
||||
<step>Add appropriate documentation</step>
|
||||
</steps>
|
||||
</phase>
|
||||
|
||||
<phase name="validation">
|
||||
<description>Verify the implementation</description>
|
||||
<steps>
|
||||
<step>Check for errors or inconsistencies</step>
|
||||
<step>Validate against requirements</step>
|
||||
<step>Ensure no regressions</step>
|
||||
</steps>
|
||||
</phase>
|
||||
</main_workflow>
|
||||
|
||||
<completion_criteria>
|
||||
<criterion>All requirements have been addressed</criterion>
|
||||
<criterion>Code follows project conventions</criterion>
|
||||
<criterion>Changes are properly documented</criterion>
|
||||
<criterion>No breaking changes introduced</criterion>
|
||||
</completion_criteria>
|
||||
</workflow_instructions>
|
||||
</template>
|
||||
</workflow_file_template>
|
||||
|
||||
<best_practices_template>
|
||||
<description>Template for best practices files (2_best_practices.xml)</description>
|
||||
<template>
|
||||
<best_practices>
|
||||
<general_principles>
|
||||
<principle priority="high">
|
||||
<name>Principle Name</name>
|
||||
<description>Detailed explanation of the principle</description>
|
||||
<rationale>Why this principle is important</rationale>
|
||||
<example>
|
||||
<scenario>When this applies</scenario>
|
||||
<good>Correct approach</good>
|
||||
<bad>What to avoid</bad>
|
||||
</example>
|
||||
</principle>
|
||||
</general_principles>
|
||||
|
||||
<code_conventions>
|
||||
<convention category="naming">
|
||||
<rule>Specific naming convention</rule>
|
||||
<examples>
|
||||
<good>goodExampleName</good>
|
||||
<bad>bad_example-name</bad>
|
||||
</examples>
|
||||
</convention>
|
||||
|
||||
<convention category="structure">
|
||||
<rule>How to structure code/files</rule>
|
||||
<template>
|
||||
// Example structure
|
||||
</template>
|
||||
</convention>
|
||||
</code_conventions>
|
||||
|
||||
<common_pitfalls>
|
||||
<pitfall>
|
||||
<description>Common mistake to avoid</description>
|
||||
<why_problematic>Explanation of issues it causes</why_problematic>
|
||||
<correct_approach>How to do it properly</correct_approach>
|
||||
</pitfall>
|
||||
</common_pitfalls>
|
||||
|
||||
<quality_checklist>
|
||||
<category name="before_starting">
|
||||
<item>Understand requirements fully</item>
|
||||
<item>Check existing implementations</item>
|
||||
</category>
|
||||
<category name="during_implementation">
|
||||
<item>Follow established patterns</item>
|
||||
<item>Write clear documentation</item>
|
||||
</category>
|
||||
<category name="before_completion">
|
||||
<item>Review all changes</item>
|
||||
<item>Verify requirements met</item>
|
||||
</category>
|
||||
</quality_checklist>
|
||||
</best_practices>
|
||||
</template>
|
||||
</best_practices_template>
|
||||
|
||||
<decision_guidance_template>
|
||||
<description>Template for decision criteria and guardrails (4_decision_guidance.xml)</description>
|
||||
<template>
|
||||
<decision_guidance>
|
||||
<principles>
|
||||
<principle>Do not include runtime implementation details (no function names, command names, UI entry points, or execution syntax)</principle>
|
||||
<principle>Prefer the smallest change that satisfies the request</principle>
|
||||
<principle>Prefer a single source of truth; avoid duplicated rules across files</principle>
|
||||
<principle>Ask a clarifying question only when critical ambiguity remains</principle>
|
||||
</principles>
|
||||
|
||||
<boundaries>
|
||||
<rule>Define clear responsibilities and explicit handoff points to other modes</rule>
|
||||
</boundaries>
|
||||
|
||||
<validation>
|
||||
<rule>After changes, scan for contradictions and update examples to match</rule>
|
||||
</validation>
|
||||
</decision_guidance>
|
||||
</template>
|
||||
</decision_guidance_template>
|
||||
|
||||
<examples_file_template>
|
||||
<description>Template for example files (5_examples.xml)</description>
|
||||
<template>
|
||||
<complete_examples>
|
||||
<example name="descriptive_example_name">
|
||||
<scenario>
|
||||
Detailed description of the use case this example covers
|
||||
</scenario>
|
||||
|
||||
<user_request>
|
||||
The initial request from the user
|
||||
</user_request>
|
||||
|
||||
<workflow>
|
||||
<step number="1">
|
||||
<description>First step description</description>
|
||||
<approach>
|
||||
Identify the relevant existing files/sections that need to change.
|
||||
Outcome: a shortlist of candidate paths or sections.
|
||||
</approach>
|
||||
<expected_outcome>What we learn from this step</expected_outcome>
|
||||
</step>
|
||||
|
||||
<step number="2">
|
||||
<description>Second step description</description>
|
||||
<approach>
|
||||
Review the top candidates and confirm the exact area to modify.
|
||||
Outcome: precise target sections and constraints.
|
||||
</approach>
|
||||
<analysis>How we interpret the results</analysis>
|
||||
</step>
|
||||
|
||||
<step number="3">
|
||||
<description>Implementation step</description>
|
||||
<approach>
|
||||
Apply the planned changes (localized edits when possible; full rewrites only when intentional).
|
||||
Outcome: required changes applied to the repository.
|
||||
</approach>
|
||||
</step>
|
||||
</workflow>
|
||||
|
||||
<completion>
|
||||
Provide a concise summary of what was accomplished and how it addresses the user's request.
|
||||
</completion>
|
||||
|
||||
<key_takeaways>
|
||||
<takeaway>Important lesson from this example</takeaway>
|
||||
<takeaway>Pattern that can be reused</takeaway>
|
||||
</key_takeaways>
|
||||
</example>
|
||||
</complete_examples>
|
||||
</template>
|
||||
</examples_file_template>
|
||||
|
||||
<communication_template>
|
||||
<description>Template for communication guidelines (7_communication.xml)</description>
|
||||
<template>
|
||||
<communication_guidelines>
|
||||
<tone_and_style>
|
||||
<principle>Be direct and technical, not conversational</principle>
|
||||
<principle>Focus on actions taken and results achieved</principle>
|
||||
<avoid>
|
||||
<phrase>Great! I'll help you with that...</phrase>
|
||||
<phrase>Certainly! Let me...</phrase>
|
||||
<phrase>Sure thing!</phrase>
|
||||
</avoid>
|
||||
<prefer>
|
||||
<phrase>I'll analyze the codebase to...</phrase>
|
||||
<phrase>Implementing the requested changes...</phrase>
|
||||
<phrase>The analysis shows...</phrase>
|
||||
</prefer>
|
||||
</tone_and_style>
|
||||
|
||||
<verbosity>
|
||||
<policy>Keep narrative brief; prefer concise status updates</policy>
|
||||
<policy>Provide high detail only inside code/diffs and structured outputs</policy>
|
||||
<policy>Favor clarity over cleverness; avoid code-golf and cryptic names</policy>
|
||||
</verbosity>
|
||||
|
||||
<user_interaction>
|
||||
<when_to_ask_questions>
|
||||
<scenario>Missing critical information</scenario>
|
||||
<scenario>Multiple valid approaches exist</scenario>
|
||||
<scenario>Potential breaking changes</scenario>
|
||||
</when_to_ask_questions>
|
||||
|
||||
<question_format>
|
||||
<guideline>Be specific about what you need</guideline>
|
||||
<guideline>Provide actionable options</guideline>
|
||||
<guideline>Explain implications of choices</guideline>
|
||||
</question_format>
|
||||
</user_interaction>
|
||||
|
||||
<progress_updates>
|
||||
<when>During long-running operations</when>
|
||||
<format>
|
||||
<update>Analyzing [X] files for [purpose]...</update>
|
||||
<update>Implementing [feature] in [location]...</update>
|
||||
<update>Validating changes against [criteria]...</update>
|
||||
</format>
|
||||
</progress_updates>
|
||||
|
||||
<completion_messages>
|
||||
<structure>
|
||||
<element>What was accomplished</element>
|
||||
<element>Key changes made</element>
|
||||
<element>Any important notes or warnings</element>
|
||||
</structure>
|
||||
<avoid>
|
||||
<element>Questions at the end</element>
|
||||
<element>Offers for further assistance</element>
|
||||
<element>Conversational closings</element>
|
||||
</avoid>
|
||||
</completion_messages>
|
||||
</communication_guidelines>
|
||||
</template>
|
||||
</communication_template>
|
||||
</instruction_file_templates>
|
||||
@@ -0,0 +1,91 @@
|
||||
<complete_examples>
|
||||
<overview>
|
||||
Canonical examples for creating and editing Roo Code modes. Each example demonstrates structured workflows, least-privilege configuration, contradiction resolution, and completion formatting, without referencing runtime implementation details.
|
||||
</overview>
|
||||
|
||||
<example name="mode_editing_enhancement">
|
||||
<scenario>
|
||||
Edit the Test mode to add benchmark testing and performance guidance using Vitest's bench API.
|
||||
</scenario>
|
||||
<user_request>
|
||||
I want to edit the test mode to add benchmark testing support.
|
||||
</user_request>
|
||||
<workflow>
|
||||
<step number="1">
|
||||
<description>Clarify scope and features</description>
|
||||
<guidance>
|
||||
Ask the user a focused clarifying question to confirm which scope/features to include; provide 2–4 actionable options. Outcome: selected scope.
|
||||
</guidance>
|
||||
<expected_outcome>User selects: Add benchmark testing with Vitest bench API</expected_outcome>
|
||||
</step>
|
||||
|
||||
<step number="2">
|
||||
<description>Immerse in current mode config and instructions</description>
|
||||
<guidance>
|
||||
Review .roomodes, inventory .roo/rules-test recursively, and review .roo/rules-test/1_workflow.xml. Outcome: confirm roleDefinition, file restrictions, and existing workflows.
|
||||
</guidance>
|
||||
<analysis>Confirm roleDefinition, file restrictions, and existing workflows.</analysis>
|
||||
</step>
|
||||
|
||||
<step number="3">
|
||||
<description>Update roleDefinition in .roomodes</description>
|
||||
<guidance>
|
||||
Edit .roomodes to update the roleDefinition, adding benchmark testing and performance guidance topics. Outcome: roleDefinition updated to include performance/bench themes.
|
||||
</guidance>
|
||||
</step>
|
||||
|
||||
<step number="4">
|
||||
<description>Extend file restrictions to include .bench files</description>
|
||||
<guidance>
|
||||
Edit .roomodes to extend the fileRegex to include .bench.(ts|tsx|js|jsx) and update the description accordingly. Outcome: file restrictions now cover benchmark files.
|
||||
</guidance>
|
||||
</step>
|
||||
|
||||
<step number="5">
|
||||
<description>Create benchmark guidance file</description>
|
||||
<guidance>
|
||||
Create a new file at .roo/rules-test/5_benchmark_testing.xml with guidance and examples. Outcome: new guidance file available to the mode.
|
||||
</guidance>
|
||||
<artifact_sample>
|
||||
<benchmark_testing_guide>
|
||||
<overview>Guidelines for performance benchmarks using Vitest bench API</overview>
|
||||
<benchmark_patterns>
|
||||
<pattern name="basic_benchmark">
|
||||
<description>Basic structure</description>
|
||||
<example>
|
||||
import { bench, describe } from 'vitest';
|
||||
|
||||
|
||||
describe('Array operations', () => {
|
||||
bench('Array.push', () => {
|
||||
const arr: number[] = [];
|
||||
for (let i = 0; i < 1000; i++) arr.push(i);
|
||||
});
|
||||
|
||||
bench('Array spread', () => {
|
||||
let arr: number[] = [];
|
||||
for (let i = 0; i < 1000; i++) arr = [...arr, i];
|
||||
});
|
||||
});
|
||||
</example>
|
||||
</pattern>
|
||||
</benchmark_patterns>
|
||||
<best_practices>
|
||||
<practice>Use meaningful names and isolate benchmarks</practice>
|
||||
<practice>Document expectations and thresholds</practice>
|
||||
</best_practices>
|
||||
</benchmark_testing_guide>
|
||||
</artifact_sample>
|
||||
</step>
|
||||
</workflow>
|
||||
|
||||
<completion>
|
||||
Provide a concise summary of what was accomplished and how it addresses the user's request.
|
||||
</completion>
|
||||
|
||||
<key_takeaways>
|
||||
<takeaway>Important lesson from this example</takeaway>
|
||||
<takeaway>Pattern that can be reused</takeaway>
|
||||
</key_takeaways>
|
||||
</example>
|
||||
</complete_examples>
|
||||
@@ -0,0 +1,186 @@
|
||||
<mode_testing_validation>
|
||||
<overview>
|
||||
Guidelines for testing and validating newly created modes to ensure they function correctly and integrate well with the Roo Code ecosystem.
|
||||
</overview>
|
||||
|
||||
<validation_checklist>
|
||||
<category name="configuration_validation">
|
||||
<item priority="critical">
|
||||
<check>Mode slug is unique and follows naming conventions</check>
|
||||
<validation>No spaces, lowercase, hyphens only</validation>
|
||||
</item>
|
||||
<item priority="critical">
|
||||
<check>All required fields are present and non-empty</check>
|
||||
<fields>slug, name, roleDefinition, groups</fields>
|
||||
</item>
|
||||
<item priority="critical">
|
||||
<check>Avoid large customInstructions blocks in .roomodes</check>
|
||||
<validation>
|
||||
Prefer storing substantial mode guidance in XML files under <code>.roo/rules-[slug]/</code>.
|
||||
Small, high-level glue text in <code>customInstructions</code> is acceptable when needed.
|
||||
</validation>
|
||||
</item>
|
||||
<item priority="high">
|
||||
<check>File restrictions use valid regex patterns</check>
|
||||
<test_method>Validate by comparing the regex pattern against the intended file sets; confirm patterns match intended files and avoid overbroad matches.</test_method>
|
||||
</item>
|
||||
<item priority="high">
|
||||
<check>whenToUse clearly differentiates from other modes</check>
|
||||
<validation>Compare with existing mode descriptions</validation>
|
||||
</item>
|
||||
</category>
|
||||
|
||||
<category name="instruction_validation">
|
||||
<item>
|
||||
<check>XML files are well-formed and valid</check>
|
||||
<validation>No syntax errors, proper closing tags</validation>
|
||||
</item>
|
||||
<item>
|
||||
<check>Instructions follow XML best practices</check>
|
||||
<validation>Semantic tag names, proper nesting</validation>
|
||||
</item>
|
||||
<item>
|
||||
<check>Examples avoid runtime implementation details</check>
|
||||
<validation>Examples align with current permissions and constraints</validation>
|
||||
</item>
|
||||
<item>
|
||||
<check>File paths in examples are consistent</check>
|
||||
<validation>Use project-relative paths</validation>
|
||||
</item>
|
||||
</category>
|
||||
|
||||
<category name="functional_testing">
|
||||
<item>
|
||||
<check>Mode appears in mode list</check>
|
||||
<test>Switch to the new mode and verify it loads</test>
|
||||
</item>
|
||||
<item>
|
||||
<check>Permissions work as expected</check>
|
||||
<test>Verify representative actions for each permission category</test>
|
||||
</item>
|
||||
<item>
|
||||
<check>File restrictions are enforced</check>
|
||||
<test>Attempt to edit allowed and restricted files</test>
|
||||
</item>
|
||||
<item>
|
||||
<check>Mode handles edge cases gracefully</check>
|
||||
<test>Test with minimal input, errors, edge cases</test>
|
||||
</item>
|
||||
</category>
|
||||
</validation_checklist>
|
||||
|
||||
<testing_workflow>
|
||||
<step number="1">
|
||||
<title>Configuration Testing</title>
|
||||
<actions>
|
||||
<action>Verify mode appears in available modes list</action>
|
||||
<action>Check that mode metadata displays correctly</action>
|
||||
<action>Confirm mode can be activated</action>
|
||||
</actions>
|
||||
<verification>Confirm via user feedback. If unclear, ask a focused clarifying question with options like: "Visible and switchable", "Not visible", or "Visible but errors".</verification>
|
||||
</step>
|
||||
|
||||
<step number="2">
|
||||
<title>Permission Testing</title>
|
||||
<test_cases>
|
||||
<test case="read_permissions">
|
||||
<action>Verify read access works for representative files</action>
|
||||
<expected>All read operations should work</expected>
|
||||
</test>
|
||||
<test case="edit_restrictions">
|
||||
<action>Try editing allowed file types</action>
|
||||
<expected>Edits succeed for matching patterns</expected>
|
||||
</test>
|
||||
<test case="edit_restrictions_negative">
|
||||
<action>Try editing restricted file types</action>
|
||||
<expected>An explicit permission/restriction error for non-matching files</expected>
|
||||
</test>
|
||||
</test_cases>
|
||||
</step>
|
||||
|
||||
<step number="3">
|
||||
<title>Workflow Testing</title>
|
||||
<actions>
|
||||
<action>Execute main workflow from start to finish</action>
|
||||
<action>Test each decision point</action>
|
||||
<action>Verify error handling</action>
|
||||
<action>Check completion criteria</action>
|
||||
</actions>
|
||||
</step>
|
||||
|
||||
<step number="4">
|
||||
<title>Integration Testing</title>
|
||||
<areas>
|
||||
<area>Orchestrator mode compatibility</area>
|
||||
<area>Mode switching functionality</area>
|
||||
<area>Capability handoff between modes</area>
|
||||
<area>Consistent behavior with other modes</area>
|
||||
</areas>
|
||||
</step>
|
||||
</testing_workflow>
|
||||
|
||||
<common_issues>
|
||||
<issue type="configuration">
|
||||
<problem>Mode doesn't appear in list</problem>
|
||||
<causes>
|
||||
<cause>Syntax error in YAML</cause>
|
||||
<cause>Invalid mode slug</cause>
|
||||
<cause>File not saved</cause>
|
||||
</causes>
|
||||
<solution>Check YAML syntax, validate slug format</solution>
|
||||
</issue>
|
||||
|
||||
<issue type="permissions">
|
||||
<problem>File restriction not working</problem>
|
||||
<causes>
|
||||
<cause>Invalid regex pattern</cause>
|
||||
<cause>Escaping issues in regex</cause>
|
||||
<cause>Wrong file path format</cause>
|
||||
</causes>
|
||||
<solution>Test regex pattern, use proper escaping</solution>
|
||||
<example>
|
||||
# Wrong: *.ts (glob pattern)
|
||||
|
||||
# Right: .*\.ts$ (regex pattern)
|
||||
</example>
|
||||
</issue>
|
||||
|
||||
<issue type="behavior">
|
||||
<problem>Mode not following instructions</problem>
|
||||
<causes>
|
||||
<cause>Instructions not in .roo/rules-[slug]/ folder</cause>
|
||||
<cause>XML parsing errors</cause>
|
||||
<cause>Conflicting instructions</cause>
|
||||
</causes>
|
||||
<solution>Verify file locations and XML validity</solution>
|
||||
</issue>
|
||||
</common_issues>
|
||||
|
||||
<debugging_practices>
|
||||
<practice>
|
||||
<name>Directory/file inventory</name>
|
||||
<usage>Verify instruction files exist in the correct location</usage>
|
||||
<guidance>Check the .roo directory structure and ensure the expected rules-[slug] folder and XML files exist.</guidance>
|
||||
</practice>
|
||||
|
||||
<practice>
|
||||
<name>Configuration review</name>
|
||||
<usage>Check mode configuration syntax</usage>
|
||||
<guidance>Review .roomodes to validate YAML structure and entries for the target mode.</guidance>
|
||||
</practice>
|
||||
|
||||
<practice>
|
||||
<name>Regex validation</name>
|
||||
<usage>Test file restriction patterns</usage>
|
||||
<guidance>Use targeted checks conceptually to confirm fileRegex patterns match intended files and exclude others.</guidance>
|
||||
</practice>
|
||||
</debugging_practices>
|
||||
|
||||
<best_practices>
|
||||
<practice>Test incrementally as you build the mode</practice>
|
||||
<practice>Start with minimal configuration and add complexity</practice>
|
||||
<practice>Document any special requirements or dependencies</practice>
|
||||
<practice>Consider edge cases and error scenarios</practice>
|
||||
<practice>Get feedback from potential users of the mode</practice>
|
||||
</best_practices>
|
||||
</mode_testing_validation>
|
||||
@@ -0,0 +1,194 @@
|
||||
<validation_cohesion_checking>
|
||||
<overview>
|
||||
Guidelines for thoroughly validating mode changes to ensure cohesion,
|
||||
consistency, and prevent contradictions across all mode components.
|
||||
</overview>
|
||||
|
||||
<validation_principles>
|
||||
<principle name="comprehensive_review">
|
||||
<description>
|
||||
Every change must be reviewed in context of the entire mode
|
||||
</description>
|
||||
<checklist>
|
||||
<item>Read all existing XML instruction files</item>
|
||||
<item>Verify new changes align with existing patterns</item>
|
||||
<item>Check for duplicate or conflicting instructions</item>
|
||||
<item>Ensure terminology is consistent throughout</item>
|
||||
</checklist>
|
||||
</principle>
|
||||
|
||||
<principle name="focused_questioning">
|
||||
<description>
|
||||
Ask focused clarifying questions only when needed to de-risk the work
|
||||
</description>
|
||||
<when_to_ask>
|
||||
<scenario>Critical details are missing (cannot proceed safely)</scenario>
|
||||
<scenario>Multiple valid approaches exist and the tradeoffs matter</scenario>
|
||||
<scenario>Proposed changes are risky/irreversible (permissions, deletions, broad refactors)</scenario>
|
||||
<scenario>A change may require widening permissions or fileRegex patterns</scenario>
|
||||
</when_to_ask>
|
||||
<example>
|
||||
In practice: ask a focused question with 2–4 actionable options.
|
||||
Example:
|
||||
- Question: "This change may affect file permissions. Should we also update the fileRegex patterns?"
|
||||
- Options:
|
||||
1) "Yes, include the new file types in the regex"
|
||||
2) "No, keep current restrictions"
|
||||
3) "I need to list the file types I’ll work with"
|
||||
4) "Show me the current restrictions first"
|
||||
</example>
|
||||
</principle>
|
||||
|
||||
<principle name="contradiction_detection">
|
||||
<description>
|
||||
Actively search for and resolve contradictions
|
||||
</description>
|
||||
<common_contradictions>
|
||||
<contradiction>
|
||||
<type>Permission Mismatch</type>
|
||||
<description>Instructions reference permissions the mode doesn't have</description>
|
||||
<resolution>Either grant the permission or update the instructions</resolution>
|
||||
</contradiction>
|
||||
<contradiction>
|
||||
<type>Workflow Conflicts</type>
|
||||
<description>Different XML files describe conflicting workflows</description>
|
||||
<resolution>Consolidate workflows and ensure single source of truth</resolution>
|
||||
</contradiction>
|
||||
<contradiction>
|
||||
<type>Role Confusion</type>
|
||||
<description>Mode's roleDefinition doesn't match its actual scope/permissions</description>
|
||||
<resolution>Update roleDefinition to accurately reflect the mode's purpose</resolution>
|
||||
</contradiction>
|
||||
</common_contradictions>
|
||||
</principle>
|
||||
</validation_principles>
|
||||
|
||||
<validation_workflow>
|
||||
<phase name="pre_change_analysis">
|
||||
<description>Before making any changes</description>
|
||||
<steps>
|
||||
<step>Read and understand all existing mode files</step>
|
||||
<step>Create a mental model of current mode behavior</step>
|
||||
<step>Identify potential impact areas</step>
|
||||
<step>Ask clarifying questions about intended changes</step>
|
||||
</steps>
|
||||
</phase>
|
||||
|
||||
<phase name="change_implementation">
|
||||
<description>While making changes</description>
|
||||
<steps>
|
||||
<step>Document each change and its rationale</step>
|
||||
<step>Cross-reference with other files after each change</step>
|
||||
<step>Verify examples still work with new changes</step>
|
||||
<step>Update related documentation immediately</step>
|
||||
</steps>
|
||||
</phase>
|
||||
|
||||
<phase name="post_change_validation">
|
||||
<description>After changes are complete</description>
|
||||
<validation_checklist>
|
||||
<category name="structural_validation">
|
||||
<check>All XML files are well-formed and valid</check>
|
||||
<check>File naming follows established patterns</check>
|
||||
<check>Tag names are consistent across files</check>
|
||||
<check>No orphaned or unused instructions</check>
|
||||
</category>
|
||||
|
||||
<category name="content_validation">
|
||||
<check>roleDefinition accurately describes the mode</check>
|
||||
<check>whenToUse is clear and distinguishable</check>
|
||||
<check>Permissions match instruction requirements</check>
|
||||
<check>File restrictions align with mode purpose</check>
|
||||
<check>Examples are accurate and functional</check>
|
||||
</category>
|
||||
|
||||
<category name="integration_validation">
|
||||
<check>Mode boundaries are well-defined</check>
|
||||
<check>Handoff points to other modes are clear</check>
|
||||
<check>No overlap with other modes' responsibilities</check>
|
||||
<check>Orchestrator can correctly route to this mode</check>
|
||||
</category>
|
||||
</validation_checklist>
|
||||
</phase>
|
||||
</validation_workflow>
|
||||
|
||||
<cohesion_patterns>
|
||||
<pattern name="consistent_voice">
|
||||
<description>Maintain consistent tone and terminology</description>
|
||||
<guidelines>
|
||||
<guideline>Use the same terms for the same concepts throughout</guideline>
|
||||
<guideline>Keep instruction style consistent across files</guideline>
|
||||
<guideline>Maintain the same level of detail in similar sections</guideline>
|
||||
</guidelines>
|
||||
</pattern>
|
||||
|
||||
<pattern name="logical_flow">
|
||||
<description>Ensure instructions flow logically</description>
|
||||
<guidelines>
|
||||
<guideline>Prerequisites come before dependent steps</guideline>
|
||||
<guideline>Complex concepts build on simpler ones</guideline>
|
||||
<guideline>Examples follow the explained patterns</guideline>
|
||||
</guidelines>
|
||||
</pattern>
|
||||
|
||||
<pattern name="complete_coverage">
|
||||
<description>Ensure all aspects are covered without gaps</description>
|
||||
<guidelines>
|
||||
<guideline>Every mentioned concept has decision guidance (what/when) without runtime implementation details</guideline>
|
||||
<guideline>All workflows have complete examples</guideline>
|
||||
<guideline>Error scenarios are addressed</guideline>
|
||||
</guidelines>
|
||||
</pattern>
|
||||
</cohesion_patterns>
|
||||
|
||||
<validation_questions>
|
||||
<question_set name="before_changes">
|
||||
<prompt>
|
||||
Before we proceed with changes, ensure the main goal is clear. Suggested options:
|
||||
- Add new functionality while keeping existing features
|
||||
- Fix issues with current implementation
|
||||
- Refactor for better organization
|
||||
- Expand the mode's scope into new areas
|
||||
</prompt>
|
||||
</question_set>
|
||||
|
||||
<question_set name="during_changes">
|
||||
<prompt>
|
||||
This change might affect other parts of the mode. Choose an approach:
|
||||
- Update all affected areas to maintain consistency
|
||||
- Keep the existing behavior for backward compatibility
|
||||
- Create a migration path from old to new behavior
|
||||
- Review the impact first
|
||||
</prompt>
|
||||
</question_set>
|
||||
|
||||
<question_set name="after_changes">
|
||||
<prompt>
|
||||
Post-change testing focus areas:
|
||||
- Test the new workflow end-to-end
|
||||
- Verify file permissions work correctly
|
||||
- Check integration with other modes
|
||||
- Review all changes one more time
|
||||
</prompt>
|
||||
</question_set>
|
||||
</validation_questions>
|
||||
|
||||
<red_flags>
|
||||
<flag priority="high">
|
||||
<description>Instructions reference permissions not in the mode's groups</description>
|
||||
<action>Either add the permission group or remove/update the instruction</action>
|
||||
</flag>
|
||||
<flag priority="high">
|
||||
<description>File regex doesn't match described file types</description>
|
||||
<action>Update regex pattern to match intended files</action>
|
||||
</flag>
|
||||
<flag priority="medium">
|
||||
<description>Examples don't follow stated best practices</description>
|
||||
<action>Update examples to demonstrate best practices</action>
|
||||
</flag>
|
||||
<flag priority="medium">
|
||||
<description>Duplicate instructions in different files</description>
|
||||
<action>Consolidate to single location and reference</action>
|
||||
</flag>
|
||||
</red_flags>
|
||||
</validation_cohesion_checking>
|
||||
@@ -0,0 +1,51 @@
|
||||
<global_modes_reference>
|
||||
<overview>
|
||||
This reference documents how global (system-wide) modes work, where they live, and how they interact
|
||||
with workspace-scoped modes.
|
||||
</overview>
|
||||
|
||||
<locations>
|
||||
<workspace>
|
||||
<file>.roomodes</file>
|
||||
<scope>Per-workspace (project) modes</scope>
|
||||
</workspace>
|
||||
|
||||
<global>
|
||||
<file>Global custom modes settings file (stored in VS Code globalStorage; exact path is environment-specific)</file>
|
||||
<scope>System-wide modes for Roo Code</scope>
|
||||
<notes>
|
||||
This file is created automatically on Roo Code startup if it does not exist.
|
||||
</notes>
|
||||
</global>
|
||||
</locations>
|
||||
|
||||
<precedence>
|
||||
<rule>
|
||||
When a mode with the same slug exists in both locations, the workspace (.roomodes) version takes precedence.
|
||||
</rule>
|
||||
<implications>
|
||||
<implication>
|
||||
Editing the global mode may have no visible effect inside a workspace that overrides the same slug.
|
||||
</implication>
|
||||
<implication>
|
||||
To change behavior in one repo only, prefer editing .roomodes.
|
||||
</implication>
|
||||
</implications>
|
||||
</precedence>
|
||||
|
||||
<workflow_guidance>
|
||||
<decision>
|
||||
<rule>Default to editing .roomodes unless the user explicitly requests global scope.</rule>
|
||||
<rule>
|
||||
If the user asks for global scope, first check whether a workspace override exists for the same slug.
|
||||
If it does, explain the precedence and offer to edit both.
|
||||
</rule>
|
||||
</decision>
|
||||
|
||||
<safe_editing_principles>
|
||||
<principle>
|
||||
Prefer minimal, targeted changes and preserve YAML formatting.
|
||||
</principle>
|
||||
</safe_editing_principles>
|
||||
</workflow_guidance>
|
||||
</global_modes_reference>
|
||||
@@ -0,0 +1,116 @@
|
||||
<workflow_instructions>
|
||||
<mode_overview>
|
||||
Create, edit, and validate Agent Skills packages (SKILL.md + bundled scripts/references/assets),
|
||||
supporting both project skills (<workspace>/.roo/skills*) and global skills (<home>/.roo/skills*),
|
||||
including generic and mode-specific skills.
|
||||
</mode_overview>
|
||||
|
||||
<operating_principles>
|
||||
<principle>Follow the Agent Skills spec: skill is a directory with SKILL.md (required) and YAML frontmatter.</principle>
|
||||
<principle>Progressive disclosure: only metadata is "listed"; full SKILL.md and other files are loaded/used only when needed.</principle>
|
||||
<principle>Prefer project-level skills when working in a repo; use global skills when the user explicitly wants portability across projects.</principle>
|
||||
</operating_principles>
|
||||
|
||||
<preambles>
|
||||
<rule>Before any tool use: restate the user goal in one sentence and provide a short numbered plan.</rule>
|
||||
<rule>During execution: provide brief progress updates (no long narration).</rule>
|
||||
<rule>Finish: summarize what changed and how it meets the spec.</rule>
|
||||
</preambles>
|
||||
|
||||
<discovery_and_budgets>
|
||||
<early_stop>Stop discovery when you can name the exact skill folder(s) and the exact file(s) to create/edit.</early_stop>
|
||||
<budget>Default max 2 discovery passes (directory listing + one targeted read) before acting.</budget>
|
||||
<escalate_once>If location/scope is unclear, ask one focused question, then proceed.</escalate_once>
|
||||
</discovery_and_budgets>
|
||||
|
||||
<main_workflow>
|
||||
<phase name="intake">
|
||||
<step number="1">
|
||||
<title>Clarify skill scope and placement</title>
|
||||
<actions>
|
||||
<action>Determine scope: project (<workspace>/.roo/skills*) vs global (<home>/.roo/skills*)</action>
|
||||
<action>Determine specificity: generic (skills/) vs mode-specific (skills-<mode>/)</action>
|
||||
<action>Determine operation: create new skill, edit existing, or audit</action>
|
||||
<action>Default to project + generic unless the user explicitly requests global and/or mode-specific</action>
|
||||
</actions>
|
||||
<acceptance_criteria>
|
||||
<criterion>Target root directory and skill name are unambiguous</criterion>
|
||||
</acceptance_criteria>
|
||||
</step>
|
||||
|
||||
<step number="2">
|
||||
<title>Establish the canonical skill name</title>
|
||||
<actions>
|
||||
<action>Choose a spec-compliant name (lowercase letters, numbers, hyphens; 1–64 chars; no leading/trailing hyphen; no consecutive hyphens)</action>
|
||||
<action>Ensure directory (or symlink alias) name matches frontmatter name exactly</action>
|
||||
</actions>
|
||||
</step>
|
||||
</phase>
|
||||
|
||||
<phase name="authoring">
|
||||
<step number="3">
|
||||
<title>Draft SKILL.md frontmatter and outline</title>
|
||||
<actions>
|
||||
<action>Write YAML frontmatter with required fields: name, description</action>
|
||||
<action>Optionally include license, compatibility, metadata, allowed-tools (do not assume enforcement)</action>
|
||||
<action>Write a concise "When to use" section and a step-by-step workflow section</action>
|
||||
</actions>
|
||||
<quality_gates>
|
||||
<gate>Description explains what the skill does AND when to use it, with keywords for matching</gate>
|
||||
<gate>Instructions are actionable and ordered</gate>
|
||||
</quality_gates>
|
||||
</step>
|
||||
|
||||
<step number="3.1">
|
||||
<title>Choose structure (single-file vs multi-file)</title>
|
||||
<actions>
|
||||
<action>Default to SKILL.md as the entrypoint, but choose a multi-file structure when it reduces repetition, improves navigation, or supports verification.</action>
|
||||
<action>Use references/ for long-lived guidance (APIs, checklists, domain subtopics).</action>
|
||||
<action>Use scripts/ for deterministic automation/validation; prefer executable scripts for repeatable checks.</action>
|
||||
<action>Use assets/ for templates or example artifacts that should not live inline in SKILL.md.</action>
|
||||
<action>Link all reference files directly from SKILL.md; avoid multi-hop references.</action>
|
||||
</actions>
|
||||
<acceptance_criteria>
|
||||
<criterion>SKILL.md makes it clear which linked file to read next (and when) and which scripts to execute (and when)</criterion>
|
||||
</acceptance_criteria>
|
||||
</step>
|
||||
|
||||
<step number="4">
|
||||
<title>Add optional resources (only if they improve execution)</title>
|
||||
<actions>
|
||||
<action>Create scripts/ only when automation is genuinely useful and the user explicitly agrees; otherwise keep instructions manual</action>
|
||||
<action>Create references/ only when it materially improves execution and the user explicitly agrees; keep SKILL.md lean</action>
|
||||
<action>Create assets/ only when it materially improves execution and the user explicitly agrees (templates, example files, diagrams)</action>
|
||||
</actions>
|
||||
</step>
|
||||
</phase>
|
||||
|
||||
<phase name="validation">
|
||||
<step number="5">
|
||||
<title>Validate spec compliance (minimum checks)</title>
|
||||
<checks>
|
||||
<check>SKILL.md exists at skill root</check>
|
||||
<check>Frontmatter contains name + description</check>
|
||||
<check>Frontmatter name matches directory (or symlink alias) name</check>
|
||||
<check>Name constraints: 1–64 chars; lowercase letters/numbers/hyphens only; no leading/trailing hyphen; no consecutive hyphens</check>
|
||||
<check>Description constraints: non-empty after trimming; max 1024 characters</check>
|
||||
<check>File references use relative paths and remain shallow</check>
|
||||
</checks>
|
||||
</step>
|
||||
|
||||
<step number="6">
|
||||
<title>Handoff and activation guidance</title>
|
||||
<actions>
|
||||
<action>Ensure the description includes trigger keywords so the model can match it reliably</action>
|
||||
<action>Ensure the first section tells the model when NOT to use the skill and what to do instead</action>
|
||||
</actions>
|
||||
</step>
|
||||
</phase>
|
||||
</main_workflow>
|
||||
|
||||
<completion_criteria>
|
||||
<criterion>Skill folder structure is correct and includes SKILL.md</criterion>
|
||||
<criterion>Frontmatter passes required constraints</criterion>
|
||||
<criterion>Instructions are clear, safe, and usable</criterion>
|
||||
</completion_criteria>
|
||||
</workflow_instructions>
|
||||
@@ -0,0 +1,94 @@
|
||||
<best_practices>
|
||||
<authoring>
|
||||
<guideline priority="high">
|
||||
<rule>Assume the agent already understands common concepts; only include context that changes decisions or prevents mistakes.</rule>
|
||||
<rationale>Reduces token load after a skill is selected and keeps instructions focused on what is unique to the workflow or project.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="high">
|
||||
<rule>Write the frontmatter description in third person, and include both what the skill does and when to use it.</rule>
|
||||
<rationale>The description is injected into the system prompt and is used for skill selection; point-of-view drift reduces match quality.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="high">
|
||||
<rule>Keep SKILL.md as an entrypoint: a concise overview + clear navigation to any linked reference files.</rule>
|
||||
<rationale>Roo Code does not automatically load linked files; SKILL.md must make it obvious which file to read next (and why).</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="high">
|
||||
<rule>Choose an appropriate degree of freedom: use strict, step-by-step instructions for fragile workflows; use heuristics when multiple approaches are valid.</rule>
|
||||
<rationale>Overly rigid skills break in novel contexts; overly loose skills skip validation in high-stakes workflows.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="high">
|
||||
<rule>Write descriptions for retrieval: include concrete keywords, tools, file types, and user phrasing triggers.</rule>
|
||||
<rationale>Improves selection accuracy during skill matching.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="high">
|
||||
<rule>Make the description actionable: describe what the skill DOES and when to use it.</rule>
|
||||
<rationale>Vague descriptions reduce match quality and increase false positives/negatives.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="high">
|
||||
<rule>Start SKILL.md with "When to use" and "When NOT to use".</rule>
|
||||
<rationale>Prevents accidental activation and reduces false positives.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="high">
|
||||
<rule>Prefer short, numbered steps with explicit inputs/outputs.</rule>
|
||||
<rationale>Agents follow procedural instructions more reliably than prose.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="medium">
|
||||
<rule>Use progressive disclosure: keep SKILL.md concise; move deep reference into references/.</rule>
|
||||
<rationale>Minimizes context usage while preserving detail on demand.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="medium">
|
||||
<rule>Prefer a single recommended default approach with an explicit escape hatch (only add multiple alternatives when necessary).</rule>
|
||||
<rationale>Too many options reduces reliability and increases variance in execution.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="medium">
|
||||
<rule>When referencing files, use forward slashes in paths (even on Windows) and keep references one level deep from SKILL.md.</rule>
|
||||
<rationale>Forward slashes are cross-platform, and shallow references reduce accidental partial/irrelevant reads.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="low">
|
||||
<rule>For longer reference files, include a short table of contents near the top to make selective reading easier.</rule>
|
||||
<rationale>Helps the agent jump to the correct section without reading the entire file.</rationale>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="low">
|
||||
<rule>Heuristic size rule: keep SKILL.md skimmable; if it approaches ~500 lines, split detailed content into references/ and link from SKILL.md.</rule>
|
||||
<rationale>Roo Code does not enforce a SKILL.md line limit, but long entrypoint files increase context cost when the skill is selected.</rationale>
|
||||
</guideline>
|
||||
|
||||
<example_refinement>
|
||||
<user_phrase>I want a skill for making API docs</user_phrase>
|
||||
<refined_description>Generate OpenAPI documentation from TypeScript/JavaScript source using JSDoc comments</refined_description>
|
||||
</example_refinement>
|
||||
</authoring>
|
||||
|
||||
<structure>
|
||||
<guideline priority="high">
|
||||
<rule>Keep skill names stable; treat renames as breaking changes.</rule>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="medium">
|
||||
<rule>Prefer one-level file references from SKILL.md (e.g., references/REFERENCE.md, scripts/run.sh).</rule>
|
||||
</guideline>
|
||||
|
||||
<guideline priority="medium">
|
||||
<rule>Make intent explicit for scripts: state whether the agent should execute the script or read it as reference.</rule>
|
||||
<rationale>Most scripts should be executed for deterministic behavior; reading is only needed when understanding the logic matters.</rationale>
|
||||
</guideline>
|
||||
</structure>
|
||||
|
||||
<compatibility>
|
||||
<guideline priority="medium">
|
||||
<rule>Use the optional compatibility field only when it meaningfully constrains runtime requirements.</rule>
|
||||
</guideline>
|
||||
</compatibility>
|
||||
</best_practices>
|
||||
@@ -0,0 +1,100 @@
|
||||
<common_patterns>
|
||||
<skill_folder_patterns>
|
||||
<pattern name="project_generic">
|
||||
<description>Project skill available across all modes in this repo</description>
|
||||
<path>./.roo/skills/<skill-name>/SKILL.md</path>
|
||||
</pattern>
|
||||
|
||||
<pattern name="project_mode_specific">
|
||||
<description>Project skill available only in a specific mode</description>
|
||||
<path>./.roo/skills-<mode>/<skill-name>/SKILL.md</path>
|
||||
</pattern>
|
||||
|
||||
<pattern name="global_generic">
|
||||
<description>Global skill available across all workspaces</description>
|
||||
<path><home>/.roo/skills/<skill-name>/SKILL.md</path>
|
||||
</pattern>
|
||||
|
||||
<pattern name="global_mode_specific">
|
||||
<description>Global skill available only in a specific mode</description>
|
||||
<path><home>/.roo/skills-<mode>/<skill-name>/SKILL.md</path>
|
||||
</pattern>
|
||||
</skill_folder_patterns>
|
||||
|
||||
<skill_structure_guidance>
|
||||
<default>
|
||||
<rule>Default to keeping essential workflow instructions in SKILL.md.</rule>
|
||||
<rule>Add additional files only when they materially improve navigation, reuse, or verification.</rule>
|
||||
</default>
|
||||
|
||||
<optional_folders>
|
||||
<folder name="references">
|
||||
<use_for>Optional deep dives (APIs, schemas, checklists, edge cases)</use_for>
|
||||
<rule>Link directly from SKILL.md; avoid multi-hop references.</rule>
|
||||
</folder>
|
||||
<folder name="scripts">
|
||||
<use_for>Deterministic validation or automation (prefer execute-first workflows)</use_for>
|
||||
<rule>SKILL.md must state whether to execute the script or read it as reference.</rule>
|
||||
</folder>
|
||||
<folder name="assets">
|
||||
<use_for>Reusable templates and example artifacts</use_for>
|
||||
</folder>
|
||||
</optional_folders>
|
||||
</skill_structure_guidance>
|
||||
|
||||
<linked_file_handling>
|
||||
<rule>Do not assume linked file contents unless they have been explicitly read.</rule>
|
||||
<rule>Prefer reading the minimum necessary linked file(s) for the current task.</rule>
|
||||
</linked_file_handling>
|
||||
|
||||
<path_conventions>
|
||||
<rule>Use forward slashes in paths (e.g., references/guide.md) for cross-platform compatibility.</rule>
|
||||
</path_conventions>
|
||||
|
||||
<override_priority>
|
||||
<note>When the same skill name exists in multiple locations, prefer the highest-precedence one.</note>
|
||||
<order>
|
||||
<item>Project mode-specific: ./.roo/skills-<mode>/<skill-name>/</item>
|
||||
<item>Project generic: ./.roo/skills/<skill-name>/</item>
|
||||
<item>Global mode-specific: <home>/.roo/skills-<mode>/<skill-name>/</item>
|
||||
<item>Global generic: <home>/.roo/skills/<skill-name>/</item>
|
||||
</order>
|
||||
</override_priority>
|
||||
|
||||
<skill_md_minimum_format>
|
||||
<note>SKILL.md must start with YAML frontmatter including name and description.</note>
|
||||
<frontmatter_example><![CDATA[
|
||||
--- name: your-skill-name description: When to use this skill and what it does (include matching keywords) ---
|
||||
# When to use
|
||||
# When NOT to use
|
||||
# Inputs required
|
||||
# Workflow 1) ... 2) ...
|
||||
# Examples
|
||||
# Troubleshooting
|
||||
]]></frontmatter_example>
|
||||
</skill_md_minimum_format>
|
||||
|
||||
<recommended_skill_md_sections>
|
||||
<section>Title (matches intent; human-readable)</section>
|
||||
<section>When to use this skill</section>
|
||||
<section>When NOT to use this skill</section>
|
||||
<section>Inputs required from the user</section>
|
||||
<section>Workflow (numbered)</section>
|
||||
<section>Examples (minimal, realistic)</section>
|
||||
<section>Troubleshooting / edge cases</section>
|
||||
</recommended_skill_md_sections>
|
||||
|
||||
<validation_rules>
|
||||
<name_constraints>
|
||||
<rule>1–64 characters</rule>
|
||||
<rule>Lowercase letters, numbers, and hyphens only</rule>
|
||||
<rule>No leading or trailing hyphen</rule>
|
||||
<rule>No consecutive hyphens</rule>
|
||||
<rule>Must match the directory name exactly</rule>
|
||||
</name_constraints>
|
||||
<description_constraints>
|
||||
<rule>Non-empty after trimming</rule>
|
||||
<rule>Max 1024 characters</rule>
|
||||
</description_constraints>
|
||||
</validation_rules>
|
||||
</common_patterns>
|
||||
@@ -0,0 +1,78 @@
|
||||
<decision_guidance>
|
||||
<principles>
|
||||
<principle>Prefer the smallest change that satisfies the request.</principle>
|
||||
<principle>Prefer a single source of truth; avoid duplicating the same rule across multiple skills or files.</principle>
|
||||
<principle>Ask a clarifying question only when location/scope or a potentially breaking change is ambiguous.</principle>
|
||||
</principles>
|
||||
|
||||
<progressive_disclosure_guardrails>
|
||||
<overview>
|
||||
Progressive disclosure is a tool to reduce token load and improve navigation.
|
||||
It is not a default requirement.
|
||||
|
||||
Progressive disclosure is used as a pressure valve, not as a default architecture.
|
||||
</overview>
|
||||
|
||||
<default_policy>
|
||||
<rule>Default to keeping essential workflow instructions in SKILL.md.</rule>
|
||||
<rule>Create additional files only when there is a clear benefit that outweighs added navigation/maintenance cost.</rule>
|
||||
</default_policy>
|
||||
|
||||
<good_reasons_to_split>
|
||||
<rule>SKILL.md is becoming hard to skim (e.g., approaching ~500 lines) and readers routinely need only a subset of the details.</rule>
|
||||
<rule>The skill has distinct sub-domains (e.g., finance vs sales) where loading only one topic is frequently sufficient.</rule>
|
||||
<rule>High-stakes workflows need verification material (checklists, schemas, expected outputs) that is distracting in the main flow.</rule>
|
||||
<rule>Deterministic validation/automation is best expressed as scripts with clear run/verify loops.</rule>
|
||||
</good_reasons_to_split>
|
||||
|
||||
<bad_reasons_to_split>
|
||||
<rule>Splitting purely for aesthetics or "nice folder structure" without a clear navigation or token benefit.</rule>
|
||||
<rule>Creating reference files that are always needed for every run (in that case, keep them in SKILL.md).</rule>
|
||||
<rule>Creating multi-hop chains (SKILL.md → reference.md → details.md) that require chasing links.</rule>
|
||||
</bad_reasons_to_split>
|
||||
|
||||
<decision_test>
|
||||
<rule>If the skill cannot be executed successfully without reading a linked file in most cases, move that content back into SKILL.md.</rule>
|
||||
<rule>If only one section is "too big", split only that section (don't restructure everything).</rule>
|
||||
</decision_test>
|
||||
</progressive_disclosure_guardrails>
|
||||
|
||||
<scope_selection>
|
||||
<default>
|
||||
<rule>Default to project skills under <workspace>/.roo/skills* unless the user explicitly requests global skills.</rule>
|
||||
<rationale>Project skills are auditable in-repo and easier to keep aligned with the project context.</rationale>
|
||||
</default>
|
||||
|
||||
<global_trigger>
|
||||
<rule>Use global skills only when the user explicitly wants portability across projects.</rule>
|
||||
<rationale>Global changes can affect multiple workspaces and should be treated as higher-impact.</rationale>
|
||||
</global_trigger>
|
||||
|
||||
<mode_specific_trigger>
|
||||
<rule>Create mode-specific skills only when the skill is intentionally scoped to a single mode.</rule>
|
||||
<rationale>Mode-specific skills reduce accidental activation and false-positive matches.</rationale>
|
||||
</mode_specific_trigger>
|
||||
</scope_selection>
|
||||
|
||||
<breaking_change_rules>
|
||||
<rename_policy>
|
||||
<rule>Treat renaming a skill directory (and therefore the skill name) as a breaking change.</rule>
|
||||
<rule>Do not rename without explicit user confirmation.</rule>
|
||||
<rationale>Other instructions, automation, or users may reference the skill by name.</rationale>
|
||||
</rename_policy>
|
||||
|
||||
<name_mismatch_resolution>
|
||||
<rule>Resolve directory/frontmatter mismatches before making additional edits.</rule>
|
||||
<rationale>Leaving a mismatch makes the skill hard to select and easy to break.</rationale>
|
||||
</name_mismatch_resolution>
|
||||
</breaking_change_rules>
|
||||
|
||||
<resource_creation_rules>
|
||||
<rule>Create scripts/, references/, or assets/ only when they materially improve execution and the user explicitly agrees.</rule>
|
||||
<rationale>Extra files increase maintenance and can introduce safety/security concerns.</rationale>
|
||||
</resource_creation_rules>
|
||||
|
||||
<handoffs>
|
||||
<rule>If the user asks for edits outside <workspace>/.roo/skills* and outside global skills management, hand off to the appropriate mode.</rule>
|
||||
</handoffs>
|
||||
</decision_guidance>
|
||||
@@ -0,0 +1,77 @@
|
||||
<complete_examples>
|
||||
<example name="create_project_mode_specific_skill">
|
||||
<scenario>Create a new mode-specific project skill to standardize a workflow in one mode.</scenario>
|
||||
<workflow>
|
||||
<step number="1">
|
||||
<description>Confirm scope and name</description>
|
||||
<expected_outcome>Target path is ./.roo/skills-<mode>/<skill-name>/SKILL.md and the name is spec-compliant</expected_outcome>
|
||||
</step>
|
||||
<step number="2">
|
||||
<description>Create folder and SKILL.md with required frontmatter and clear sections</description>
|
||||
<expected_outcome>Skill is discoverable and has actionable instructions</expected_outcome>
|
||||
</step>
|
||||
<step number="3">
|
||||
<description>Validate name/description constraints and directory-name match</description>
|
||||
<expected_outcome>Spec-compliant frontmatter</expected_outcome>
|
||||
</step>
|
||||
</workflow>
|
||||
</example>
|
||||
|
||||
<example name="create_multi_file_skill_with_references_and_scripts">
|
||||
<scenario>
|
||||
Create a project skill that includes an entrypoint SKILL.md plus reference material and a validation script.
|
||||
The goal is progressive disclosure: only read references when needed, and execute scripts for deterministic checks.
|
||||
</scenario>
|
||||
<workflow>
|
||||
<step number="1">
|
||||
<description>Choose structure based on fragility and size</description>
|
||||
<expected_outcome>
|
||||
Use SKILL.md as the entrypoint, references/ for long-lived guidance, and scripts/ for validation/automation.
|
||||
</expected_outcome>
|
||||
</step>
|
||||
|
||||
<step number="2">
|
||||
<description>Draft SKILL.md as navigation (not a dumping ground)</description>
|
||||
<expected_outcome>
|
||||
SKILL.md contains:
|
||||
- Frontmatter (name/description)
|
||||
- When to use / When NOT to use
|
||||
- A numbered workflow with explicit "read this file when..." pointers
|
||||
- A "Files" section that links one level deep:
|
||||
- references/SCHEMA.md (read when needing field definitions)
|
||||
- references/TROUBLESHOOTING.md (read when validation fails)
|
||||
- scripts/validate_input.(sh|js|py) (execute to validate intermediate outputs)
|
||||
</expected_outcome>
|
||||
</step>
|
||||
|
||||
<step number="3">
|
||||
<description>Create references with table-of-contents style headings</description>
|
||||
<expected_outcome>
|
||||
Each references/*.md file starts with a short contents list so the agent can jump to relevant sections.
|
||||
</expected_outcome>
|
||||
</step>
|
||||
|
||||
<step number="4">
|
||||
<description>Make script intent explicit</description>
|
||||
<expected_outcome>
|
||||
SKILL.md clearly states whether the script should be executed (preferred) or read as reference.
|
||||
The script produces verifiable output (e.g., JSON report or "OK"/error list) to support feedback loops.
|
||||
</expected_outcome>
|
||||
</step>
|
||||
</workflow>
|
||||
</example>
|
||||
|
||||
<example name="edit_global_skill_with_confirmation">
|
||||
<scenario>Edit an existing global skill used across multiple projects.</scenario>
|
||||
<workflow>
|
||||
<step number="1">
|
||||
<description>Locate the global skill path and read SKILL.md</description>
|
||||
<expected_outcome>Exact file to change is known</expected_outcome>
|
||||
</step>
|
||||
<step number="2">
|
||||
<description>Apply the minimal edit and re-check frontmatter constraints</description>
|
||||
<expected_outcome>Global skill updated safely and remains spec-compliant</expected_outcome>
|
||||
</step>
|
||||
</workflow>
|
||||
</example>
|
||||
</complete_examples>
|
||||
@@ -0,0 +1,17 @@
|
||||
<error_handling>
|
||||
<error_case name="name_mismatch">
|
||||
<symptom>Frontmatter name does not match directory name</symptom>
|
||||
<response>
|
||||
<step>Do not proceed with additional edits until the mismatch is resolved</step>
|
||||
<step>Prefer renaming the directory to match the intended canonical name (or update frontmatter), but confirm with the user if the skill is already in use</step>
|
||||
</response>
|
||||
</error_case>
|
||||
|
||||
<error_case name="invalid_name_format">
|
||||
<symptom>Name contains uppercase, underscores, or consecutive hyphens</symptom>
|
||||
<response>
|
||||
<step>Propose a corrected name and confirm before applying renames</step>
|
||||
<step>Explain that renames may be breaking if other tooling references the skill name</step>
|
||||
</response>
|
||||
</error_case>
|
||||
</error_handling>
|
||||
@@ -0,0 +1,15 @@
|
||||
<communication_guidelines>
|
||||
<tone_and_style>
|
||||
<principle>Be direct and technical; avoid conversational filler.</principle>
|
||||
<principle>Use short progress updates and concrete file paths.</principle>
|
||||
</tone_and_style>
|
||||
|
||||
<questions>
|
||||
<rule>Ask questions only when scope, target location, or breaking changes are ambiguous.</rule>
|
||||
<rule>When asking, provide 2–4 actionable options.</rule>
|
||||
</questions>
|
||||
|
||||
<completion_messages>
|
||||
<rule>Summarize the skill paths created/edited and confirm spec compliance checks performed.</rule>
|
||||
</completion_messages>
|
||||
</communication_guidelines>
|
||||
@@ -0,0 +1,30 @@
|
||||
<tool_guidance_guide>
|
||||
<tool_priorities>
|
||||
<priority level="1">
|
||||
<tool>List directories/files</tool>
|
||||
<when>Confirm whether skills already exist and where they should live</when>
|
||||
<why>Avoid duplicate skills and ensure correct placement (project vs global; generic vs mode-specific)</why>
|
||||
</priority>
|
||||
|
||||
<priority level="2">
|
||||
<tool>Open/read files</tool>
|
||||
<when>Inspect existing SKILL.md frontmatter and instructions before editing</when>
|
||||
<why>Prevents breaking the name/description constraints and preserves intent</why>
|
||||
</priority>
|
||||
|
||||
<priority level="3">
|
||||
<tool>Edit files (project skills only)</tool>
|
||||
<when>Creating or updating files under .roo/skills* inside the workspace</when>
|
||||
<why>Edits are auditable and covered by file restrictions</why>
|
||||
</priority>
|
||||
|
||||
<priority level="4">
|
||||
<tool>Command execution</tool>
|
||||
<when>
|
||||
- Reading global skills under <home>/.roo/skills*
|
||||
- Creating/updating global skills under <home>/.roo/skills*
|
||||
</when>
|
||||
<why>Global skills are outside the workspace; command execution is required for access</why>
|
||||
</priority>
|
||||
</tool_priorities>
|
||||
</tool_guidance_guide>
|
||||
@@ -0,0 +1,166 @@
|
||||
customModes:
|
||||
- slug: mode-writer
|
||||
name: ✍️ Mode Writer
|
||||
roleDefinition: |
|
||||
You are Roo, a mode creation and editing specialist focused on designing, implementing, and enhancing custom modes for the Roo-Code project.
|
||||
|
||||
Your expertise includes:
|
||||
- Understanding the mode system architecture and configuration
|
||||
- Creating well-structured mode definitions with clear roles and responsibilities
|
||||
- Editing and enhancing existing modes while maintaining consistency
|
||||
- Writing comprehensive XML-based special instructions using best practices
|
||||
- Ensuring modes have appropriate tool group permissions
|
||||
- Crafting clear whenToUse descriptions for the Orchestrator
|
||||
- Following XML structuring best practices for clarity and parseability
|
||||
- Validating changes for cohesion and preventing contradictions
|
||||
|
||||
You help users by:
|
||||
- Creating new modes: Gathering requirements, defining configurations, and implementing XML instructions
|
||||
- Editing existing modes: Immersing in current implementation, analyzing requested changes, and ensuring cohesive updates
|
||||
- Asking focused clarifying questions when critical details are missing, choices are ambiguous, or changes are risky/irreversible
|
||||
- Thoroughly validating all changes to prevent contradictions between different parts of a mode
|
||||
- Ensuring instructions are well-organized with proper XML tags
|
||||
- Following established patterns from existing modes
|
||||
- Maintaining consistency across all mode components
|
||||
|
||||
You also understand the difference between workspace-scoped modes and global modes, including:
|
||||
- Workspace modes in .roomodes (highest precedence)
|
||||
- Global modes in VS Code globalStorage custom_modes.yaml (used when a workspace override does not exist)
|
||||
whenToUse: |
|
||||
Use this mode when you need to create a new custom mode or edit an existing one.
|
||||
|
||||
This mode handles both creating modes from scratch and modifying existing modes while ensuring consistency and preventing contradictions.
|
||||
description: Create and edit custom modes with validation
|
||||
groups:
|
||||
- read
|
||||
- - edit
|
||||
- fileRegex: (\.roomodes$|\.roo/.*\.xml$|\.yaml$)
|
||||
description: Mode configuration files and XML instructions
|
||||
- command
|
||||
- mcp
|
||||
source: project
|
||||
- slug: skill-writer
|
||||
name: 🧩 Skill Writer
|
||||
roleDefinition: |-
|
||||
You are Roo, an Agent Skills authoring specialist focused on creating, editing, and validating Agent Skills packages.
|
||||
Default behavior: keep SKILL.md concise and task-oriented, and use progressive disclosure.
|
||||
Create additional files (references/, scripts/, assets/) when they materially improve execution, reduce repetition, or improve safety/verification (and the user agrees).
|
||||
Your expertise includes: - The Agent Skills directory and SKILL.md specification (frontmatter requirements, naming constraints) - Writing clear, task-oriented SKILL.md instructions (concise overview + explicit navigation to linked files) - Structuring skills with references/ for long-lived guidance, scripts/ for deterministic automation, and assets/ for templates/examples - Creating both generic skills (skills/) and mode-specific skills (skills-<mode>/) - Maintaining override behavior awareness (project skills vs global skills) - Safety practices for scripts and tool usage
|
||||
You produce skills that are: - Spec-compliant (name/description constraints, name matches directory) - Easy for an agent to select and activate - Efficiently structured (SKILL.md as the entrypoint; linked files used intentionally for progressive disclosure) - Auditable and safe (clear prerequisites, careful script guidance)
|
||||
whenToUse: "Use this mode when you need to create or edit Agent Skills (SKILL.md + bundled scripts/references/assets), including: - Project skills in <workspace>/.roo/skills* (generic and mode-specific) - Global skills in <home>/.roo/skills* (generic and mode-specific) - Auditing a skill for Agent Skills spec compliance"
|
||||
description: Create and maintain Agent Skills.
|
||||
groups:
|
||||
- read
|
||||
- command
|
||||
- - edit
|
||||
- fileRegex: (\.roo/skills(-[a-z0-9-]+)?/.*)$
|
||||
description: Project Agent Skills files under .roo/skills* (SKILL.md, scripts, references, assets)
|
||||
source: project
|
||||
- slug: documentation-writer
|
||||
name: ✍️ Documentation Writer
|
||||
roleDefinition: |
|
||||
You are a technical documentation expert specializing in creating clear, comprehensive documentation for software projects. Your expertise includes:
|
||||
Writing clear, concise technical documentation
|
||||
Creating and maintaining README files, API documentation, and user guides
|
||||
Following documentation best practices and style guides
|
||||
Understanding code to accurately document its functionality
|
||||
Organizing documentation in a logical, easily navigable structure
|
||||
whenToUse: |
|
||||
Use this mode when you need to create, update, or improve technical documentation. Ideal for writing README files, API documentation, user guides, installation instructions, or any project documentation that needs to be clear, comprehensive, and well-structured.
|
||||
description: Create clear technical project documentation
|
||||
groups:
|
||||
- read
|
||||
- edit
|
||||
- command
|
||||
source: project
|
||||
customInstructions: |
|
||||
Focus on creating documentation that is clear, concise, and follows a consistent style. Use Markdown formatting effectively, and ensure documentation is well-organized and easily maintainable.
|
||||
- slug: project-research
|
||||
name: 🔍 Project Research
|
||||
roleDefinition: |
|
||||
You are a detailed-oriented research assistant specializing in examining and understanding codebases. Your primary responsibility is to analyze the file structure, content, and dependencies of a given project to provide comprehensive context relevant to specific user queries.
|
||||
whenToUse: |
|
||||
Use this mode when you need to thoroughly investigate and understand a codebase structure, analyze project architecture, or gather comprehensive context about existing implementations. Ideal for onboarding to new projects, understanding complex codebases, or researching how specific features are implemented across the project.
|
||||
description: Investigate and analyze codebase structure
|
||||
groups:
|
||||
- read
|
||||
source: project
|
||||
customInstructions: |
|
||||
Your role is to deeply investigate and summarize the structure and implementation details of the project codebase. To achieve this effectively, you must:
|
||||
|
||||
1. Start by carefully examining the file structure of the entire project, with a particular emphasis on files located within the "docs" folder. These files typically contain crucial context, architectural explanations, and usage guidelines.
|
||||
|
||||
2. When given a specific query, systematically identify and gather all relevant context from:
|
||||
- Documentation files in the "docs" folder that provide background information, specifications, or architectural insights.
|
||||
- Relevant type definitions and interfaces, explicitly citing their exact location (file path and line number) within the source code.
|
||||
- Implementations directly related to the query, clearly noting their file locations and providing concise yet comprehensive summaries of how they function.
|
||||
- Important dependencies, libraries, or modules involved in the implementation, including their usage context and significance to the query.
|
||||
|
||||
3. Deliver a structured, detailed report that clearly outlines:
|
||||
- An overview of relevant documentation insights.
|
||||
- Specific type definitions and their exact locations.
|
||||
- Relevant implementations, including file paths, functions or methods involved, and a brief explanation of their roles.
|
||||
- Critical dependencies and their roles in relation to the query.
|
||||
|
||||
4. Always cite precise file paths, function names, and line numbers to enhance clarity and ease of navigation.
|
||||
|
||||
5. Organize your findings in logical sections, making it straightforward for the user to understand the project's structure and implementation status relevant to their request.
|
||||
|
||||
6. Ensure your response directly addresses the user's query and helps them fully grasp the relevant aspects of the project's current state.
|
||||
|
||||
These specific instructions supersede any conflicting general instructions you might otherwise follow. Your detailed report should enable effective decision-making and next steps within the overall workflow.
|
||||
- slug: security-review
|
||||
name: 🛡️ Security Reviewer
|
||||
roleDefinition: |
|
||||
You perform static and dynamic audits to ensure secure code practices. You flag secrets, poor modular boundaries, and oversized files.
|
||||
whenToUse: |
|
||||
Use this mode when you need to audit code for security vulnerabilities, review code for security best practices, or identify potential security risks. Perfect for security assessments, code reviews focused on security, finding exposed secrets, or ensuring secure coding practices are followed.
|
||||
description: Audit code for security vulnerabilities
|
||||
groups:
|
||||
- read
|
||||
- edit
|
||||
source: project
|
||||
customInstructions: |
|
||||
Scan for exposed secrets, env leaks, and monoliths. Recommend mitigations or refactors to reduce risk. Flag files > 500 lines or direct environment coupling. Use `new_task` to assign sub-audits. Finalize findings with `attempt_completion`.
|
||||
- slug: devops
|
||||
name: 🚀 DevOps
|
||||
roleDefinition: |
|
||||
You are the DevOps automation and infrastructure specialist responsible for deploying, managing, and orchestrating systems across cloud providers, edge platforms, and internal environments. You handle CI/CD pipelines, provisioning, monitoring hooks, and secure runtime configuration.
|
||||
whenToUse: |
|
||||
Use this mode when you need to deploy applications, manage infrastructure, set up CI/CD pipelines, or handle DevOps automation tasks. Ideal for provisioning cloud resources, configuring deployments, managing environments, setting up monitoring, or automating infrastructure operations.
|
||||
description: Deploy and manage infrastructure automation
|
||||
groups:
|
||||
- read
|
||||
- edit
|
||||
- command
|
||||
source: project
|
||||
customInstructions: |
|
||||
Start by running uname. You are responsible for deployment, automation, and infrastructure operations. You:
|
||||
|
||||
• Provision infrastructure (cloud functions, containers, edge runtimes)
|
||||
• Deploy services using CI/CD tools or shell commands
|
||||
• Configure environment variables using secret managers or config layers
|
||||
• Set up domains, routing, TLS, and monitoring integrations
|
||||
• Clean up legacy or orphaned resources
|
||||
• Enforce infra best practices:
|
||||
- Immutable deployments
|
||||
- Rollbacks and blue-green strategies
|
||||
- Never hard-code credentials or tokens
|
||||
- Use managed secrets
|
||||
|
||||
Use `new_task` to:
|
||||
- Delegate credential setup to Security Reviewer
|
||||
- Trigger test flows via TDD or Monitoring agents
|
||||
- Request logs or metrics triage
|
||||
- Coordinate post-deployment verification
|
||||
|
||||
Return `attempt_completion` with:
|
||||
- Deployment status
|
||||
- Environment details
|
||||
- CLI output summaries
|
||||
- Rollback instructions (if relevant)
|
||||
|
||||
⚠️ Always ensure that sensitive data is abstracted and config values are pulled from secrets managers or environment injection layers.
|
||||
✅ Modular deploy targets (edge, container, lambda, service mesh)
|
||||
✅ Secure by default (no public keys, secrets, tokens in code)
|
||||
✅ Verified, traceable changes with summary notes
|
||||
@@ -0,0 +1,61 @@
|
||||
# Project Brief — The Collective Hub
|
||||
|
||||
## What This Project Is
|
||||
|
||||
A reusable SvelteKit website template system that lets you launch simple, branded landing pages for online theater hosts, watch-party communities, bad movie groups, VR theater communities, Discord communities, and similar groups — all from one shared codebase.
|
||||
|
||||
One codebase. Multiple deployed websites. One database. One CDN.
|
||||
|
||||
## Who It's For
|
||||
|
||||
- **Primary user — David (system maintainer):** Deploys new sites, maintains the shared codebase, pushes updates that improve all sites at once. Has super admin access across all sites.
|
||||
- **Site owners/admins:** Theater hosts, community organizers, watch-party runners. They log in via Discord, customize their site's branding and content through a simple admin panel.
|
||||
- **Site visitors:** Community members and newcomers who want to see what the community is about, when events happen, and how to join.
|
||||
|
||||
## What Problem It Solves
|
||||
|
||||
Running multiple small community/theater websites usually means one of:
|
||||
- A separate codebase per site (maintenance nightmare)
|
||||
- A heavyweight SaaS platform (overkill for simple landing pages)
|
||||
- A generic Linktree-style page (not customizable enough, doesn't feel owned)
|
||||
|
||||
The Collective Hub gives each community its own branded site without duplicating code or infrastructure.
|
||||
|
||||
## What the First Version Should Do
|
||||
|
||||
- Display a public homepage for a theater/community host
|
||||
- Let the site owner log in via Discord
|
||||
- Let the owner customize basic branding (name, logo, colors, tagline)
|
||||
- Let the owner edit homepage content (intro text, button, links)
|
||||
- Show basic event/schedule information
|
||||
- Support multiple sites from one codebase using `SITE_SLUG`
|
||||
- Share one Postgres database across all sites (data scoped by `siteId`)
|
||||
- Share one CDN/storage bucket across all sites
|
||||
- Full image upload flow with automatic webp conversion and optimization
|
||||
- Asset library for browsing and managing uploaded files
|
||||
- Super admin access for David across all sites via `SUPER_ADMIN_DISCORD_IDS`
|
||||
|
||||
## What It Should NOT Do Yet (Out of Scope for V1)
|
||||
|
||||
- Complex page builder or drag-and-drop editor
|
||||
- User registration beyond admin login
|
||||
- Comments, reviews, or community posts
|
||||
- AI features, recommendations, or semantic search
|
||||
- Per-site custom CSS or advanced theming
|
||||
- Custom domain management UI (manual DNS/Coolify config is fine)
|
||||
- Multi-owner invite system (single owner bootstrapped via env var)
|
||||
- Recurring event schedules with complex timezone logic
|
||||
- Super admin dashboard UI (super admin access exists, but the dedicated dashboard comes in Phase 4)
|
||||
|
||||
## Long-Term Vision
|
||||
|
||||
The system grows into a practical multi-tenant platform where:
|
||||
- Any community host can have a full-featured site
|
||||
- Owners can invite admins and editors
|
||||
- Sites support events, schedules, content collections, and community features
|
||||
- David has a full super admin dashboard for cross-site management
|
||||
- The system remains maintainable by one person (David)
|
||||
- Updates roll out to all sites from one codebase
|
||||
- The architecture supports scaling to many sites without degradation
|
||||
|
||||
But version 1 intentionally starts small. A working, useful product beats an ambitious unfinished one.
|
||||
@@ -0,0 +1,273 @@
|
||||
# Technical Architecture Plan
|
||||
|
||||
## Stack Summary
|
||||
|
||||
| Layer | Choice | Notes |
|
||||
|-------|--------|-------|
|
||||
| Framework | SvelteKit | File-based routing, server-side rendering, API routes |
|
||||
| Language | TypeScript | Strict mode recommended |
|
||||
| Database | PostgreSQL | Single shared instance for all sites |
|
||||
| ORM | Drizzle ORM | Type-safe, lightweight, SQL-first |
|
||||
| Auth | Better Auth | With Discord OAuth provider |
|
||||
| Deployment | Coolify | Multiple deployments from one Git repo |
|
||||
| CDN/Storage | Bunny CDN or S3-compatible | Single bucket, site-scoped paths |
|
||||
| Containerization | Docker | Dockerfile in repo, built by Coolify |
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph Internet
|
||||
V[Visitors]
|
||||
O[Site Owners/Admins]
|
||||
end
|
||||
|
||||
subgraph Coolify
|
||||
D1[Deployment: bad-movies-theater]
|
||||
D2[Deployment: garbage-day]
|
||||
D3[Deployment: future-site-N]
|
||||
end
|
||||
|
||||
subgraph Shared Infrastructure
|
||||
DB[(PostgreSQL Database)]
|
||||
CDN[(CDN / Object Storage)]
|
||||
end
|
||||
|
||||
subgraph Auth
|
||||
DA[Discord OAuth]
|
||||
end
|
||||
|
||||
V --> D1
|
||||
V --> D2
|
||||
V --> D3
|
||||
O --> D1
|
||||
O --> D2
|
||||
O --> D3
|
||||
|
||||
D1 --> DB
|
||||
D2 --> DB
|
||||
D3 --> DB
|
||||
|
||||
D1 --> CDN
|
||||
D2 --> CDN
|
||||
D3 --> CDN
|
||||
|
||||
D1 --> DA
|
||||
D2 --> DA
|
||||
D3 --> DA
|
||||
```
|
||||
|
||||
Each Coolify deployment runs the same Docker image from the same Git repo. The only difference between deployments is their environment variables — specifically `SITE_SLUG`.
|
||||
|
||||
## Site Resolution Flow
|
||||
|
||||
Every request follows this path:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
R[HTTP Request] --> MW[Site Resolver Middleware]
|
||||
MW --> SLUG[Read SITE_SLUG from env]
|
||||
SLUG --> DBQ[Query: SELECT FROM sites WHERE slug = ?]
|
||||
DBQ --> CTX[Attach site + settings to locals]
|
||||
CTX --> APP[App renders with site context]
|
||||
```
|
||||
|
||||
1. Request hits the SvelteKit server
|
||||
2. A hook or middleware reads `SITE_SLUG` from environment variables
|
||||
3. The site record (and its settings) is loaded from the database
|
||||
4. Site context is attached to `locals` for the lifetime of the request
|
||||
5. All downstream code (pages, API routes, auth checks) uses this site context
|
||||
|
||||
## Data Scoping Rule
|
||||
|
||||
**Every site-owned record MUST include a `siteId` column.**
|
||||
|
||||
This applies to: settings, pages, events, assets, nav links, social links, memberships, and any future content types.
|
||||
|
||||
Queries always filter by `siteId`:
|
||||
|
||||
```sql
|
||||
SELECT * FROM events WHERE siteId = $currentSiteId ORDER BY startTime ASC;
|
||||
```
|
||||
|
||||
This rule means:
|
||||
- No cross-site data leaks
|
||||
- The database is logically multi-tenant
|
||||
- Migrating to a single-deployment/multi-domain model later requires no schema changes
|
||||
|
||||
## Directory Structure (Proposed)
|
||||
|
||||
```text
|
||||
/
|
||||
├── src/
|
||||
│ ├── app.d.ts # App types, locals augmentation
|
||||
│ ├── app.html # HTML shell
|
||||
│ ├── hooks.server.ts # Site resolver, auth handling
|
||||
│ ├── lib/
|
||||
│ │ ├── server/
|
||||
│ │ │ ├── db/
|
||||
│ │ │ │ ├── index.ts # Drizzle + postgres connection
|
||||
│ │ │ │ ├── schema.ts # All table definitions
|
||||
│ │ │ │ └── seed.ts # Optional seed data
|
||||
│ │ │ ├── auth.ts # Better Auth configuration
|
||||
│ │ │ ├── site-resolver.ts # Site loading by SITE_SLUG
|
||||
│ │ │ └── cdn.ts # CDN URL helpers
|
||||
│ │ └── shared/
|
||||
│ │ └── types.ts # Shared TypeScript types
|
||||
│ ├── routes/
|
||||
│ │ ├── +layout.server.ts # Root layout, loads site for all pages
|
||||
│ │ ├── +page.server.ts # Public homepage data loading
|
||||
│ │ ├── +page.svelte # Public homepage
|
||||
│ │ ├── login/
|
||||
│ │ │ └── +page.svelte # Login page (Discord redirect)
|
||||
│ │ ├── admin/
|
||||
│ │ │ ├── +layout.server.ts # Admin auth guard
|
||||
│ │ │ ├── +layout.svelte # Admin shell/nav
|
||||
│ │ │ ├── +page.svelte # Admin dashboard
|
||||
│ │ │ ├── settings/
|
||||
│ │ │ │ └── +page.svelte # Site settings editor
|
||||
│ │ │ ├── branding/
|
||||
│ │ │ │ └── +page.svelte # Logo, colors, theme
|
||||
│ │ │ ├── homepage/
|
||||
│ │ │ │ └── +page.svelte # Homepage content editor
|
||||
│ │ │ ├── links/
|
||||
│ │ │ │ └── +page.svelte # Nav and social links
|
||||
│ │ │ └── events/
|
||||
│ │ │ └── +page.svelte # Events manager
|
||||
│ │ └── api/
|
||||
│ │ └── auth/
|
||||
│ │ └── [...betterAuth] # Better Auth API routes
|
||||
│ └── styles/
|
||||
│ └── app.css # Global styles, CSS custom properties
|
||||
├── static/
|
||||
│ └── favicon.png
|
||||
├── Dockerfile
|
||||
├── docker-compose.yml # Optional, for local dev
|
||||
├── drizzle.config.ts
|
||||
├── package.json
|
||||
├── svelte.config.js
|
||||
├── tsconfig.json
|
||||
└── vite.config.ts
|
||||
```
|
||||
|
||||
## Auth Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant S as SvelteKit App
|
||||
participant DA as Discord OAuth
|
||||
participant DB as PostgreSQL
|
||||
|
||||
U->>S: Visit /login
|
||||
S->>DA: Redirect to Discord OAuth
|
||||
DA->>U: Authorize
|
||||
U->>S: Callback with OAuth code
|
||||
S->>DA: Exchange code for token + user info
|
||||
DA-->>S: Discord user (id, username, avatar)
|
||||
S->>DB: Upsert user record
|
||||
S->>DB: Check if Discord ID matches OWNER_DISCORD_ID
|
||||
S->>DB: Check if Discord ID matches SUPER_ADMIN_DISCORD_IDS
|
||||
DB-->>S: Match found → assign appropriate role for current site
|
||||
S->>S: Create session
|
||||
S-->>U: Redirect to /admin (or show access denied)
|
||||
```
|
||||
|
||||
### Ownership Bootstrap
|
||||
|
||||
On first login, the app compares the user's Discord ID against the `OWNER_DISCORD_ID` environment variable. If they match:
|
||||
1. A membership record is created (or confirmed) with role `owner` for the current site
|
||||
2. The env var acts as a bootstrap — once the owner exists in the database, the env var could theoretically be removed (though keeping it is fine)
|
||||
|
||||
Long-term, existing owners can add other admins/editors through the admin panel, and the database becomes the source of truth for all roles.
|
||||
|
||||
### Super Admin Access
|
||||
|
||||
The app also checks the user's Discord ID against `SUPER_ADMIN_DISCORD_IDS` (a comma-separated list). If a match is found:
|
||||
1. The user is granted cross-site admin access — they bypass site-scoped membership checks
|
||||
2. Super admins can access any site's admin panel regardless of `OWNER_DISCORD_ID`
|
||||
3. This is intended for David (system maintainer) to manage all sites
|
||||
4. Super admin access is checked on every request, not just at login
|
||||
|
||||
## Deployment Model
|
||||
|
||||
### Current: Multiple Coolify Deployments
|
||||
|
||||
```
|
||||
Git Repo (main branch)
|
||||
│
|
||||
├── Coolify Deployment "bad-movies-theater"
|
||||
│ └── Env: SITE_SLUG=bad-movies-theater
|
||||
│
|
||||
├── Coolify Deployment "garbage-day"
|
||||
│ └── Env: SITE_SLUG=garbage-day
|
||||
│
|
||||
└── Coolify Deployment "future-site"
|
||||
└── Env: SITE_SLUG=future-site
|
||||
```
|
||||
|
||||
Each deployment:
|
||||
- Points to the same Git repo + branch
|
||||
- Has its own set of environment variables
|
||||
- Connects to the same database
|
||||
- Uses the same CDN bucket
|
||||
- Is completely isolated at the container level
|
||||
|
||||
### Future: Single Deployment / Multi-Domain (Optional)
|
||||
|
||||
If desired later, the system could switch to a single deployment that resolves the site by domain name instead of `SITE_SLUG`:
|
||||
- Add a `domains` table or JSON field on `sites`
|
||||
- The site resolver checks the request's `Host` header
|
||||
- Falls back to `SITE_SLUG` for local dev
|
||||
|
||||
This is **not** needed for version 1 but the architecture supports it because all data is already scoped by `siteId`.
|
||||
|
||||
## CDN/Asset Architecture
|
||||
|
||||
```
|
||||
CDN Bucket: collective-hub
|
||||
├── sites/
|
||||
│ ├── bad-movies-theater/
|
||||
│ │ ├── logo.webp
|
||||
│ │ ├── background.webp
|
||||
│ │ └── events/
|
||||
│ │ └── movie-night-june.webp
|
||||
│ ├── garbage-day/
|
||||
│ │ ├── logo.webp
|
||||
│ │ └── background.webp
|
||||
│ └── future-site/
|
||||
│ └── logo.webp
|
||||
```
|
||||
|
||||
Key rules:
|
||||
- Database stores asset records with `cdnKey` (the path within the bucket)
|
||||
- Application constructs full CDN URLs using `CDN_BASE_URL` + `cdnKey`
|
||||
- Never hardcode full CDN URLs in the database
|
||||
- Assets are always scoped by `siteId` in the database
|
||||
- Path convention: `sites/{siteSlug}/{type}/{filename}`
|
||||
- All uploaded images are automatically converted to webp and optimized before storage
|
||||
|
||||
## Migration Safety
|
||||
|
||||
Multiple deployments sharing one database means migrations must be handled carefully:
|
||||
|
||||
- **Migrations run automatically on startup**, but only on the deployment with `RUN_MIGRATIONS=true`.
|
||||
- All other deployments (`RUN_MIGRATIONS=false`) skip migrations entirely.
|
||||
- **Exactly one deployment** must be designated the migration runner. Choose a stable, low-traffic deployment.
|
||||
- The migration runner must be deployed first when schema changes are included in a release.
|
||||
- Drizzle's migration tools handle idempotency — running the same migration twice is safe, but concurrent runs from multiple deployments must be avoided.
|
||||
- This is enforced by convention (the `RUN_MIGRATIONS` flag), not by a distributed lock. David must ensure only one deployment has the flag set to `true`.
|
||||
|
||||
## Key Architecture Decisions
|
||||
|
||||
| Decision | Choice | Rationale |
|
||||
|----------|--------|-----------|
|
||||
| Multi-deploy vs single-deploy | Multi-deploy first | Simpler initially, no domain-routing complexity |
|
||||
| siteId on every table | Yes | Multi-tenant from day one, no rewrite needed later |
|
||||
| JSON vs normalized tables | Prefer normalized; JSON for theme settings only | Queryable, type-safe, referential integrity |
|
||||
| CDN URLs in DB | Store keys only, not full URLs | CDN migration is trivial, no data changes needed |
|
||||
| Image processing | Auto webp conversion + optimization on upload | Consistent format, smaller files, better performance |
|
||||
| Auth library | Better Auth | First-class Discord support, SvelteKit integration |
|
||||
| Super admin | `SUPER_ADMIN_DISCORD_IDS` env var | Cross-site access for system maintainer |
|
||||
| Migration strategy | Automated, gated by `RUN_MIGRATIONS` flag | One deployment runs them; others skip |
|
||||
| ORM | Drizzle | Type-safe, lightweight, good Postgres support |
|
||||
@@ -0,0 +1,313 @@
|
||||
# Database Planning Document
|
||||
|
||||
## Design Principles
|
||||
|
||||
- **siteId on every site-owned table.** Non-negotiable.
|
||||
- **Prefer normalized tables over JSON columns** — except for theme/branding settings where flexibility is valuable.
|
||||
- **Timestamps on every table** (`createdAt`, `updatedAt`).
|
||||
- **Use UUIDs for primary keys** — avoids sequential ID enumeration and works well distributed.
|
||||
- **Index `siteId` on every table that has it** — it's the most common query filter.
|
||||
- **Soft deletes where appropriate** — prefer `deletedAt` over hard deletes for content that might be needed later.
|
||||
|
||||
---
|
||||
|
||||
## Tables
|
||||
|
||||
### `sites`
|
||||
|
||||
The core tenant table. One row per deployed site.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | `uuid` (PK) | |
|
||||
| `slug` | `text` (UNIQUE, NOT NULL) | Matches `SITE_SLUG` env var |
|
||||
| `name` | `text` (NOT NULL) | Display name |
|
||||
| `isActive` | `boolean` (default true) | Soft disable a site |
|
||||
| `createdAt` | `timestamptz` | |
|
||||
| `updatedAt` | `timestamptz` | |
|
||||
|
||||
**Indexes:** UNIQUE on `slug`.
|
||||
|
||||
---
|
||||
|
||||
### `users`
|
||||
|
||||
Auth users. Created automatically on first Discord login.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | `uuid` (PK) | |
|
||||
| `discordId` | `text` (UNIQUE, NOT NULL) | Discord user ID |
|
||||
| `discordUsername` | `text` | Display name from Discord |
|
||||
| `discordAvatar` | `text` | Avatar hash/URL from Discord |
|
||||
| `email` | `text` | If available from Discord scope |
|
||||
| `createdAt` | `timestamptz` | |
|
||||
| `updatedAt` | `timestamptz` | |
|
||||
| `lastLoginAt` | `timestamptz` | |
|
||||
|
||||
**Indexes:** UNIQUE on `discordId`.
|
||||
|
||||
**Note:** Better Auth manages its own session/account tables. The `users` table here is the application-level user profile. Better Auth tables are separate and managed by the library.
|
||||
|
||||
---
|
||||
|
||||
### `memberships`
|
||||
|
||||
Links users to sites with a role. A user can be a member of multiple sites with different roles.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | `uuid` (PK) | |
|
||||
| `siteId` | `uuid` → `sites.id` (NOT NULL) | |
|
||||
| `userId` | `uuid` → `users.id` (NOT NULL) | |
|
||||
| `role` | `enum('owner', 'admin', 'editor')` | See role definitions below |
|
||||
| `createdAt` | `timestamptz` | |
|
||||
| `updatedAt` | `timestamptz` | |
|
||||
|
||||
**Indexes:** UNIQUE on `(siteId, userId)`. INDEX on `siteId`. INDEX on `userId`.
|
||||
|
||||
**Role Definitions (V1):**
|
||||
- **owner** — Full control. Bootstrap via `OWNER_DISCORD_ID`. Can manage admins. One per site initially.
|
||||
- **admin** — Can edit all site settings and content. Cannot delete the site or manage the owner.
|
||||
- **editor** — Can edit content (events, pages) but not site settings or branding.
|
||||
|
||||
Future roles: `viewer`, `moderator` — not needed in V1.
|
||||
|
||||
---
|
||||
|
||||
### `siteSettings`
|
||||
|
||||
Key-value or JSON settings for a site. Two approaches are viable; recommendation below.
|
||||
|
||||
**Recommended approach: Single JSON column per site**
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | `uuid` (PK) | |
|
||||
| `siteId` | `uuid` → `sites.id` (UNIQUE, NOT NULL) | One settings row per site |
|
||||
| `settings` | `jsonb` (NOT NULL, default `{}`) | All site settings as JSON |
|
||||
| `createdAt` | `timestamptz` | |
|
||||
| `updatedAt` | `timestamptz` | |
|
||||
|
||||
**Indexes:** UNIQUE on `siteId`.
|
||||
|
||||
The `settings` JSON would contain:
|
||||
|
||||
```json
|
||||
{
|
||||
"branding": {
|
||||
"siteName": "Bad Movies Theater",
|
||||
"tagline": "Terrible movies, great company",
|
||||
"logoCdnKey": "sites/bad-movies-theater/logo.webp",
|
||||
"backgroundCdnKey": "sites/bad-movies-theater/background.webp",
|
||||
"faviconCdnKey": null
|
||||
},
|
||||
"theme": {
|
||||
"preset": "dark",
|
||||
"accentColor": "#e63946",
|
||||
"backgroundColor": "#1a1a2e",
|
||||
"textColor": "#eaeaea"
|
||||
},
|
||||
"homepage": {
|
||||
"heroTitle": "Welcome to Bad Movies Theater",
|
||||
"heroSubtitle": "We watch bad movies so you don't have to",
|
||||
"aboutText": "A community of bad movie enthusiasts...",
|
||||
"primaryButtonText": "Join us on Discord",
|
||||
"primaryButtonLink": "https://discord.gg/example",
|
||||
"showNextEvent": true,
|
||||
"showSchedule": true
|
||||
},
|
||||
"layout": {
|
||||
"preset": "standard"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Why JSON for settings?** Settings are read as a batch, rarely queried individually, and benefit from schema flexibility. If you add a new setting, no migration is needed.
|
||||
|
||||
**Alternative (not recommended for V1):** Key-value table with `siteId`, `key`, `value` columns. More queryable but more complex for nested settings.
|
||||
|
||||
---
|
||||
|
||||
### `assets`
|
||||
|
||||
Records of uploaded or referenced media files stored in the CDN.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | `uuid` (PK) | |
|
||||
| `siteId` | `uuid` → `sites.id` (NOT NULL) | |
|
||||
| `uploadedByUserId` | `uuid` → `users.id` | Nullable for system assets |
|
||||
| `type` | `text` (NOT NULL) | e.g., `image`, `document` |
|
||||
| `filename` | `text` (NOT NULL) | Original filename |
|
||||
| `mimeType` | `text` | e.g., `image/webp` |
|
||||
| `size` | `integer` | Bytes |
|
||||
| `cdnKey` | `text` (NOT NULL) | Path within CDN bucket |
|
||||
| `altText` | `text` | Accessibility description |
|
||||
| `createdAt` | `timestamptz` | |
|
||||
| `updatedAt` | `timestamptz` | |
|
||||
|
||||
**Indexes:** INDEX on `siteId`. INDEX on `cdnKey`.
|
||||
|
||||
**V1 approach:** Assets table may start as a manual-reference table (paste CDN URLs) before automatic upload flow is built. This is fine — the table structure supports both.
|
||||
|
||||
---
|
||||
|
||||
### `navLinks`
|
||||
|
||||
Custom navigation links for a site's header/footer.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | `uuid` (PK) | |
|
||||
| `siteId` | `uuid` → `sites.id` (NOT NULL) | |
|
||||
| `label` | `text` (NOT NULL) | Display text |
|
||||
| `url` | `text` (NOT NULL) | Link target |
|
||||
| `position` | `text` (default `'header'`) | `header` or `footer` |
|
||||
| `sortOrder` | `integer` (default 0) | Ordering within position |
|
||||
| `isExternal` | `boolean` (default true) | Open in new tab? |
|
||||
| `createdAt` | `timestamptz` | |
|
||||
| `updatedAt` | `timestamptz` | |
|
||||
|
||||
**Indexes:** INDEX on `(siteId, position, sortOrder)`.
|
||||
|
||||
---
|
||||
|
||||
### `socialLinks`
|
||||
|
||||
Social media / external platform links.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | `uuid` (PK) | |
|
||||
| `siteId` | `uuid` → `sites.id` (NOT NULL) | |
|
||||
| `platform` | `text` (NOT NULL) | e.g., `discord`, `twitter`, `youtube`, `twitch` |
|
||||
| `label` | `text` | Display label, defaults to platform name |
|
||||
| `url` | `text` (NOT NULL) | |
|
||||
| `icon` | `text` | Icon identifier if custom |
|
||||
| `sortOrder` | `integer` (default 0) | |
|
||||
| `createdAt` | `timestamptz` | |
|
||||
| `updatedAt` | `timestamptz` | |
|
||||
|
||||
**Indexes:** INDEX on `(siteId, sortOrder)`.
|
||||
|
||||
---
|
||||
|
||||
### `events`
|
||||
|
||||
Scheduled events / watch parties / screenings.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | `uuid` (PK) | |
|
||||
| `siteId` | `uuid` → `sites.id` (NOT NULL) | |
|
||||
| `title` | `text` (NOT NULL) | |
|
||||
| `description` | `text` | |
|
||||
| `eventType` | `text` (default `'screening'`) | `screening`, `watch_party`, `meetup`, `other` |
|
||||
| `startTime` | `timestamptz` (NOT NULL) | |
|
||||
| `endTime` | `timestamptz` | Optional, for duration |
|
||||
| `timezone` | `text` (default `'America/New_York'`) | IANA timezone |
|
||||
| `location` | `text` | e.g., "Discord Stage", "VR Chat", "Online" |
|
||||
| `externalLink` | `text` | Link to event page, stream, etc. |
|
||||
| `imageCdnKey` | `text` | Optional event image |
|
||||
| `isPublished` | `boolean` (default false) | Draft mode |
|
||||
| `isRecurring` | `boolean` (default false) | Placeholder for future recurring support |
|
||||
| `createdAt` | `timestamptz` | |
|
||||
| `updatedAt` | `timestamptz` | |
|
||||
|
||||
**Indexes:** INDEX on `(siteId, startTime)`. INDEX on `(siteId, isPublished)`.
|
||||
|
||||
**Recurring events:** V1 treats all events as one-off. The `isRecurring` flag is a placeholder. A future phase could add a `recurrenceRule` field (JSON or a separate table) for repeat patterns. Don't build recurring logic in V1.
|
||||
|
||||
---
|
||||
|
||||
### `homepageSections` (Optional V1)
|
||||
|
||||
If the homepage needs more structure than a single text block, sections allow ordered content blocks.
|
||||
|
||||
| Column | Type | Notes |
|
||||
|--------|------|-------|
|
||||
| `id` | `uuid` (PK) | |
|
||||
| `siteId` | `uuid` → `sites.id` (NOT NULL) | |
|
||||
| `type` | `text` (NOT NULL) | `hero`, `about`, `events`, `links`, `custom` |
|
||||
| `title` | `text` | Section heading |
|
||||
| `content` | `text` | Markdown or plain text |
|
||||
| `settings` | `jsonb` | Section-specific config |
|
||||
| `sortOrder` | `integer` (default 0) | |
|
||||
| `isVisible` | `boolean` (default true) | |
|
||||
| `createdAt` | `timestamptz` | |
|
||||
| `updatedAt` | `timestamptz` | |
|
||||
|
||||
**Indexes:** INDEX on `(siteId, sortOrder)`.
|
||||
|
||||
**V1 recommendation:** Start without this table. Use the `homepage` JSON in `siteSettings` for the first version. Add sections in Phase 2+ if sites need more flexible page building.
|
||||
|
||||
---
|
||||
|
||||
## Entity Relationship Summary
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
sites ||--o{ memberships : "has"
|
||||
sites ||--|| siteSettings : "has"
|
||||
sites ||--o{ assets : "owns"
|
||||
sites ||--o{ navLinks : "has"
|
||||
sites ||--o{ socialLinks : "has"
|
||||
sites ||--o{ events : "hosts"
|
||||
users ||--o{ memberships : "has"
|
||||
users ||--o{ assets : "uploads"
|
||||
|
||||
sites {
|
||||
uuid id PK
|
||||
text slug UK
|
||||
text name
|
||||
boolean isActive
|
||||
}
|
||||
|
||||
users {
|
||||
uuid id PK
|
||||
text discordId UK
|
||||
text discordUsername
|
||||
text discordAvatar
|
||||
}
|
||||
|
||||
memberships {
|
||||
uuid id PK
|
||||
uuid siteId FK
|
||||
uuid userId FK
|
||||
enum role
|
||||
}
|
||||
|
||||
siteSettings {
|
||||
uuid id PK
|
||||
uuid siteId FK UK
|
||||
jsonb settings
|
||||
}
|
||||
|
||||
events {
|
||||
uuid id PK
|
||||
uuid siteId FK
|
||||
text title
|
||||
timestamptz startTime
|
||||
boolean isPublished
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
1. **All migrations run manually** — not on app startup. David runs `drizzle-kit migrate` locally or via a primary deployment.
|
||||
2. **Additive changes only in production** — new columns, new tables. Avoid renames or destructive changes without a plan.
|
||||
3. **JSON columns for settings** reduce migration frequency for feature additions.
|
||||
4. **Seed data** — a seed script can populate the initial site record for a new deployment, or David creates the site row manually.
|
||||
|
||||
## What This Schema Intentionally Avoids
|
||||
|
||||
- **No `accounts` or `sessions` tables** — Better Auth manages those.
|
||||
- **No `pages` table for V1** — homepage content lives in `siteSettings.homepage` JSON.
|
||||
- **No `reviews`, `comments`, `posts` tables** — future phases.
|
||||
- **No `featureFlags` table** — use env vars or settings JSON for now.
|
||||
- **No `domains` table** — single `SITE_SLUG` resolution in V1.
|
||||
- **No `auditLog` table** — nice to have later, not needed for V1.
|
||||
- **No `invitations` table** — owner adds admins directly in V1, no invite flow.
|
||||
@@ -0,0 +1,163 @@
|
||||
# Feature Roadmap
|
||||
|
||||
## How to Read This
|
||||
|
||||
Each phase builds on the previous one. Phases are ordered by dependency, not by importance.
|
||||
|
||||
**The rule:** Phase 1 must be complete and working before starting Phase 2. Later phases can be reordered based on need.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Foundation Minimum Viable Product
|
||||
|
||||
**Goal:** A working SvelteKit app that resolves a site by `SITE_SLUG`, shows a public homepage, lets the owner log in and edit settings, and supports image uploads with CDN storage.
|
||||
|
||||
### Deliverables
|
||||
|
||||
- [ ] SvelteKit project initialized with TypeScript
|
||||
- [ ] Drizzle ORM configured, connected to Postgres
|
||||
- [ ] Core database tables created: `sites`, `users`, `memberships`, `siteSettings`, `assets`
|
||||
- [ ] Better Auth integrated with Discord OAuth provider
|
||||
- [ ] Site resolver: reads `SITE_SLUG`, loads site + settings from DB, attaches to `locals`
|
||||
- [ ] Public homepage renders with site name and basic content
|
||||
- [ ] Login page: "Login with Discord" button
|
||||
- [ ] Owner bootstrap: `OWNER_DISCORD_ID` env var creates owner membership on first login
|
||||
- [ ] Super admin bootstrap: `SUPER_ADMIN_DISCORD_IDS` env var grants cross-site access
|
||||
- [ ] Admin auth guard: `/admin/*` routes redirect unauthenticated users to login
|
||||
- [ ] Basic admin dashboard page (placeholder with site name)
|
||||
- [ ] Admin settings page: edit site name and tagline (saved to `siteSettings` JSON)
|
||||
- [ ] CDN storage integration (Bunny CDN or S3-compatible)
|
||||
- [ ] Image upload endpoint with webp conversion and optimization
|
||||
- [ ] File validation: accepted types, max size
|
||||
- [ ] Asset records created in database on upload
|
||||
- [ ] Asset library page in admin: browse, search, copy CDN URL
|
||||
- [ ] Migration automation: primary deployment runs migrations on startup; others skip via `RUN_MIGRATIONS` env var
|
||||
|
||||
### What's NOT in Phase 1
|
||||
- No branding customization (logo, colors) — Phase 2
|
||||
- No homepage content editing beyond name/tagline — Phase 2
|
||||
- No events, nav links, social links — Phase 2 / Phase 4
|
||||
- No role management UI — Phase 5
|
||||
- No super admin dashboard UI — Phase 5
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Branding & Customization
|
||||
|
||||
**Goal:** Site owners can customize the look and feel of their site. The public site reflects branding settings. Asset upload is already available from Phase 1.
|
||||
|
||||
### Deliverables
|
||||
|
||||
- [ ] Admin branding page: select logo, background image, favicon from asset library
|
||||
- [ ] Admin theme page: preset selector (dark/light/custom), accent color, background color, text color
|
||||
- [ ] CSS custom properties generated from theme settings
|
||||
- [ ] Admin homepage editor: hero title, subtitle, about text, CTA button text/link
|
||||
- [ ] Public site renders all branding and homepage settings
|
||||
- [ ] Admin nav links manager: add, edit, reorder, delete header/footer links
|
||||
- [ ] Admin social links manager: add, edit, reorder, delete social platform links
|
||||
- [ ] Public site renders nav links and social links
|
||||
- [ ] Layout preset support (single configurable layout for V1)
|
||||
|
||||
### What's NOT in Phase 2
|
||||
- Multiple layout options (just one flexible layout)
|
||||
- Custom CSS fields
|
||||
- Per-page theming
|
||||
- Theme marketplace or sharing
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Events & Schedule
|
||||
|
||||
**Goal:** Sites can display upcoming events. Admins can manage events through the admin panel.
|
||||
|
||||
### Deliverables
|
||||
|
||||
- [ ] Events table created (if not already)
|
||||
- [ ] Admin events manager: create, edit, delete, publish/unpublish events
|
||||
- [ ] Event fields: title, description, type, start time, end time, timezone, location, external link, image
|
||||
- [ ] Public homepage: "Next Event" card (shows the next upcoming published event)
|
||||
- [ ] Public homepage: "Upcoming Events" list/schedule section
|
||||
- [ ] Event detail page (optional — can be a modal or external link for V1)
|
||||
- [ ] Timezone display handling (show event time in visitor's local time via JS)
|
||||
|
||||
### What's NOT in Phase 3
|
||||
- Recurring/repeating events
|
||||
- Calendar feed (iCal/RSS)
|
||||
- Event reminders or notifications
|
||||
- Attendee RSVPs
|
||||
- Integration with Discord events
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Super Admin Dashboard
|
||||
|
||||
**Goal:** David (system maintainer) can manage all sites from a central dashboard.
|
||||
|
||||
### Deliverables
|
||||
|
||||
- [ ] Super admin auth: `SUPER_ADMIN_DISCORD_IDS` env var bypasses site-scoped membership checks
|
||||
- [ ] Super admin dashboard: list all sites with status, quick links
|
||||
- [ ] Create new site flow: insert site row, generate setup instructions
|
||||
- [ ] View any site's settings, events, assets (read-only cross-site access)
|
||||
- [ ] Feature flag management across sites
|
||||
- [ ] Site deactivation/reactivation
|
||||
|
||||
### What's NOT in Phase 4
|
||||
- Full site provisioning automation (still manual Coolify setup)
|
||||
- Usage analytics or billing
|
||||
- Impersonation (login as site owner)
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Admin Improvements
|
||||
|
||||
**Goal:** Better admin experience, role management, and operational tooling.
|
||||
|
||||
### Deliverables
|
||||
|
||||
- [ ] Role management: owner can add/remove admins and editors
|
||||
- [ ] Admin list page showing all team members with roles
|
||||
- [ ] Preview mode: admins can preview unpublished changes
|
||||
- [ ] Improved admin dashboard with quick stats
|
||||
- [ ] Site cloning helper (manual or scripted) for creating new sites
|
||||
- [ ] Feature flags via settings JSON or env vars
|
||||
- [ ] Audit-like log of who changed what (basic)
|
||||
- [ ] Enhanced super admin dashboard: cross-site search, bulk operations
|
||||
|
||||
### What's NOT in Phase 5
|
||||
- Full audit trail with rollback
|
||||
- Granular permission system
|
||||
- Multi-owner support per site
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Future (Optional, Not Planned in Detail)
|
||||
|
||||
These are ideas for later. Do not build any of these until Phases 1-5 are solid.
|
||||
|
||||
- **Community features:** reviews, comments, discussion posts
|
||||
- **Discord integration:** server widget, event sync, role sync
|
||||
- **Calendar feeds:** iCal export, Google Calendar integration
|
||||
- **AI tools:** content suggestions, event descriptions, semantic search (pgvector)
|
||||
- **Advanced theming:** multiple layout presets, custom CSS per site
|
||||
- **Analytics:** page views, event clicks, simple dashboard
|
||||
- **Email notifications:** event reminders, new content alerts
|
||||
- **Single-deployment model:** switch from multi-Coolify-deployment to one deployment resolving sites by domain
|
||||
- **Public API:** read-only API for events and site info
|
||||
|
||||
---
|
||||
|
||||
## Phase Dependency Diagram
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
P1[Phase 1: Foundation + Assets] --> P2[Phase 2: Branding & Customization]
|
||||
P1 --> P3[Phase 3: Events & Schedule]
|
||||
P2 --> P3
|
||||
P1 --> P4[Phase 4: Super Admin Dashboard]
|
||||
P3 --> P5[Phase 5: Admin Improvements]
|
||||
P4 --> P5
|
||||
P5 --> P6[Phase 6: Future Features]
|
||||
```
|
||||
|
||||
**Note:** Phase 1 now includes CDN + asset upload (previously Phase 3). Phase 4 (Super Admin Dashboard) can start as soon as Phase 1 is done — it's independent of branding and events. Phase 5 enhances both regular admin and super admin experiences.
|
||||
@@ -0,0 +1,192 @@
|
||||
# Environment Variables Document — The Collective Hub
|
||||
|
||||
## Overview
|
||||
|
||||
Environment variables are the only difference between deployments. Each Coolify deployment has its own set of env vars, but all deployments share the same database, CDN, and Discord OAuth app.
|
||||
|
||||
---
|
||||
|
||||
## Variable Reference
|
||||
|
||||
### Required for Every Deployment
|
||||
|
||||
| Variable | Example | Description | Shared or Per-Site? |
|
||||
|----------|---------|-------------|---------------------|
|
||||
| `SITE_SLUG` | `bad-movies-theater` | Identifies which site this deployment serves. Must match a `slug` in the `sites` table. | **Per-site** |
|
||||
| `PUBLIC_SITE_URL` | `https://badmovies.example.com` | The public URL of this deployment. Used for auth callbacks, canonical URLs. | **Per-site** |
|
||||
| `DATABASE_URL` | `postgresql://user:pass@host:5432/collective_hub` | Postgres connection string. | **Shared** (same for all) |
|
||||
| `BETTER_AUTH_SECRET` | (generated) | Secret key for Better Auth session signing. | **Shared** (same for all) |
|
||||
| `BETTER_AUTH_URL` | `https://badmovies.example.com` | Base URL for auth callbacks. Must match `PUBLIC_SITE_URL`. | **Per-site** |
|
||||
| `DISCORD_CLIENT_ID` | `123456789012345678` | Discord OAuth application client ID. | **Shared** |
|
||||
| `DISCORD_CLIENT_SECRET` | `abc123...` | Discord OAuth application client secret. | **Shared** |
|
||||
| `OWNER_DISCORD_ID` | `123456789012345678` | Discord user ID of the site owner. Used to bootstrap ownership on first login. | **Per-site** |
|
||||
|
||||
### Required for CDN (Phase 1)
|
||||
|
||||
| Variable | Example | Description | Shared or Per-Site? |
|
||||
|----------|---------|-------------|---------------------|
|
||||
| `CDN_BASE_URL` | `https://cdn.example.com` | Base URL for constructing CDN URLs. | **Shared** |
|
||||
| `CDN_STORAGE_ENDPOINT` | `https://ny.storage.bunnycdn.com` | Storage API endpoint. | **Shared** |
|
||||
| `CDN_ACCESS_KEY` | `abc123...` | Storage access key. | **Shared** |
|
||||
| `CDN_SECRET_KEY` | (S3 only) | Secret key for S3-compatible storage. | **Shared** |
|
||||
| `CDN_BUCKET` | `collective-hub` | Bucket or storage zone name. | **Shared** |
|
||||
| `CDN_REGION` | `us-east-1` | Region for S3-compatible storage. | **Shared** |
|
||||
|
||||
### Super Admin
|
||||
|
||||
| Variable | Example | Description | Shared or Per-Site? |
|
||||
|----------|---------|-------------|---------------------|
|
||||
| `SUPER_ADMIN_DISCORD_IDS` | `123456789,987654321` | Comma-separated Discord user IDs with cross-site super admin access. | **Shared** |
|
||||
|
||||
### Migration Control
|
||||
|
||||
| Variable | Example | Description | Shared or Per-Site? |
|
||||
|----------|---------|-------------|---------------------|
|
||||
| `RUN_MIGRATIONS` | `true` | Whether this deployment should run database migrations on startup. Only one deployment should have this set to `true`. | **Per-site** (only one `true`) |
|
||||
|
||||
### Optional
|
||||
|
||||
| Variable | Example | Description | Shared or Per-Site? |
|
||||
|----------|---------|-------------|---------------------|
|
||||
| `NODE_ENV` | `production` | Node environment. | **Per-site** (usually `production`) |
|
||||
| `LOG_LEVEL` | `info` | Logging verbosity. | **Per-site** |
|
||||
| `FEATURE_FLAGS` | `events:on` | Comma-separated feature flags (future). | **Per-site** |
|
||||
|
||||
---
|
||||
|
||||
## Example: Full Deployment Env File
|
||||
|
||||
### Deployment: bad-movies-theater (primary — runs migrations)
|
||||
|
||||
```env
|
||||
# Site Identity
|
||||
SITE_SLUG=bad-movies-theater
|
||||
PUBLIC_SITE_URL=https://badmovies.example.com
|
||||
|
||||
# Database (shared)
|
||||
DATABASE_URL=postgresql://hub_app:password@db.example.com:5432/collective_hub
|
||||
|
||||
# Auth (Better Auth)
|
||||
BETTER_AUTH_SECRET=generated-secret-value-here
|
||||
BETTER_AUTH_URL=https://badmovies.example.com
|
||||
|
||||
# Discord OAuth (shared)
|
||||
DISCORD_CLIENT_ID=123456789012345678
|
||||
DISCORD_CLIENT_SECRET=your-discord-client-secret
|
||||
|
||||
# Ownership Bootstrap
|
||||
OWNER_DISCORD_ID=123456789012345678
|
||||
|
||||
# Super Admin
|
||||
SUPER_ADMIN_DISCORD_IDS=111111111111111111
|
||||
|
||||
# Migration Control
|
||||
RUN_MIGRATIONS=true
|
||||
|
||||
# CDN (shared)
|
||||
CDN_BASE_URL=https://cdn.example.com
|
||||
CDN_STORAGE_ENDPOINT=https://ny.storage.bunnycdn.com
|
||||
CDN_ACCESS_KEY=your-bunny-access-key
|
||||
CDN_BUCKET=collective-hub
|
||||
|
||||
# Optional
|
||||
NODE_ENV=production
|
||||
LOG_LEVEL=info
|
||||
```
|
||||
|
||||
### Deployment: garbage-day (secondary — skips migrations)
|
||||
|
||||
```env
|
||||
# Site Identity
|
||||
SITE_SLUG=garbage-day
|
||||
PUBLIC_SITE_URL=https://garbageday.example.com
|
||||
|
||||
# Database (shared — same value)
|
||||
DATABASE_URL=postgresql://hub_app:password@db.example.com:5432/collective_hub
|
||||
|
||||
# Auth (Better Auth)
|
||||
BETTER_AUTH_SECRET=generated-secret-value-here
|
||||
BETTER_AUTH_URL=https://garbageday.example.com
|
||||
|
||||
# Discord OAuth (shared — same value)
|
||||
DISCORD_CLIENT_ID=123456789012345678
|
||||
DISCORD_CLIENT_SECRET=your-discord-client-secret
|
||||
|
||||
# Ownership Bootstrap
|
||||
OWNER_DISCORD_ID=987654321098765432
|
||||
|
||||
# Super Admin (same value)
|
||||
SUPER_ADMIN_DISCORD_IDS=111111111111111111
|
||||
|
||||
# Migration Control
|
||||
RUN_MIGRATIONS=false
|
||||
|
||||
# CDN (shared — same values)
|
||||
CDN_BASE_URL=https://cdn.example.com
|
||||
CDN_STORAGE_ENDPOINT=https://ny.storage.bunnycdn.com
|
||||
CDN_ACCESS_KEY=your-bunny-access-key
|
||||
CDN_BUCKET=collective-hub
|
||||
|
||||
# Optional
|
||||
NODE_ENV=production
|
||||
LOG_LEVEL=info
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What's Shared vs Per-Site
|
||||
|
||||
```
|
||||
Shared across ALL deployments:
|
||||
├── DATABASE_URL (one database)
|
||||
├── BETTER_AUTH_SECRET (same session signing key)
|
||||
├── DISCORD_CLIENT_ID (one Discord OAuth app)
|
||||
├── DISCORD_CLIENT_SECRET
|
||||
├── SUPER_ADMIN_DISCORD_IDS (system maintainers)
|
||||
├── CDN_BASE_URL (one CDN bucket)
|
||||
├── CDN_STORAGE_ENDPOINT
|
||||
├── CDN_ACCESS_KEY
|
||||
├── CDN_SECRET_KEY (if S3)
|
||||
├── CDN_BUCKET
|
||||
└── CDN_REGION (if S3)
|
||||
|
||||
Unique per deployment:
|
||||
├── SITE_SLUG (which site this is)
|
||||
├── PUBLIC_SITE_URL (its domain)
|
||||
├── BETTER_AUTH_URL (must match PUBLIC_SITE_URL)
|
||||
├── OWNER_DISCORD_ID (who owns this site)
|
||||
└── RUN_MIGRATIONS (only one deployment = true)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes & Warnings
|
||||
|
||||
### Discord OAuth: Shared App
|
||||
|
||||
All sites share one Discord OAuth application. This means:
|
||||
- Users see the same app name when authorizing (e.g., "The Collective Hub")
|
||||
- The OAuth redirect URL list must include every site's callback URL
|
||||
- Discord has a limit on redirect URLs — manageable for a handful of sites
|
||||
- If the system grows to many sites, each site may need its own Discord OAuth app, or a central auth domain pattern should be introduced
|
||||
|
||||
### Better Auth Secret
|
||||
|
||||
`BETTER_AUTH_SECRET` must be the same across all deployments because sessions are signed with it. This enables super admins to potentially navigate between site admin panels with a single session (future enhancement).
|
||||
|
||||
### Database Migrations — Automated but Coordinated
|
||||
|
||||
Migrations run automatically on app startup, but only on the deployment with `RUN_MIGRATIONS=true`. All other deployments skip migrations (`RUN_MIGRATIONS=false`). This means:
|
||||
|
||||
- **Exactly one deployment** is designated as the migration runner
|
||||
- That deployment must be deployed first when schema changes are made
|
||||
- If the migration runner is down, other deployments still work (they just can't run new migrations)
|
||||
- Choose a stable, low-traffic deployment as the migration runner (or the super admin dashboard deployment)
|
||||
|
||||
### Super Admin Access
|
||||
|
||||
`SUPER_ADMIN_DISCORD_IDS` is a comma-separated list of Discord user IDs. Users matching these IDs bypass site-scoped membership checks and can access any site's admin panel. This is intended for David (system maintainer) and should be kept to a minimal, trusted set of IDs.
|
||||
|
||||
### Sensitive Values
|
||||
|
||||
All secrets (database URL, auth secrets, Discord secrets, CDN keys) must be stored securely in Coolify's environment variable management — never committed to the repository.
|
||||
@@ -0,0 +1,265 @@
|
||||
# Admin UX Planning Document — The Collective Hub
|
||||
|
||||
## Design Principles
|
||||
|
||||
- **Practical over fancy.** A basic form that works beats a beautiful UI that's confusing.
|
||||
- **One page per concern.** Settings, branding, homepage, links, events, assets — each gets its own admin page.
|
||||
- **Instant feedback.** Save button with clear success/error state. No ambiguous "it might have saved" experiences.
|
||||
- **Site-scoped by default, super admin cross-site.** Regular admins see only their site. Super admins (David) can access any site's admin panel.
|
||||
- **Mobile-accessible but desktop-first.** Admins will primarily manage their site from a desktop/laptop.
|
||||
|
||||
---
|
||||
|
||||
## Login Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant A as Admin/Owner
|
||||
participant S as Site
|
||||
participant D as Discord
|
||||
|
||||
A->>S: Clicks "Admin" or visits /admin
|
||||
S->>S: Check session
|
||||
S-->>A: Redirect to /login (if not logged in)
|
||||
A->>S: Clicks "Login with Discord"
|
||||
S->>D: Redirect to Discord OAuth
|
||||
D->>A: Authorize screen
|
||||
A->>D: Approve
|
||||
D->>S: Callback with code
|
||||
S->>S: Exchange code, get user info
|
||||
S->>S: Check OWNER_DISCORD_ID match
|
||||
S->>S: Create/confirm membership (owner role)
|
||||
S->>S: Create session
|
||||
S-->>A: Redirect to /admin
|
||||
```
|
||||
|
||||
### Login Page
|
||||
|
||||
A simple, centered page with:
|
||||
- Site logo (or site name if no logo set)
|
||||
- "Login with Discord" button (prominent, branded)
|
||||
- Brief explanation: "Sign in to manage [Site Name]"
|
||||
- No other login methods in V1
|
||||
|
||||
### First Owner Login
|
||||
|
||||
1. Owner visits `/login`
|
||||
2. Logs in with Discord
|
||||
3. System detects their Discord ID matches `OWNER_DISCORD_ID`
|
||||
4. Owner membership created automatically
|
||||
5. Redirected to admin dashboard
|
||||
6. Dashboard shows: "Welcome, [username]. You are the owner of [Site Name]."
|
||||
|
||||
### Super Admin Login
|
||||
|
||||
Super admins (Discord IDs listed in `SUPER_ADMIN_DISCORD_IDS`):
|
||||
- Can log in to any site's admin panel regardless of `OWNER_DISCORD_ID`
|
||||
- See a "Super Admin" badge or indicator in the admin UI
|
||||
- Have a "View All Sites" link (placeholdered until Phase 4 super admin dashboard)
|
||||
- Can perform all actions a site owner can
|
||||
|
||||
### Non-Owner Login (Before Role Management)
|
||||
|
||||
If a non-owner, non-super-admin logs in (Phase 1-4 before role management exists):
|
||||
- They are authenticated but have no membership for the current site
|
||||
- Show: "You don't have access to manage this site. Contact the site owner."
|
||||
- No admin pages are accessible
|
||||
|
||||
### Session Behavior
|
||||
|
||||
- Session persists across browser restarts (HTTP-only cookie via Better Auth)
|
||||
- Logout button in admin nav clears session
|
||||
- Session expiry: Better Auth defaults (configurable)
|
||||
|
||||
---
|
||||
|
||||
## Admin Layout
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ [Logo/Name] Admin Panel [User] [Logout] │
|
||||
├──────────┬───────────────────────────────────┤
|
||||
│ │ │
|
||||
│ Dashboard│ │
|
||||
│ Settings │ Content Area │
|
||||
│ Branding │ │
|
||||
│ Homepage │ │
|
||||
│ Links │ │
|
||||
│ Events │ │
|
||||
│ Assets │ │
|
||||
│ Team │ │
|
||||
│ │ │
|
||||
└──────────┴───────────────────────────────────┘
|
||||
```
|
||||
|
||||
- **Left sidebar:** Navigation links. Highlight current page. Collapse on mobile (hamburger).
|
||||
- **Top bar:** Site name, current user avatar + name, logout button.
|
||||
- **Content area:** The active page content.
|
||||
|
||||
---
|
||||
|
||||
## Admin Pages
|
||||
|
||||
### Dashboard (`/admin`)
|
||||
|
||||
**Purpose:** Quick overview and navigation hub.
|
||||
|
||||
**Content:**
|
||||
- Welcome message with owner name
|
||||
- Site status: "Your site is live at [URL]"
|
||||
- Quick stats (future): event count, page views
|
||||
- Quick links to common actions: "Edit Homepage", "Manage Events"
|
||||
- In V1, this can be minimal—a simple landing page after login
|
||||
|
||||
### Settings (`/admin/settings`)
|
||||
|
||||
**Purpose:** Basic site identity.
|
||||
|
||||
**Fields:**
|
||||
- Site name (text input)
|
||||
- Tagline (text input)
|
||||
- Save button
|
||||
|
||||
**Behavior:**
|
||||
- Load current values from `siteSettings` JSON
|
||||
- Save updates the JSON blob
|
||||
- Success toast: "Settings saved"
|
||||
- Error toast with specific message on failure
|
||||
|
||||
### Branding (`/admin/branding`)
|
||||
|
||||
**Purpose:** Visual identity and theme.
|
||||
|
||||
**Fields:**
|
||||
- Logo: file upload button OR manual URL input (Phase 2: asset picker from library)
|
||||
- Background image: same pattern
|
||||
- Favicon: file upload
|
||||
- Theme preset: dropdown (Dark, Light, Custom)
|
||||
- Accent color: color picker + hex input
|
||||
- Background color: color picker + hex input
|
||||
- Text color: color picker + hex input
|
||||
|
||||
**Behavior:**
|
||||
- Color pickers show live preview of the color
|
||||
- "Preview" link opens public site in new tab
|
||||
- Save updates `siteSettings.branding` and `siteSettings.theme` in JSON
|
||||
|
||||
### Homepage (`/admin/homepage`)
|
||||
|
||||
**Purpose:** Edit public homepage content.
|
||||
|
||||
**Fields:**
|
||||
- Hero title (text input)
|
||||
- Hero subtitle (text input)
|
||||
- About/intro text (textarea, plain text or basic Markdown)
|
||||
- Primary button text (text input, e.g., "Join Discord")
|
||||
- Primary button link (URL input)
|
||||
- Toggle: Show next event section (checkbox)
|
||||
- Toggle: Show schedule section (checkbox)
|
||||
|
||||
**Behavior:**
|
||||
- All fields are optional — empty fields are hidden on the public site
|
||||
- Save updates `siteSettings.homepage` in JSON
|
||||
- "View site" link opens public homepage in new tab
|
||||
|
||||
### Links (`/admin/links`)
|
||||
|
||||
**Purpose:** Manage navigation and social links.
|
||||
|
||||
**Sub-pages or tabs:**
|
||||
- **Nav Links tab:** Table of links with label, URL, position (header/footer), sort order
|
||||
- **Social Links tab:** Table of links with platform (dropdown: Discord, Twitter/X, YouTube, Twitch, etc.), label, URL, sort order
|
||||
|
||||
**Behavior:**
|
||||
- Add new link: inline form at top or modal
|
||||
- Edit: inline or modal
|
||||
- Delete: with confirmation
|
||||
- Drag-to-reorder (nice-to-have, manual sort order numbers are fine for V1)
|
||||
- Save is per-link or "Save all changes" button
|
||||
|
||||
### Events (`/admin/events`)
|
||||
|
||||
**Purpose:** Manage event listings.
|
||||
|
||||
**List view:**
|
||||
- Table: title, date/time, status (published/draft), actions (edit/delete)
|
||||
- "Add Event" button
|
||||
- Filter: upcoming, past, drafts
|
||||
|
||||
**Event edit/create form:**
|
||||
- Title (text, required)
|
||||
- Description (textarea)
|
||||
- Event type (dropdown: Screening, Watch Party, Meetup, Other)
|
||||
- Start time (datetime picker)
|
||||
- End time (datetime picker, optional)
|
||||
- Timezone (dropdown, defaults to `America/New_York`)
|
||||
- Location (text, e.g., "Discord Stage")
|
||||
- External link (URL)
|
||||
- Event image (upload or URL)
|
||||
- Published toggle
|
||||
|
||||
**Behavior:**
|
||||
- Events sorted by start time
|
||||
- Draft events hidden from public site
|
||||
- Delete with confirmation
|
||||
- Basic validation: title required, start time required
|
||||
|
||||
### Assets (`/admin/assets`)
|
||||
|
||||
**Purpose:** Browse and manage uploaded files.
|
||||
|
||||
**List view:**
|
||||
- Grid or table of assets with thumbnail, filename, type, size, date
|
||||
- Search/filter by filename
|
||||
- Click to copy CDN URL
|
||||
- Delete with confirmation
|
||||
|
||||
**Upload:**
|
||||
- Drag-and-drop zone or file input
|
||||
- Accept: image/webp, image/png, image/jpeg
|
||||
- Max size: configurable (e.g., 5MB)
|
||||
- Progress indicator during upload
|
||||
- Success: asset appears in list
|
||||
|
||||
**Note:** Asset upload with webp conversion is available from Phase 1. The asset library is fully functional from day one — no manual URL phase.
|
||||
|
||||
### Team (`/admin/team`) — Phase 5+
|
||||
|
||||
**Purpose:** Manage admins and editors.
|
||||
|
||||
**List view:**
|
||||
- Table: user avatar, username, role, actions (change role, remove)
|
||||
|
||||
**Add member:**
|
||||
- Input for Discord username or ID
|
||||
- Role dropdown
|
||||
- "Add" button
|
||||
|
||||
**Behavior:**
|
||||
- Owner cannot be removed or demoted
|
||||
- Owner can promote/demote/remove admins and editors
|
||||
- Changes take effect immediately
|
||||
|
||||
---
|
||||
|
||||
## Error States & Edge Cases
|
||||
|
||||
| Situation | Behavior |
|
||||
|-----------|----------|
|
||||
| Save fails (network error) | Show error toast, keep form data intact |
|
||||
| Save fails (validation) | Highlight invalid fields, show specific messages |
|
||||
| Session expires while editing | Redirect to login on next action, preserve intended destination |
|
||||
| Concurrent editing (two admins) | Last write wins in V1 (no conflict detection) |
|
||||
| Loading state | Skeleton/spinner while data loads |
|
||||
| Empty state | "No events yet. Create your first event!" with action button |
|
||||
| CDN unreachable | Admin still works; image uploads fail with clear error |
|
||||
|
||||
---
|
||||
|
||||
## What to Avoid
|
||||
|
||||
- **Multi-step wizards.** Single-page forms are simpler.
|
||||
- **Inline editing everywhere.** Form pages with clear save buttons are more predictable.
|
||||
- **Real-time preview in V1.** A "preview" link to the public site is sufficient.
|
||||
- **Over-designed dashboards.** The admin panel is a tool, not a product demo.
|
||||
- **Custom permission UIs in V1.** Owner + super admin access is sufficient until Phase 5.
|
||||
@@ -0,0 +1,202 @@
|
||||
# Public Site UX Planning Document
|
||||
|
||||
## Design Principles
|
||||
|
||||
- **Simple landing page, not a full website.** The public site is a single page (with maybe an event detail modal or page). It tells visitors who the community is, what they do, when they meet, and how to join.
|
||||
- **Content-driven by settings.** Everything on the page comes from the database (site settings, events, links). No hardcoded content.
|
||||
- **Theme-aware.** The page renders with the site's branding settings: logo, colors, background image.
|
||||
- **Fast and accessible.** Server-side rendered, minimal client JS, semantic HTML.
|
||||
- **Mobile-responsive.** Many visitors will check on their phones.
|
||||
|
||||
---
|
||||
|
||||
## Homepage Layout
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ NAV BAR │
|
||||
│ [Logo] Site Name [Link1] [Link2] [Link3] │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ HERO SECTION │
|
||||
│ [Background Image Optional] │
|
||||
│ │
|
||||
│ Site Name (large heading) │
|
||||
│ Tagline / Subtitle │
|
||||
│ [Primary CTA Button] │
|
||||
│ │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ABOUT / INTRO SECTION │
|
||||
│ │
|
||||
│ About text (from settings) │
|
||||
│ │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ NEXT EVENT SECTION │
|
||||
│ (if showNextEvent is enabled) │
|
||||
│ │
|
||||
│ "Next Event" heading │
|
||||
│ Event card with: │
|
||||
│ - Title │
|
||||
│ - Date/Time │
|
||||
│ - Description snippet │
|
||||
│ - [Event Link / Details] │
|
||||
│ │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ UPCOMING SCHEDULE SECTION │
|
||||
│ (if showSchedule is enabled) │
|
||||
│ │
|
||||
│ "Upcoming Events" heading │
|
||||
│ List of upcoming events: │
|
||||
│ - Date | Title | Type │
|
||||
│ - Each links to event or external │
|
||||
│ │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ SOCIAL LINKS SECTION │
|
||||
│ │
|
||||
│ [Discord] [Twitter] [YouTube] ... │
|
||||
│ Icon + label, opens in new tab │
|
||||
│ │
|
||||
├─────────────────────────────────────────────┤
|
||||
│ FOOTER │
|
||||
│ Footer nav links │
|
||||
│ "Powered by The Collective Hub" │
|
||||
│ Copyright / site name │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Section Details
|
||||
|
||||
### Nav Bar
|
||||
|
||||
- **Position:** Sticky top (optional, can be static)
|
||||
- **Content:**
|
||||
- Site logo (or site name text if no logo)
|
||||
- Site name (hidden if logo is present and preferred)
|
||||
- Nav links from database (header position), ordered by `sortOrder`
|
||||
- **Mobile:** Hamburger menu collapses nav links into a drawer or dropdown
|
||||
- **Behavior:** External links open in new tab with `rel="noopener noreferrer"`
|
||||
|
||||
### Hero Section
|
||||
|
||||
- **Background:** Site background image (if set) with overlay/gradient for text readability. Falls back to background color.
|
||||
- **Content:**
|
||||
- Site name (large heading, `h1`)
|
||||
- Tagline/subtitle (`p` or `h2`)
|
||||
- Primary CTA button (if button text and link are set)
|
||||
- **Button styling:** Uses accent color. Links to Discord invite, event page, or any URL set by admin.
|
||||
- **If no hero content is set:** Section collapses or shows a minimal version with just the site name.
|
||||
|
||||
### About / Intro Section
|
||||
|
||||
- **Content:** About text from settings. Plain text or basic Markdown rendered to HTML.
|
||||
- **If empty:** Section is hidden entirely.
|
||||
- **Styling:** Clean typography, max-width for readability (~65ch).
|
||||
|
||||
### Next Event Section
|
||||
|
||||
- **Visibility:** Only shown if `showNextEvent` is enabled AND at least one published event exists with a future `startTime`.
|
||||
- **Content:** A single event card showing the soonest upcoming event.
|
||||
- Event title
|
||||
- Date and time (displayed in visitor's local timezone via client-side JS)
|
||||
- Short description (truncated)
|
||||
- Event type badge/chip
|
||||
- Location (if set)
|
||||
- Link: "Event Details" → external link or internal event page
|
||||
- **If no upcoming events:** Optionally show "No upcoming events — check back soon!" or hide section.
|
||||
|
||||
### Upcoming Schedule Section
|
||||
|
||||
- **Visibility:** Only shown if `showSchedule` is enabled.
|
||||
- **Content:** List of upcoming published events (excluding the one shown in "Next Event" if duplicate).
|
||||
- **List format:**
|
||||
- Date (short format)
|
||||
- Event title
|
||||
- Event type icon or badge
|
||||
- Optional: time, location
|
||||
- **Max items:** Configurable, e.g., show next 5 events with a "View all events" link if more exist.
|
||||
- **If no events:** Hide the section.
|
||||
|
||||
### Social Links Section
|
||||
|
||||
- **Visibility:** Shown if any social links exist in the database.
|
||||
- **Content:** Row of icon+label links for each social platform.
|
||||
- **Icons:** Simple SVG icons or icon font. Recognizable platform icons (Discord, Twitter/X, YouTube, Twitch, GitHub, etc.).
|
||||
- **Behavior:** All open in new tab.
|
||||
|
||||
### Footer
|
||||
|
||||
- **Content:**
|
||||
- Footer-position nav links (if any)
|
||||
- Optional: "Powered by The Collective Hub" credit
|
||||
- Site name / copyright
|
||||
- **Styling:** Subtle, smaller text, subdued colors.
|
||||
|
||||
---
|
||||
|
||||
## Theme Rendering
|
||||
|
||||
The site's theme settings are applied via CSS custom properties on the root element:
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-accent: #e63946;
|
||||
--color-background: #1a1a2e;
|
||||
--color-text: #eaeaea;
|
||||
--color-text-secondary: #b0b0b0;
|
||||
--font-family: 'Inter', sans-serif;
|
||||
/* derived values generated from presets if needed */
|
||||
}
|
||||
```
|
||||
|
||||
**Theme Presets:**
|
||||
- **Dark:** Dark background, light text, accent color applied
|
||||
- **Light:** Light background, dark text, accent color applied
|
||||
- **Custom:** Owner sets each color manually
|
||||
|
||||
Presets provide sensible defaults for derived colors (card backgrounds, borders, muted text) so the owner only needs to pick 3 colors.
|
||||
|
||||
---
|
||||
|
||||
## States
|
||||
|
||||
| State | Behavior |
|
||||
|-------|----------|
|
||||
| **Loading** | Server-rendered, so no loading spinner on initial load. Fast. |
|
||||
| **Empty site (no settings)** | Show site name from `sites` table. Everything else gracefully hidden. |
|
||||
| **No events** | Hide event sections. |
|
||||
| **No branding set** | Use neutral default colors (dark theme as fallback). |
|
||||
| **Error (data fetch fails)** | Show a minimal page with site name. Log error server-side. Don't crash. |
|
||||
| **Site deactivated** (`isActive=false`) | Show a simple "Site is currently unavailable" page with HTTP 503. |
|
||||
|
||||
---
|
||||
|
||||
## Responsive Behavior
|
||||
|
||||
- **Desktop (≥1024px):** Full layout as designed. Multi-column where appropriate.
|
||||
- **Tablet (768-1023px):** Same layout, adjusted spacing. Nav may collapse.
|
||||
- **Mobile (<768px):** Single column. Hamburger nav. Stacked sections. Larger touch targets for buttons.
|
||||
|
||||
---
|
||||
|
||||
## Performance Targets
|
||||
|
||||
- Server-rendered HTML (SSR) — no client-side rendering for public pages
|
||||
- Minimal JavaScript — only for timezone conversion, mobile nav toggle
|
||||
- Images from CDN with proper `width`/`height` and `loading="lazy"` on below-fold images
|
||||
- No client-side data fetching for public pages (all data loaded server-side)
|
||||
|
||||
---
|
||||
|
||||
## What to Avoid
|
||||
|
||||
- **Animation-heavy designs.** Subtle transitions are fine; scroll-triggered animations are not needed.
|
||||
- **Over-complicated layouts.** One column of stacked sections works well and is easy to maintain.
|
||||
- **Custom fonts that hurt performance.** System font stack or a single web font (Inter) is sufficient.
|
||||
- **Client-side routing for public pages.** The homepage is one page. If event detail pages are added later, they should be server-rendered too.
|
||||
- **Assuming content exists.** Every section must handle the "nothing configured yet" case gracefully.
|
||||
@@ -0,0 +1,260 @@
|
||||
# Development Implementation Plan
|
||||
|
||||
## How to Use This
|
||||
|
||||
This is a step-by-step build order for Phase 1 and beyond. Each step lists what to build, what it depends on, and how to verify it works.
|
||||
|
||||
**Follow the order.** Each step builds on the previous one. Don't skip ahead.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Foundation
|
||||
|
||||
### Step 1: Initialize SvelteKit Project
|
||||
|
||||
**What to do:**
|
||||
- Create a new SvelteKit project with `create-svelte` (choose TypeScript, ESLint, Prettier)
|
||||
- Set up the directory structure as outlined in the architecture plan
|
||||
- Configure `svelte.config.js` with the Node adapter for production builds
|
||||
- Create a basic `+page.svelte` that says "Hello World"
|
||||
- Create a `Dockerfile` for production builds
|
||||
|
||||
**Depends on:** Nothing.
|
||||
|
||||
**Verify:** `npm run dev` starts. Browser shows "Hello World". `docker build` succeeds.
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Set Up Postgres and Drizzle
|
||||
|
||||
**What to do:**
|
||||
- Install `drizzle-orm`, `drizzle-kit`, and `postgres` (the npm package)
|
||||
- Create `drizzle.config.ts`
|
||||
- Create `src/lib/server/db/index.ts` with the Postgres connection
|
||||
- Create `src/lib/server/db/schema.ts` with the `sites` table only (start simple)
|
||||
- Run `drizzle-kit push` to create the table in Postgres
|
||||
- Insert a test site row manually: `INSERT INTO sites (slug, name) VALUES ('test-site', 'Test Site');`
|
||||
|
||||
**Depends on:** Step 1. A running Postgres instance (local Docker or remote).
|
||||
|
||||
**Verify:** `drizzle-kit studio` shows the table. A simple script can query the test site.
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Create Core Tables
|
||||
|
||||
**What to do:**
|
||||
- Add all Phase 1 tables to `schema.ts`: `sites`, `users`, `memberships`, `siteSettings`
|
||||
- Define types, enums, indexes, and foreign keys
|
||||
- Run `drizzle-kit push` to create all tables
|
||||
- Optionally create a seed script for a test site
|
||||
|
||||
**Depends on:** Step 2.
|
||||
|
||||
**Verify:** All tables exist in the database. Relationships are correct in Drizzle Studio.
|
||||
|
||||
---
|
||||
|
||||
### Step 4: Implement Site Resolver
|
||||
|
||||
**What to do:**
|
||||
- Create `src/lib/server/site-resolver.ts`
|
||||
- Export a function `getSiteBySlug(slug: string)` that queries the `sites` table and includes `siteSettings`
|
||||
- In `src/hooks.server.ts`, read `SITE_SLUG` from env, call the resolver, attach site to `locals`
|
||||
- Augment `app.d.ts` so `locals.site` is typed
|
||||
- In `src/routes/+layout.server.ts`, load site data from locals and return it
|
||||
- The homepage `+page.svelte` should display the site name
|
||||
|
||||
**Depends on:** Step 3.
|
||||
|
||||
**Verify:** Set `SITE_SLUG=test-site` in `.env`. Homepage shows "Test Site". Change the slug, restart, page breaks cleanly.
|
||||
|
||||
---
|
||||
|
||||
### Step 5: Set Up Better Auth with Discord
|
||||
|
||||
**What to do:**
|
||||
- Install Better Auth and follow its SvelteKit setup guide
|
||||
- Configure Discord OAuth provider
|
||||
- Create `src/lib/server/auth.ts` with the Better Auth configuration
|
||||
- Add the Better Auth API route: `src/routes/api/auth/[...betterAuth]/+server.ts`
|
||||
- Create a `/login` page with a "Login with Discord" button
|
||||
- On successful login, upsert the user into the `users` table
|
||||
|
||||
**Depends on:** Step 3 (users table must exist).
|
||||
|
||||
**Verify:** Visit `/login`, click the Discord button, authorize, get redirected back. User record appears in the `users` table.
|
||||
|
||||
---
|
||||
|
||||
### Step 6: Implement Owner Bootstrap
|
||||
|
||||
**What to do:**
|
||||
- In the auth callback or post-login hook, check if `user.discordId === process.env.OWNER_DISCORD_ID`
|
||||
- If match: upsert a membership row with role `owner` for the current site
|
||||
- In `src/hooks.server.ts`, after auth, load the user's membership for the current site and attach to `locals`
|
||||
- Create an admin auth guard: a `+layout.server.ts` in `/admin` that checks `locals.membership`
|
||||
|
||||
**Depends on:** Step 4 (site resolver), Step 5 (auth).
|
||||
|
||||
**Verify:** Log in with the Discord account matching `OWNER_DISCORD_ID`. Membership row with `owner` role appears. Navigate to `/admin` — accessible. Log in with a different Discord account — `/admin` redirects to `/login` with an error message.
|
||||
|
||||
---
|
||||
|
||||
### Step 7: Build Admin Layout
|
||||
|
||||
**What to do:**
|
||||
- Create `src/routes/admin/+layout.svelte` with sidebar navigation and top bar
|
||||
- Create `src/routes/admin/+layout.server.ts` with the auth guard
|
||||
- Create a minimal `src/routes/admin/+page.svelte` dashboard
|
||||
|
||||
**Depends on:** Step 6.
|
||||
|
||||
**Verify:** Owner logs in, sees admin layout with nav sidebar. Non-owner cannot access.
|
||||
|
||||
---
|
||||
|
||||
### Step 8: Build Admin Settings Page
|
||||
|
||||
**What to do:**
|
||||
- Create `src/routes/admin/settings/+page.svelte`
|
||||
- Form fields: site name, tagline
|
||||
- Load current values from `siteSettings.settings` JSON
|
||||
- Create a form action (or API endpoint) that updates the JSON
|
||||
- Add basic form validation and success/error feedback
|
||||
|
||||
**Depends on:** Step 7.
|
||||
|
||||
**Verify:** Owner can edit site name and tagline. Changes persist after reload. Public homepage reflects changes.
|
||||
|
||||
---
|
||||
|
||||
### Step 9: Build Public Homepage
|
||||
|
||||
**What to do:**
|
||||
- Update `src/routes/+page.server.ts` to load site settings as a flat object
|
||||
- Build `src/routes/+page.svelte` with sections:
|
||||
- Hero (site name, tagline, CTA button if configured)
|
||||
- About (text from settings if configured)
|
||||
- Apply basic CSS styling with CSS custom properties (hardcode dark theme defaults for now)
|
||||
- Handle empty states: sections hide when no content configured
|
||||
|
||||
**Depends on:** Step 4 (site resolver), Step 8 (settings exist).
|
||||
|
||||
**Verify:** Public homepage shows site name and content. Changing settings in admin updates the public page.
|
||||
|
||||
---
|
||||
|
||||
### Step 10: Add Theme CSS Variables
|
||||
|
||||
**What to do:**
|
||||
- In the root layout, generate CSS custom properties from theme settings
|
||||
- Fall back to sensible defaults if no theme configured
|
||||
- Apply variables to the public homepage
|
||||
- Admin panel can use a fixed theme (don't need the public theme in admin)
|
||||
|
||||
**Depends on:** Step 9.
|
||||
|
||||
**Verify:** Changing accent color in admin (once branding page is built) changes the public page's button color. Default theme looks clean.
|
||||
|
||||
---
|
||||
|
||||
### Step 11: Set Up CDN and Asset Upload
|
||||
|
||||
**What to do:**
|
||||
- Configure CDN storage client (Bunny CDN or S3-compatible)
|
||||
- Create `src/lib/server/cdn.ts` with upload, delete, and URL construction helpers
|
||||
- Create an image upload API endpoint: `src/routes/api/assets/+server.ts`
|
||||
- Implement webp conversion and optimization (using `sharp` or similar)
|
||||
- File validation: accepted types (PNG, JPEG, WebP input), max size
|
||||
- Auto-generate CDN keys: `sites/{siteSlug}/{type}/{uuid}.webp`
|
||||
- Create asset records in the `assets` table on successful upload
|
||||
- Create asset library page: `src/routes/admin/assets/+page.svelte`
|
||||
|
||||
**Depends on:** Step 4 (site resolver for siteSlug), Step 7 (admin layout).
|
||||
|
||||
**Verify:** Upload an image via admin. Asset record appears in database. File exists in CDN bucket. Asset library page shows uploaded files. Image is served correctly via CDN URL.
|
||||
|
||||
---
|
||||
|
||||
### Step 12: Set Up Migration Automation
|
||||
|
||||
**What to do:**
|
||||
- Add `RUN_MIGRATIONS` env var check in app startup
|
||||
- If `RUN_MIGRATIONS=true`, run `drizzle-kit migrate` on startup
|
||||
- If `RUN_MIGRATIONS=false` (or unset), skip migrations entirely
|
||||
- Log migration status on startup for observability
|
||||
- Document which deployment is the migration runner
|
||||
|
||||
**Depends on:** Step 2 (Drizzle configured).
|
||||
|
||||
**Verify:** Start app with `RUN_MIGRATIONS=true` — migrations run. Start with `RUN_MIGRATIONS=false` — migrations are skipped. Both deployments work against the same database.
|
||||
|
||||
---
|
||||
|
||||
### Step 13: Implement Super Admin Access
|
||||
|
||||
**What to do:**
|
||||
- Parse `SUPER_ADMIN_DISCORD_IDS` env var (comma-separated) on startup
|
||||
- In the auth hook / membership check, compare user's Discord ID against the super admin list
|
||||
- If match: bypass site-scoped membership checks, grant full admin access
|
||||
- Attach super admin flag to `locals` for conditional UI (e.g., "View All Sites" link)
|
||||
|
||||
**Depends on:** Step 6 (owner bootstrap / membership logic).
|
||||
|
||||
**Verify:** Log in with a Discord ID in `SUPER_ADMIN_DISCORD_IDS`. Access any site's admin panel. Log in with a non-super-admin ID — restricted to their own site.
|
||||
|
||||
---
|
||||
|
||||
### Step 14: Admin Branding Page
|
||||
|
||||
**What to do:**
|
||||
- Create `src/routes/admin/branding/+page.svelte`
|
||||
- Color pickers for accent, background, text colors
|
||||
- Theme preset dropdown (Dark, Light, Custom)
|
||||
- Logo and background selectors: pick from asset library (uploaded in Step 11)
|
||||
|
||||
**Depends on:** Step 8 (settings save pattern), Step 11 (asset library).
|
||||
|
||||
**Verify:** Owner can change colors. Public page reflects changes immediately. Logo and background can be selected from uploaded assets.
|
||||
|
||||
---
|
||||
|
||||
### Step 15: Dockerize and Deploy
|
||||
|
||||
**What to do:**
|
||||
- Finalize Dockerfile (multi-stage build for Node)
|
||||
- Create `docker-compose.yml` for local testing with Postgres
|
||||
- Set up first Coolify deployment (designate as migration runner: `RUN_MIGRATIONS=true`)
|
||||
- Configure all environment variables in Coolify
|
||||
- Deploy and verify public site is accessible
|
||||
|
||||
**Depends on:** Step 9 (working public site), Step 12 (migration automation).
|
||||
|
||||
**Verify:** Site is live at the configured URL. Login works. Admin works. Migrations ran on startup.
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 Onward
|
||||
|
||||
Once Phase 1 is fully working, continue with:
|
||||
|
||||
1. Nav links + social links admin pages and public rendering
|
||||
2. Homepage content editor (hero title, subtitle, about text, CTA)
|
||||
3. Events: schema, admin CRUD, public render
|
||||
4. Super admin dashboard (Phase 4)
|
||||
5. Role management (Phase 5)
|
||||
|
||||
Detailed steps for Phases 2-5 should be written once Phase 1 is complete and any lessons learned are incorporated.
|
||||
|
||||
---
|
||||
|
||||
## Development Rules
|
||||
|
||||
- **One migration per schema change.** Don't batch unrelated changes into one migration.
|
||||
- **Test with multiple SITE_SLUG values locally.** Use different `.env` files or a script that switches them.
|
||||
- **Commit often.** Small, focused commits are easier to reason about.
|
||||
- **Migrations run automatically on startup, gated by `RUN_MIGRATIONS`.** Only one deployment runs them. All others skip.
|
||||
- **Keep the public site SSR-only.** No client-side data fetching for public pages.
|
||||
- **Admin pages can use client-side interactivity.** Forms, file uploads, etc. can use Svelte's client-side features.
|
||||
- **All uploaded images are converted to webp.** No raw user files stored on CDN.
|
||||
@@ -0,0 +1,87 @@
|
||||
# Decision Register — The Collective Hub
|
||||
|
||||
All key architectural and product decisions made during planning. This document serves as the authoritative record of what was decided and why.
|
||||
|
||||
---
|
||||
|
||||
## Auth & Discord
|
||||
|
||||
| # | Decision | Rationale |
|
||||
|---|----------|-----------|
|
||||
| Q1 | **One shared Discord OAuth app** for all sites in V1 | Simpler to manage. Works for up to ~10 sites before Discord's redirect URL limit becomes an issue. Each site's callback URL is added to the Discord app's redirect list. Switch to per-site apps later if needed. |
|
||||
| Q2 | **Defer central auth domain** | Not needed for V1. Architecture supports adding it later. |
|
||||
|
||||
## Sites & Domains
|
||||
|
||||
| # | Decision | Rationale |
|
||||
|---|----------|-----------|
|
||||
| Q3 | **Support both custom domains and subdomains** | The app doesn't care what the URL is — it uses `PUBLIC_SITE_URL` from env vars. DNS and Coolify routing are manual per site. Each site runs in its own Coolify container. |
|
||||
| Q4 | **No Host header validation in V1** | Each site is in its own container. Trust the `SITE_SLUG` env var. Add Host validation if moving to single-deployment multi-domain later. |
|
||||
|
||||
## Roles & Permissions
|
||||
|
||||
| # | Decision | Rationale |
|
||||
|---|----------|-----------|
|
||||
| Q5 | **Defer admin invites to Phase 5** | V1 has one owner per site bootstrapped via `OWNER_DISCORD_ID`. David has cross-site access via `SUPER_ADMIN_DISCORD_IDS`. The `memberships` table supports multiple members from day one — just no UI for it yet. |
|
||||
| Q6 | **Multi-site membership with different roles** | Already baked into the schema. A user can be owner of one site and editor of another. No special handling needed. |
|
||||
|
||||
## Super Admin
|
||||
|
||||
| # | Decision | Rationale |
|
||||
|---|----------|-----------|
|
||||
| — | **`SUPER_ADMIN_DISCORD_IDS` env var** for cross-site super admin access | Comma-separated Discord user IDs. David (system maintainer) can access any site's admin panel. These IDs bypass site-scoped membership checks. A dedicated super admin dashboard is planned for Phase 4. |
|
||||
|
||||
## Content & Customization
|
||||
|
||||
| # | Decision | Rationale |
|
||||
|---|----------|-----------|
|
||||
| Q7 | **Single `jsonb` column for theme/site settings** | Simpler than separate columns or key-value tables. No migrations needed when adding new settings. Settings are always loaded as a batch — no need to query individual settings in SQL. |
|
||||
| Q8 | **Fixed homepage fields for V1** | Hero title, about text, CTA button, etc. stored in settings JSON. Covers 90% of what theater sites need. A flexible `homepageSections` table is defined in the database plan as a future upgrade. |
|
||||
| Q9 | **Basic Markdown for long text fields** | About text and event descriptions support headings, bold, italic, links, lists. No raw HTML passthrough for safety. Short fields (hero title, button text) are plain text only. |
|
||||
| Q10 | **Customization checklist confirmed as drafted** | Name/tagline/logo/colors/hero/CTA/nav/social/theme presets in V1. No custom CSS, no extra layout presets, no custom fonts, no custom pages beyond homepage. |
|
||||
|
||||
### V1 Customization Scope (Q10 Detail)
|
||||
|
||||
| Feature | V1? | Phase |
|
||||
|---------|-----|-------|
|
||||
| Site name, tagline | ✅ Yes | Phase 1 |
|
||||
| Logo, background image | ✅ Yes | Phase 2 (from asset library) |
|
||||
| Accent/background/text colors | ✅ Yes | Phase 2 |
|
||||
| Hero title, subtitle, about text | ✅ Yes | Phase 2 |
|
||||
| CTA button text and link | ✅ Yes | Phase 2 |
|
||||
| Nav links | ✅ Yes | Phase 2 |
|
||||
| Social links | ✅ Yes | Phase 2 |
|
||||
| Theme presets (dark/light) | ✅ Yes | Phase 2 |
|
||||
| Custom CSS | ❌ No | Future |
|
||||
| Multiple layout presets | ❌ No | One flexible layout |
|
||||
| Custom fonts | ❌ No | System stack + Inter |
|
||||
| Per-page customization | ❌ No | Homepage only |
|
||||
| Custom pages beyond homepage | ❌ No | Future |
|
||||
|
||||
## Events
|
||||
|
||||
| # | Decision | Rationale |
|
||||
|---|----------|-----------|
|
||||
| Q11 | **No recurring events in V1** | V1 events are one-off. The `isRecurring` boolean is a placeholder. Recurring events add significant complexity (RRULE parsing, occurrence generation, timezone math). |
|
||||
| Q12 | **UTC storage + client-side timezone conversion** | All event times stored as `timestamptz` in UTC. Event's intended timezone stored as a string. Public site converts to visitor's local time using `Intl.DateTimeFormat`. |
|
||||
|
||||
## Assets & CDN
|
||||
|
||||
| # | Decision | Rationale |
|
||||
|---|----------|-----------|
|
||||
| Q13 | **Full upload flow from day one** | No manual URL pasting. Admin uploads images through the app. Assets table tracks all files. CDN integration is Phase 1, not deferred. |
|
||||
| Q14 | **Auto webp conversion and optimization on upload** | All uploaded images are converted to webp and optimized before storage. Uses `sharp` or similar for processing. Consistent format, smaller files, better performance. |
|
||||
|
||||
## Database & Operations
|
||||
|
||||
| # | Decision | Rationale |
|
||||
|---|----------|-----------|
|
||||
| Q15 | **Automated migrations, gated by `RUN_MIGRATIONS` env var** | Exactly one deployment (the "primary") has `RUN_MIGRATIONS=true` and runs migrations on startup. All others skip. This avoids migration collisions while eliminating manual steps. |
|
||||
| Q16 | **Backups handled externally by David** | Not a code concern. David manages Postgres backups separately. |
|
||||
| — | **Shared database with `siteId` scoping** | Confirmed after discussion. One Postgres database, all tables scoped by `siteId`. Simpler than per-site tables/schemas/databases. Enables super admin cross-site queries. |
|
||||
|
||||
## Project Identity
|
||||
|
||||
| # | Decision | Rationale |
|
||||
|---|----------|-----------|
|
||||
| Q17 | **Project name: The Collective Hub** | Chosen by David. Used for repo name, package name, documentation references, CDN bucket name, database name, and public references (e.g., Discord OAuth app name). |
|
||||
@@ -0,0 +1,152 @@
|
||||
# Risks & Things to Avoid
|
||||
|
||||
## Critical Risks
|
||||
|
||||
### Risk 1: Multiple Deployments Running Migrations Simultaneously
|
||||
|
||||
**Severity:** High — could corrupt the database.
|
||||
|
||||
**Why it's a risk:** With multiple Coolify deployments all pointing to the same database, if every deployment runs migrations on startup, they could conflict — two containers trying to create the same table at the same time.
|
||||
|
||||
**Mitigation:**
|
||||
- Migrations run automatically on startup, but gated by `RUN_MIGRATIONS` env var
|
||||
- **Exactly one deployment** has `RUN_MIGRATIONS=true` (the "primary" deployment)
|
||||
- All other deployments set `RUN_MIGRATIONS=false` and skip migrations
|
||||
- Deploy the primary first when schema changes are included
|
||||
- This is enforced by convention, not by a lock — David must ensure only one deployment has the flag set to `true`
|
||||
|
||||
### Risk 2: Missing siteId Scope on Queries
|
||||
|
||||
**Severity:** High — data leaks between sites.
|
||||
|
||||
**Why it's a risk:** If a query forgets to filter by `siteId`, one site could display another site's events, settings, or assets. This is the most common multi-tenant bug.
|
||||
|
||||
**Mitigation:**
|
||||
- All data access functions accept `siteId` as a required parameter
|
||||
- Create a helper that wraps Drizzle queries and enforces `siteId`
|
||||
- Review every query in code review for `siteId` filtering
|
||||
- Consider a lint rule or type-level enforcement (e.g., branded types) later
|
||||
|
||||
### Risk 3: Hardcoding Full CDN URLs
|
||||
|
||||
**Severity:** Medium — painful CDN migration if the CDN provider changes.
|
||||
|
||||
**Why it's a risk:** If the database stores `https://cdn.example.com/sites/bad-movies/logo.webp` and you later switch CDN providers, every URL in the database needs updating.
|
||||
|
||||
**Mitigation:**
|
||||
- Database stores only the CDN key/path (`sites/bad-movies-theater/logo.webp`)
|
||||
- Application constructs full URLs using `CDN_BASE_URL` env var
|
||||
- A single env var change switches all CDN URLs
|
||||
|
||||
### Risk 4: Overbuilding Before the Core Works
|
||||
|
||||
**Severity:** Medium — wasted effort, complexity without value.
|
||||
|
||||
**Why it's a risk:** It's tempting to build the fancy admin dashboard, the AI features, the perfect theming system before the basic site actually works end-to-end. This leads to a complex codebase that doesn't ship.
|
||||
|
||||
**Mitigation:**
|
||||
- Follow the phases strictly
|
||||
- Phase 1 must be fully working (public site + admin login + settings save) before anything else
|
||||
- A working simple site is infinitely more valuable than a half-built complex one
|
||||
- Ask "Can this wait until Phase X?" before building anything
|
||||
|
||||
### Risk 5: Per-Site Custom Code
|
||||
|
||||
**Severity:** Medium — maintenance nightmare.
|
||||
|
||||
**Why it's a risk:** If "Bad Movies Theater" needs something special and you add an `if (site.slug === 'bad-movies-theater')` in the code, that's the start of a slippery slope. Soon every site has special cases, and the "shared codebase" advantage is lost.
|
||||
|
||||
**Mitigation:**
|
||||
- Never write site-specific conditional logic
|
||||
- All customization comes from the database (settings, theme, content)
|
||||
- If a site genuinely needs a unique feature, it should be built as a configurable feature for all sites, or that site should fork the codebase (last resort)
|
||||
|
||||
### Risk 6: Letting Site Owners Write Raw CSS/HTML
|
||||
|
||||
**Severity:** Medium — security and maintenance risk.
|
||||
|
||||
**Why it's a risk:** Allowing custom CSS or HTML opens XSS vectors (if not properly sanitized), breaks the design system, and makes future template updates unpredictable. A site owner could accidentally break their own site's layout.
|
||||
|
||||
**Mitigation:**
|
||||
- No custom CSS field in V1
|
||||
- No raw HTML in content fields — use Markdown with safe rendering
|
||||
- If custom CSS is ever added (future phase), sandbox it (e.g., a per-site stylesheet loaded separately, not injected into the main app)
|
||||
- Clearly document that custom CSS is an advanced/risky feature
|
||||
|
||||
---
|
||||
|
||||
## Design Pitfalls to Avoid
|
||||
|
||||
### Pitfall 1: Making the Admin Panel Too Complex Before the Public Page Works
|
||||
|
||||
The admin panel exists to serve the public page. If you spend weeks on a beautiful admin UI but the public site is a broken placeholder, priorities are wrong.
|
||||
|
||||
**Rule:** The public page must work before any admin page is considered complete.
|
||||
|
||||
### Pitfall 2: Building AI Features Before the Core Template Works
|
||||
|
||||
AI content suggestions, semantic search with pgvector, AI chatbots — these are exciting but useless if a site can't display a homepage with basic content.
|
||||
|
||||
**Rule:** No AI features until Phase 5+ and even then, only if the core template is stable and useful.
|
||||
|
||||
### Pitfall 3: Planning Too Many Layout Options
|
||||
|
||||
One clean, flexible layout that adapts to content is better than three half-baked layout options. Adding a second layout doubles the testing surface.
|
||||
|
||||
**Rule:** One layout in V1. Add a second only when there's a clear, proven need.
|
||||
|
||||
### Pitfall 4: Normalizing Settings Too Aggressively
|
||||
|
||||
A `siteSettings` table with 30 columns (one per setting) means a migration for every new setting. A `jsonb` column means adding a setting is zero-cost.
|
||||
|
||||
**Rule:** Settings go in JSON. Structured, relational data (events, links, assets) goes in normalized tables.
|
||||
|
||||
### Pitfall 5: Building for Scale That Doesn't Exist Yet
|
||||
|
||||
Planning for 1,000 sites when you have 3 leads to over-engineering. The architecture supports growth (multi-tenant from day one), but don't optimize for scale prematurely.
|
||||
|
||||
**Rule:** Architecture should not block growth; implementation should not optimize for it yet.
|
||||
|
||||
---
|
||||
|
||||
## Process Risks
|
||||
|
||||
### Risk 7: Skipping Documentation
|
||||
|
||||
**Severity:** Low now, high later.
|
||||
|
||||
**Why it's a risk:** When there's only one developer (David), documentation feels optional. But when you come back to the project after 6 months, or when a site owner asks how something works, missing documentation hurts.
|
||||
|
||||
**Mitigation:**
|
||||
- These planning docs live in the repo
|
||||
- Add a simple `README.md` with setup instructions
|
||||
- Add code comments for non-obvious logic
|
||||
- Keep a `CHANGELOG.md` once the project is live
|
||||
|
||||
### Risk 8: Super Admin Account Compromise
|
||||
|
||||
**Severity:** High — cross-site data breach.
|
||||
|
||||
**Why it's a risk:** A `SUPER_ADMIN_DISCORD_IDS` entry grants unrestricted access to all sites. If a super admin's Discord account is compromised, all sites are exposed.
|
||||
|
||||
**Mitigation:**
|
||||
- Keep the super admin list minimal (ideally just David)
|
||||
- Super admin Discord accounts should have 2FA enabled
|
||||
- Consider adding a secondary verification step for super admin actions in a future phase
|
||||
- Monitor for unusual super admin activity
|
||||
|
||||
---
|
||||
|
||||
## Summary Checklist
|
||||
|
||||
Before writing any code, confirm:
|
||||
|
||||
- [ ] Migrations are automated but gated by `RUN_MIGRATIONS` — only one deployment runs them
|
||||
- [ ] Every query includes `siteId` filtering
|
||||
- [ ] CDN keys stored in DB, not full URLs
|
||||
- [ ] Phase 1 scope is locked — no feature creep
|
||||
- [ ] No site-specific conditional code planned
|
||||
- [ ] No raw CSS/HTML inputs for site owners
|
||||
- [ ] Database backups are configured (handled externally by David)
|
||||
- [ ] Project name decided: **The Collective Hub**
|
||||
- [ ] Super admin Discord IDs are set and accounts have 2FA enabled
|
||||
Reference in New Issue
Block a user