BlogWikiAbout

Kyle Pericak

"It works in my environment"

Bot-Wiki/Design Docs/<Feature Name> — Design Doc

<Feature Name> — Design Doc

Context

Link to PRD: PRD title

One paragraph on the technical challenge this design addresses. Don't restate the PRD — reference it. Focus on what makes this technically interesting or risky.

Goals and Non-Goals

Carried from the PRD, restated in technical terms. Add any technical non-goals discovered during design.

Goals:

  • Technical goal derived from PRD goal

Non-Goals:

  • Technical non-goal (e.g., "No database migration in v1")

Proposed Design

Architecture overview. Include a Mermaid diagram showing component relationships and data flow.

graph TD
    A[Component A] --> B[Component B]
    B --> C[Component C]

Component Details

Subsections as needed for each significant component. Include:

  • Responsibility
  • File path where it lives
  • Key interfaces

Data Model

Schema, storage, access patterns. Only if applicable.

API / Interface Contracts

Inputs, outputs, error handling for key boundaries.

Alternatives Considered

One subsection per significant decision.

Decision:

Option Pros Cons Verdict
Option A Pro Con Chosen — reason
Option B Pro Con Rejected — reason

File Change List

Files to create, modify, or delete, each with a one-line rationale.

Action File Rationale
CREATE path/to/new-file.ts Reason
MODIFY path/to/existing.ts Reason
DELETE path/to/old-file.ts Reason

Task Breakdown

Dependency-ordered tasks. Each task is a single coherent change, testable in isolation. Mark parallelizable tasks with [P].

TASK-001: </h3> <ul> <li><strong>Requirement:</strong> PRD user story or acceptance criterion this addresses</li> <li><strong>Files:</strong> <code>path/to/file1.ts</code>, <code>path/to/file2.ts</code></li> <li><strong>Dependencies:</strong> None</li> <li><strong>Acceptance criteria:</strong> <ul class="contains-task-list"> <li class="task-list-item"><input type="checkbox" disabled> Specific, testable condition</li> <li class="task-list-item"><input type="checkbox" disabled> Specific, testable condition</li> </ul> </li> </ul> <h3 id="task-002-title-p">TASK-002: <title> <code>[P]</code></h3> <ul> <li><strong>Requirement:</strong> PRD user story or acceptance criterion</li> <li><strong>Files:</strong> <code>path/to/file3.ts</code></li> <li><strong>Dependencies:</strong> TASK-001</li> <li><strong>Acceptance criteria:</strong> <ul class="contains-task-list"> <li class="task-list-item"><input type="checkbox" disabled> Specific, testable condition</li> </ul> </li> </ul> <h2 id="implementation-additions">Implementation Additions</h2> <p>Scope drifts during implementation. That's expected. Document divergences here as they happen so the design doc stays accurate without a full rewrite. Each entry should state what changed and why the original design was wrong or incomplete.</p> <ul> <li><strong>Addition:</strong> What changed and why.</li> </ul> <h2 id="open-questions">Open Questions</h2> <p>Unresolved items. State what blocks on each.</p> <ul> <li><strong>Question:</strong> What blocks resolution?</li> </ul> <h2 id="risks">Risks</h2> <p>Technical risks and wrong assumptions.</p> <ul> <li><strong>Risk:</strong> Mitigation strategy or acceptance rationale.</li> </ul> </div><style data-emotion="css 15l33vf">.css-15l33vf{margin-top:30px;padding-top:15px;border-top:1px solid #eee;}</style><div class="MuiBox-root css-15l33vf"><style data-emotion="css 1wlk75r">.css-1wlk75r{margin:0;font-size:14px;color:#888888;margin-bottom:5px;}</style><span class="MuiTypography-root MuiTypography-blogPostGreySubtitle css-1wlk75r">Related:</span><style data-emotion="css 1424k1g">.css-1424k1g{-webkit-text-decoration:underline;text-decoration:underline;text-decoration-color:rgba(25, 118, 210, 0.4);display:block;-webkit-text-decoration:none;text-decoration:none;margin-bottom:3px;}.css-1424k1g:hover{text-decoration-color:inherit;}</style><style data-emotion="css 1f3lvd5">.css-1f3lvd5{margin:0;font:inherit;color:#1976d2;-webkit-text-decoration:underline;text-decoration:underline;text-decoration-color:rgba(25, 118, 210, 0.4);display:block;-webkit-text-decoration:none;text-decoration:none;margin-bottom:3px;}.css-1f3lvd5:hover{text-decoration-color:inherit;}</style><a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineAlways css-1f3lvd5" href="/wiki/prds/<slug>.html">wiki/prds/<slug></a><a class="MuiTypography-root MuiTypography-inherit MuiLink-root MuiLink-underlineAlways css-1f3lvd5" href="/<linear-issue-url>.html"><linear-issue-url></a></div></div></div></div><style data-emotion="css 1jv09ek">.css-1jv09ek{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;width:100%;height:50px;background-color:#EEEEEE;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:1px dotted #AAAAAA;padding:0 10px;}@media (min-width:0px){.css-1jv09ek{-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;padding-left:3%;padding-right:3%;}}@media (min-width:600px){.css-1jv09ek{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;padding-left:3%;padding-right:3%;}}@media (min-width:900px){.css-1jv09ek{padding-left:6%;padding-right:6%;}}@media (min-width:1200px){.css-1jv09ek{padding-left:9%;padding-right:9%;}}</style><div class="MuiBox-root css-1jv09ek"><style data-emotion="css 1wdrywq">.css-1wdrywq{margin:0;font-size:small;text-align:center;word-wrap:break-word;overflow-wrap:anywhere;}</style><span class="MuiTypography-root MuiTypography-footerText css-1wdrywq">Blog code last updated on <!-- -->2026-03-17<!-- -->:<a href="https://github.com/kylep/multi/commit/7ae9b0dec32c090b187b7ffa81b1559756cdad46"> <!-- -->7ae9b0dec32c090b187b7ffa81b1559756cdad46</a></span></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"route":["wiki","design-docs","template"],"markdownFiles":[],"categories":{"dev":13,"ai":11,"development":14,"cloud":22,"systems administration":17,"reference pages":5,"projects":5,"gaming":1,"guides":1},"tags":{"ai-agents":2,"sdlc":1,"product-management":1,"prd":1,"design-docs":1,"claude-code":14,"ai":15,"kubernetes":2,"agents":2,"automation":1,"go":1,"mcp":6,"cloudflare":2,"dns":2,"orchestration":1,"bot-wiki":3,"security":4,"hooks":1,"rag":2,"faiss":1,"openrouter":2,"embeddings":1,"python":12,"wiki":1,"knowledge-base":1,"opencode":3,"openclaw":4,"linear":3,"self-hosted":3,"vault":1,"telegram":1,"docker":11,"linting":1,"ruff":1,"biome":1,"hadolint":1,"tflint":1,"semgrep":1,"trivy":1,"gitleaks":1,"cursor":2,"llm":2,"dev":1,"ga4":1,"google-analytics":1,"next-js":1,"playwright":1,"testing":1,"gherkin":1,"codex":1,"monorepo":1,"ruler":1,"images":2,"comfyui":1,"apple-silicon":2,"sdxl":1,"ip-adapter":1,"ttrpg":1,"coderabbit":1,"code-review":1,"github":1,"llama-cpp":1,"qwen":1,"deepseek":1,"mistral":1,"openai":2,"flux":1,"nano-banana":1,"blog":1,"markdown":1,"mermaid":1,"diagram":1,"openstack":9,"https":3,"openssl":1,"mac-os":4,"ubuntu":9,"kvm":1,"http":1,"api":2,"tshark":1,"tcpdump":1,"nfs":1,"ceph":2,"git":2,"aws":11,"lambda":3,"codebuild":2,"windows":2,"powershell":1,"api-gateway":1,"firebase":2,"cicd":1,"codepipeline":1,"codecommit":1,"ec2":1,"node.js":1,"ansible":3,"gcp":7,"vim":2,"s3":1,"remote-access":2,"pure-storage":1,"bash":2,"pypi":1,"minecraft":1,"email":4,"wifi":2,"chrome":1,"ssh":1,"postfix":1,"ci/cd":1,"pelican":4},"currentPageIndexNumber":0,"pageCount":6,"postContent":{},"wikiContent":{"slug":"wiki/design-docs/template","title":"\u003cFeature Name\u003e — Design Doc","summary":"\u003cOne-liner technical approach\u003e","contentHtml":"\u003ch2 id=\"context\"\u003eContext\u003c/h2\u003e\n\u003cp\u003eLink to PRD: \u003ca href=\"../prds/%3Cslug%3E.html\"\u003ePRD title\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eOne paragraph on the technical challenge this design addresses. Don't\nrestate the PRD — reference it. Focus on what makes this technically\ninteresting or risky.\u003c/p\u003e\n\u003ch2 id=\"goals-and-non-goals\"\u003eGoals and Non-Goals\u003c/h2\u003e\n\u003cp\u003eCarried from the PRD, restated in technical terms. Add any technical\nnon-goals discovered during design.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eGoals:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eTechnical goal derived from PRD goal\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003eNon-Goals:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eTechnical non-goal (e.g., \"No database migration in v1\")\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"proposed-design\"\u003eProposed Design\u003c/h2\u003e\n\u003cp\u003eArchitecture overview. Include a Mermaid diagram showing component\nrelationships and data flow.\u003c/p\u003e\n\u003cpre class=\"mermaid\"\u003e\ngraph TD\n A[Component A] --\u003e B[Component B]\n B --\u003e C[Component C]\n\u003c/pre\u003e\n\u003ch3 id=\"component-details\"\u003eComponent Details\u003c/h3\u003e\n\u003cp\u003eSubsections as needed for each significant component. Include:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eResponsibility\u003c/li\u003e\n\u003cli\u003eFile path where it lives\u003c/li\u003e\n\u003cli\u003eKey interfaces\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"data-model\"\u003eData Model\u003c/h3\u003e\n\u003cp\u003eSchema, storage, access patterns. Only if applicable.\u003c/p\u003e\n\u003ch3 id=\"api--interface-contracts\"\u003eAPI / Interface Contracts\u003c/h3\u003e\n\u003cp\u003eInputs, outputs, error handling for key boundaries.\u003c/p\u003e\n\u003ch2 id=\"alternatives-considered\"\u003eAlternatives Considered\u003c/h2\u003e\n\u003cp\u003eOne subsection per significant decision.\u003c/p\u003e\n\u003ch3 id=\"decision-what-was-decided\"\u003eDecision: \u003cwhat was decided\u003e\u003c/h3\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eOption\u003c/th\u003e\n\u003cth\u003ePros\u003c/th\u003e\n\u003cth\u003eCons\u003c/th\u003e\n\u003cth\u003eVerdict\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eOption A\u003c/td\u003e\n\u003ctd\u003ePro\u003c/td\u003e\n\u003ctd\u003eCon\u003c/td\u003e\n\u003ctd\u003e\u003cstrong\u003eChosen\u003c/strong\u003e — reason\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eOption B\u003c/td\u003e\n\u003ctd\u003ePro\u003c/td\u003e\n\u003ctd\u003eCon\u003c/td\u003e\n\u003ctd\u003eRejected — reason\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"file-change-list\"\u003eFile Change List\u003c/h2\u003e\n\u003cp\u003eFiles to create, modify, or delete, each with a one-line rationale.\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eAction\u003c/th\u003e\n\u003cth\u003eFile\u003c/th\u003e\n\u003cth\u003eRationale\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eCREATE\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003epath/to/new-file.ts\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eReason\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eMODIFY\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003epath/to/existing.ts\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eReason\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003eDELETE\u003c/td\u003e\n\u003ctd\u003e\u003ccode\u003epath/to/old-file.ts\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eReason\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"task-breakdown\"\u003eTask Breakdown\u003c/h2\u003e\n\u003cp\u003eDependency-ordered tasks. Each task is a single coherent change,\ntestable in isolation. Mark parallelizable tasks with \u003ccode\u003e[P]\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"task-001-title\"\u003eTASK-001: \u003ctitle\u003e\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eRequirement:\u003c/strong\u003e PRD user story or acceptance criterion this addresses\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFiles:\u003c/strong\u003e \u003ccode\u003epath/to/file1.ts\u003c/code\u003e, \u003ccode\u003epath/to/file2.ts\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDependencies:\u003c/strong\u003e None\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAcceptance criteria:\u003c/strong\u003e\n\u003cul class=\"contains-task-list\"\u003e\n\u003cli class=\"task-list-item\"\u003e\u003cinput type=\"checkbox\" disabled\u003e Specific, testable condition\u003c/li\u003e\n\u003cli class=\"task-list-item\"\u003e\u003cinput type=\"checkbox\" disabled\u003e Specific, testable condition\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"task-002-title-p\"\u003eTASK-002: \u003ctitle\u003e \u003ccode\u003e[P]\u003c/code\u003e\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eRequirement:\u003c/strong\u003e PRD user story or acceptance criterion\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFiles:\u003c/strong\u003e \u003ccode\u003epath/to/file3.ts\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDependencies:\u003c/strong\u003e TASK-001\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAcceptance criteria:\u003c/strong\u003e\n\u003cul class=\"contains-task-list\"\u003e\n\u003cli class=\"task-list-item\"\u003e\u003cinput type=\"checkbox\" disabled\u003e Specific, testable condition\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"implementation-additions\"\u003eImplementation Additions\u003c/h2\u003e\n\u003cp\u003eScope drifts during implementation. That's expected. Document\ndivergences here as they happen so the design doc stays accurate\nwithout a full rewrite. Each entry should state what changed and\nwhy the original design was wrong or incomplete.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eAddition:\u003c/strong\u003e What changed and why.\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"open-questions\"\u003eOpen Questions\u003c/h2\u003e\n\u003cp\u003eUnresolved items. State what blocks on each.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eQuestion:\u003c/strong\u003e What blocks resolution?\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"risks\"\u003eRisks\u003c/h2\u003e\n\u003cp\u003eTechnical risks and wrong assumptions.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eRisk:\u003c/strong\u003e Mitigation strategy or acceptance rationale.\u003c/li\u003e\n\u003c/ul\u003e\n","metaData":{"title":"\u003cFeature Name\u003e — Design Doc","summary":"\u003cOne-liner technical approach\u003e","status":"draft | approved | in-progress | done","owner":"kyle","date":"YYYY-MM-DD","prd":"wiki/prds/\u003cslug\u003e","hidden":false,"related":["wiki/prds/\u003cslug\u003e","\u003clinear-issue-url\u003e"]},"breadcrumbs":[{"title":"Bot-Wiki","slug":"wiki"},{"title":"Design Docs","slug":"wiki/design-docs"},{"title":"\u003cFeature Name\u003e — Design Doc","slug":"wiki/design-docs/template"}],"childTreeHtml":"","children":[]},"lastGitCommitHash":"7ae9b0dec32c090b187b7ffa81b1559756cdad46","siteLastModified":"2026-03-17"},"__N_SSG":true},"page":"/[...route]","query":{"route":["wiki","design-docs","template"]},"buildId":"uocAgF0qPuNcHlPaI-0od","isFallback":false,"gsp":true,"scriptLoader":[]}</script></body></html>