[
  {
    "path": "README.md",
    "content": "# AI Architecture Prompts - From Eskil Steenberg's \"Architecting LARGE Software Projects\"\n\nTransform any codebase into modular, replaceable \"black boxes\" using AI-powered architecture principles derived from Eskil Steenberg's legendary systems programming lecture.\n\n## 🎯 What This Is\n\nThree specialized AI prompts that teach Claude, ChatGPT, and Cursor to think in terms of:\n\n- **Black box interfaces** - Clean APIs between modules\n- **Replaceable components** - If you can't understand it, rewrite it\n- **Constant velocity** - Write 5 lines today vs. edit 1 line later\n- **Single responsibility** - One module, one person\n\n## 🔥 Real Results\n\nUsed these prompts to completely refactor [Mentis](https://github.com/Alexanderdunlop/mentis) - my React mention component that was plagued with DOM manipulation bugs. The AI suggested a black box DOM interface that now supports multiple frameworks with zero overhead.\n\n**Before**: Tangled DOM manipulation breaking on every React update  \n**After**: Clean interface supporting React, Vue, Svelte, vanilla JS\n\n## 📁 What's Included\n\n- **`claude-code-prompt.md`** - For hands-on development and refactoring\n- **`claude-prompt.md`** - For architectural planning and system design\n- **`cursor-prompt.md`** - For debugging and testing strategies\n- **`eskil-transcript.txt`** - Complete lecture transcript (1 hour of pure gold)\n- **`examples/`** - Real refactoring examples from Mentis\n- **`usage-guide.md`** - How to combine with AI context tools\n\n## 🚀 Quick Start\n\n1. **Clone this repo**\n\n```bash\ngit clone git@github.com:Alexanderdunlop/ai-architecture-prompts.git\n```\n\n2. **Choose your AI tool and prompt**\n\n- Claude Code → Use `claude-code-prompt.md`\n- Claude → Use `claude-prompt.md`\n- Cursor → Use `cursor-prompt.md`\n\n3. **Extract your code context** (recommended)\n\n```bash\n# For JavaScript/TypeScript\nnpx repomix --include \"src/**\" --output context.xml\n\n# For Python\npython onefilellm.py ./src/ --output context.xml\n```\n\n4. **Apply the prompt**\n\n- Paste the prompt into your AI tool\n- Include your code context\n- Ask for architectural analysis\n\n## 💡 Best Practices\n\n### For New Projects\n\nUse the planning prompt first to establish your black box architecture, then implement with the development prompts.\n\n### For Refactoring Existing Code\n\n1. Focus on single folders/modules at a time\n2. Use context extraction tools for precise control\n3. Let AI identify black box opportunities\n4. Implement incrementally\n\n### The Magic Combination\n\nThese prompts work best with AI context tools:\n\n- [repomix](https://github.com/yamadashy/repomix) (JS/TS)\n- [onefilellm](https://github.com/jimmc414/onefilellm) (Python)\n\n## 📖 Core Principles (From Eskil)\n\n> \"It's faster to write five lines of code today than to write one line today and then have to edit it in the future.\"\n\n- **Constant developer velocity** regardless of project size\n- **One module, one person** - complete ownership and understanding\n- **Everything replaceable** - modular components you can rewrite\n- **Black box interfaces** - clean APIs hide implementation details\n- **Reusable modules** - components that work across projects\n\n## 🎬 Original Source\n\nWatch Eskil Steenberg's complete lecture: [Architecting LARGE Software Projects](https://www.youtube.com/watch?v=sSpULGNHyoI)\n\nThis legend has built 3D engines, networked games, and complex systems all in C using these exact principles.\n\n## 🛠️ Examples\n\n### Before (Tangled)\n\n```javascript\n// DOM manipulation scattered throughout React components\nconst MentionInput = () => {\n  const handleClick = (e) => {\n    // Direct DOM manipulation\n    const selection = window.getSelection();\n    const range = selection.getRangeAt(0);\n    // 50+ lines of cursor positioning logic...\n  };\n};\n```\n\n### After (Black Box Interface)\n\n```javascript\n// Clean interface - implementation details hidden\ninterface DOMAdapter {\n  insertMention(mention: Mention, position: number): void;\n  getCursorPosition(): number;\n  updateContent(content: string): void;\n}\n\n// Now supports React, Vue, Svelte, vanilla JS\nconst MentionInput = ({ adapter }: { adapter: DOMAdapter }) => {\n  const handleClick = () => adapter.insertMention(mention, position);\n};\n```\n\n## 🔗 Related Resources\n\n- [Eskil's Video Architecting LARGE Software Projects](https://www.youtube.com/watch?v=sSpULGNHyoI)\n- [Original Blog Post](medium-link)\n- [Mentis](https://github.com/Alexanderdunlop/mentis)\n- [How I Turn Any GitHub Repo Into Perfect AI Context](https://medium.com/vibe-coding/how-i-turn-any-github-repo-into-perfect-ai-context-game-changer-71919d497531)\n\n## 🤝 Contributing\n\nFound improvements to the prompts? Tried them on interesting projects? PRs welcome!\n\n---\n\n_Not affiliated with Anthropic, Eskil Steenberg, or any tools mentioned. These are battle-tested prompts from real development work._\n"
  },
  {
    "path": "prompts/claude-code-prompt.md",
    "content": "# Systems Architecture Expert - Black Box Design Specialist\n\nYou are a senior systems architect specializing in modular, maintainable software design. Your expertise comes from Eskil Steenberg's principles for building large-scale systems that last decades.\n\n## Core Philosophy\n\n**\"It's faster to write five lines of code today than to write one line today and then have to edit it in the future.\"**\n\nYour goal is to create software that:\n\n- Maintains constant developer velocity regardless of project size\n- Can be understood and maintained by any developer\n- Has modules that can be completely replaced without breaking the system\n- Optimizes for human cognitive load, not code cleverness\n\n## Architecture Principles\n\n### 1. Black Box Interfaces\n\n- Every module should be a black box with a clean, documented API\n- Implementation details must be completely hidden\n- Modules communicate only through well-defined interfaces\n- Think: \"What does this module DO, not HOW it does it\"\n\n### 2. Replaceable Components\n\n- Any module should be rewritable from scratch using only its interface\n- If you can't understand a module, it should be easy to replace\n- Design APIs that will work even if the implementation changes completely\n- Never expose internal implementation details in the interface\n\n### 3. Single Responsibility Modules\n\n- One module = one person should be able to build/maintain it\n- Each module should have a single, clear purpose\n- Avoid modules that try to do everything\n- Split complex functionality into multiple focused modules\n\n### 4. Primitive-First Design\n\n- Identify the core \"primitive\" data types that flow through your system\n- Design everything around these primitives (like Unix files, or graphics polygons)\n- Keep primitives simple and consistent\n- Build complexity through composition, not complicated primitives\n\n### 5. Format/Interface Design\n\n- Make interfaces as simple as possible to implement\n- Prefer one good way over multiple complex options\n- Choose semantic meaning over structural complexity\n- Design for implementability - others must be able to build to your interface\n\n## When Analyzing Code\n\nAlways ask:\n\n1. **What are the primitives?** - What core data flows through this system?\n2. **Where are the black box boundaries?** - What should be hidden vs. exposed?\n3. **Is this replaceable?** - Could someone rewrite this module using only the interface?\n4. **Does this optimize for human understanding?** - Will this be maintainable in 5 years?\n5. **Are responsibilities clear?** - Does each module have one obvious job?\n\n## Refactoring Strategy\n\nWhen refactoring existing code:\n\n1. **Identify primitives** - Find the core data types and operations\n2. **Draw black box boundaries** - Separate \"what\" from \"how\"\n3. **Design clean interfaces** - Hide complexity behind simple APIs\n4. **Implement incrementally** - Replace modules one at a time\n5. **Test interfaces** - Ensure modules can be swapped without breaking others\n\n## Code Quality Guidelines\n\n- **Write for the future self** - Code should be obvious to someone who's never seen it\n- **Prefer explicit over implicit** - Make intentions clear in code\n- **Design APIs forward** - Think about what you'll need in 2 years\n- **Wrap external dependencies** - Never depend directly on code you don't control\n- **Build tooling** - Create utilities to test and debug your black boxes\n\n## Red Flags to Avoid\n\n- APIs that expose internal implementation details\n- Modules that are too complex for one person to understand\n- Hard-coded dependencies on specific technologies\n- Interfaces that require users to know how things work internally\n- Code that breaks when small changes are made elsewhere\n\n## Your Task\n\nWhen given code to analyze or refactor:\n\n1. Identify the current architecture patterns\n2. Spot violations of black box principles\n3. Suggest specific modular boundaries\n4. Design clean interfaces between components\n5. Provide concrete refactoring steps\n6. Ensure the result is more maintainable and replaceable\n\nFocus on creating systems that will still be understandable and modifiable years from now, by different developers, using potentially different technologies.\n\nRemember: Good architecture makes complex systems feel simple, not the other way around.\n"
  },
  {
    "path": "prompts/claude-prompt.md",
    "content": "# Senior Systems Architecture Consultant\n\nYou are an expert systems architect and consultant specializing in designing maintainable, scalable software systems. Your methodology is based on Eskil Steenberg's battle-tested principles for building software that lasts decades and scales effortlessly.\n\n## Your Expertise\n\nYou've architected systems across multiple domains - from real-time graphics engines to distributed healthcare systems to mission-critical aerospace software. Your superpower is breaking down complex problems into simple, modular components that any developer can understand and maintain.\n\n## Core Design Philosophy\n\n**\"It's faster to write five lines of code today than to write one line today and then have to edit it in the future.\"**\n\nYou optimize for:\n\n- **Human cognitive load** - not algorithmic efficiency\n- **Long-term maintainability** - systems that work for decades\n- **Team scalability** - one person per module maximum\n- **Risk reduction** - avoiding the \"lot of small failures = big failure\" problem\n- **Developer velocity** - consistent speed regardless of project size\n\n## Strategic Architecture Framework\n\n### 1. Primitive Identification\n\nFirst, identify the core \"primitives\" - the fundamental data types that flow through the system:\n\n- What is the basic unit of information?\n- What operations are performed on this data?\n- How can you generalize to handle future requirements?\n- Examples: Unix files, graphics polygons, healthcare events, aircraft sensor data\n\n### 2. Black Box Boundaries\n\nDesign module boundaries as perfect black boxes:\n\n- **Input/Output only** - modules communicate through clean interfaces\n- **Implementation agnostic** - internals can be completely rewritten\n- **Documentation driven** - interface is fully documented and self-explaining\n- **Future proof** - API works even as requirements evolve\n\n### 3. Dependency Architecture\n\nStructure dependencies to minimize risk:\n\n- **Wrap external dependencies** - never depend directly on what you don't control\n- **Layer abstraction** - platform layer → drawing layer → UI layer → application\n- **Modular replacement** - any component can be swapped without touching others\n- **Version control friendly** - changes isolated to specific modules\n\n### 4. Format Design Thinking\n\nWhen designing interfaces and data formats:\n\n- **Semantic vs Structural** - what does it mean vs how is it stored?\n- **Implementation freedom** - don't lock users into specific technologies\n- **Simplicity first** - easier to implement = better adoption and fewer bugs\n- **Make choices** - one good way beats multiple complex options\n\n## Planning Process\n\n### Phase 1: Problem Analysis\n\n1. **Identify the true problem** - what are you actually building?\n2. **Find the primitives** - what data flows through your system?\n3. **Map the ecosystem** - what external systems/platforms will you interact with?\n4. **Assess risk factors** - what's most likely to change or break?\n\n### Phase 2: Architecture Design\n\n1. **Draw black box boundaries** - what modules do you need?\n2. **Design clean interfaces** - how do modules communicate?\n3. **Plan dependency layers** - what depends on what?\n4. **Consider team structure** - who owns which modules?\n\n### Phase 3: Implementation Strategy\n\n1. **Build foundation first** - platform abstraction, core primitives\n2. **Create test applications** - simple apps to validate your architecture\n3. **Implement incrementally** - one module at a time\n4. **Build tooling** - debugging, testing, and development aids\n\n### Phase 4: Future Proofing\n\n1. **Design for replaceability** - can modules be rewritten easily?\n2. **Plan for scale** - will this work with 10x more features/users/developers?\n3. **Consider maintenance** - who maintains this in 5 years?\n4. **Document interfaces** - can new developers contribute immediately?\n\n## Risk Assessment Framework\n\nEvaluate these common failure modes:\n\n- **Platform dependency** - what if the underlying platform changes?\n- **Language/framework churn** - what if your tech stack becomes obsolete?\n- **Team changes** - what if key developers leave?\n- **Requirement evolution** - what if you need features you didn't plan for?\n- **Scale challenges** - what if success creates new problems?\n\n## Strategic Questions to Ask\n\nFor any architecture decision:\n\n1. **Replaceability**: Can this component be rewritten from scratch using only its interface?\n2. **Cognitive load**: Can one developer understand and maintain this module?\n3. **Future flexibility**: Will this still make sense with 10x the requirements?\n4. **Risk isolation**: If this fails, does it bring down other components?\n5. **Team scaling**: Can we add more developers without coordination overhead?\n\n## Common Patterns to Recommend\n\n### The Platform Layer Pattern\n\nAlways wrap external dependencies:\n\n- Operating system APIs\n- Third-party libraries\n- Cloud services\n- Hardware interfaces\n\n### The Core + Plugins Pattern\n\nBuild extensible systems:\n\n- Minimal, stable core\n- Plugin architecture for features\n- Clean plugin interfaces\n- Independent plugin development\n\n### The Glue Code Pattern\n\nConnect systems without tight coupling:\n\n- Translation layers between different APIs\n- Gradual migration paths\n- Multiple interface support\n- Backward compatibility bridges\n\n## Your Communication Style\n\n- **Strategic focus** - emphasize long-term thinking and maintainability\n- **Practical examples** - reference real systems (video editors, healthcare, aerospace)\n- **Risk awareness** - highlight what could go wrong and how to prevent it\n- **Team psychology** - consider how humans actually work on large projects\n- **Trade-off honest** - explain why you recommend certain approaches over others\n\n## When Consulted\n\nProvide:\n\n1. **Strategic architecture overview** - high-level system design\n2. **Module breakdown** - specific components and their responsibilities\n3. **Interface specifications** - how components should communicate\n4. **Implementation roadmap** - what to build first and why\n5. **Risk mitigation plan** - what could go wrong and how to prevent it\n6. **Team organization advice** - how to structure development work\n\nRemember: You're not just designing software - you're designing systems that teams of humans will build, maintain, and evolve over years or decades. Optimize for human success, not just technical elegance.\n"
  },
  {
    "path": "prompts/cursor-prompt.md",
    "content": "# Modular Architecture Development Assistant\n\nYou are a senior development engineer specializing in building and testing modular, maintainable code using black box architecture principles. Your approach is based on Eskil Steenberg's methodology for creating systems that remain fast to develop regardless of scale.\n\n## Development Philosophy\n\n**\"It's faster to write five lines of code today than to write one line today and then have to edit it in the future.\"**\n\nYou focus on:\n\n- **Writing code that never needs to be edited** - get it right the first time\n- **Modular boundaries** - clear separation between components\n- **Testable interfaces** - every module can be tested in isolation\n- **Debugging ease** - problems are easy to locate and fix\n- **Replacement readiness** - any module can be rewritten without breaking others\n\n## Code Development Approach\n\n### 1. Black Box Implementation\n\nWhen writing code:\n\n- **Hide implementation details** - expose only necessary interfaces\n- **Design APIs first** - define what the module does before how it does it\n- **Use clear naming** - function/class names should explain purpose, not implementation\n- **Document interfaces** - make usage obvious to other developers\n- **Avoid leaky abstractions** - don't expose internal complexity\n\n### 2. Modular Structure\n\nStructure code for maintainability:\n\n- **Single responsibility** - each module/class/function has one clear job\n- **Minimal interfaces** - expose as few functions/methods as possible\n- **No cross-dependencies** - modules communicate through defined interfaces only\n- **Wrapper layers** - wrap external dependencies instead of using them directly\n- **Configuration isolation** - module behavior controlled through parameters, not globals\n\n### 3. Testing Strategy\n\nTest at the right boundaries:\n\n- **Interface testing** - test the public API, not internal implementation\n- **Black box validation** - can you test without knowing how it works internally?\n- **Replacement tests** - would tests still pass if you rewrote the implementation?\n- **Integration points** - test how modules communicate with each other\n- **Error boundaries** - test how modules handle and propagate failures\n\n## Debugging Methodology\n\n### Problem Isolation\n\nWhen debugging issues:\n\n1. **Identify the module boundary** - which black box contains the problem?\n2. **Test the interface** - is the module receiving correct inputs?\n3. **Verify outputs** - is the module producing expected results?\n4. **Check assumptions** - are interface contracts being followed?\n5. **Isolate dependencies** - is the problem in this module or its dependencies?\n\n### Debugging Tools\n\nBuild debugging capabilities into your architecture:\n\n- **Logging at boundaries** - log inputs/outputs of each module\n- **State inspection** - ability to examine module internal state\n- **Mock interfaces** - ability to replace modules with test doubles\n- **Replay capability** - ability to reproduce issues with saved inputs\n- **Validation modes** - extra checks that can be enabled during development\n\n## Testing Implementation Patterns\n\n### Unit Testing Black Boxes\n\n```typescript\n// Test the interface, not the implementation\ndescribe(\"UserAuthenticator\", () => {\n  it(\"should return success for valid credentials\", () => {\n    const auth = new UserAuthenticator();\n    const result = auth.authenticate(\"valid@email.com\", \"correct-password\");\n    expect(result.success).toBe(true);\n    expect(result.user).toBeDefined();\n  });\n\n  it(\"should return failure for invalid credentials\", () => {\n    const auth = new UserAuthenticator();\n    const result = auth.authenticate(\"invalid@email.com\", \"wrong-password\");\n    expect(result.success).toBe(false);\n    expect(result.error).toBeDefined();\n  });\n});\n```\n\n### Integration Testing Module Boundaries\n\n```typescript\n// Test how modules work together\ndescribe(\"User Registration Flow\", () => {\n  it(\"should handle complete registration process\", () => {\n    const validator = new EmailValidator();\n    const hasher = new PasswordHasher();\n    const database = new UserDatabase();\n    const registrar = new UserRegistrar(validator, hasher, database);\n\n    const result = registrar.register(\"new@email.com\", \"secure-password\");\n    expect(result.success).toBe(true);\n  });\n});\n```\n\n### Replacement Testing\n\n```typescript\n// Ensure modules can be swapped out\ndescribe(\"Database Interface Compatibility\", () => {\n  const testCases = [\n    new SqliteUserDatabase(),\n    new PostgresUserDatabase(),\n    new MockUserDatabase(),\n  ];\n\n  testCases.forEach((database) => {\n    it(`should work with ${database.constructor.name}`, () => {\n      const service = new UserService(database);\n      const user = service.createUser(\"test@email.com\");\n      expect(user.id).toBeDefined();\n    });\n  });\n});\n```\n\n## Development Patterns\n\n### Wrapper Pattern for External Dependencies\n\n```typescript\n// Don't use external libraries directly\ninterface FileStorage {\n  save(filename: string, data: Buffer): Promise<void>;\n  load(filename: string): Promise<Buffer>;\n  delete(filename: string): Promise<void>;\n}\n\nclass LocalFileStorage implements FileStorage {\n  // Wraps fs operations\n}\n\nclass S3FileStorage implements FileStorage {\n  // Wraps AWS SDK\n}\n```\n\n### Plugin Architecture Pattern\n\n```typescript\ninterface Plugin {\n  readonly name: string;\n  readonly version: string;\n  initialize(config: PluginConfig): void;\n  process(input: any): any;\n  cleanup(): void;\n}\n\nclass PluginManager {\n  private plugins: Map<string, Plugin> = new Map();\n\n  register(plugin: Plugin): void {\n    this.plugins.set(plugin.name, plugin);\n  }\n\n  execute(pluginName: string, input: any): any {\n    const plugin = this.plugins.get(pluginName);\n    return plugin?.process(input);\n  }\n}\n```\n\n## Code Quality Checks\n\nAlways verify:\n\n- **Interface clarity** - can someone use this without reading the implementation?\n- **Error handling** - does the module handle failures gracefully?\n- **Resource management** - are resources properly allocated and cleaned up?\n- **Thread safety** - can this be used safely in concurrent environments?\n- **Memory efficiency** - does this avoid unnecessary allocations or leaks?\n\n## Refactoring Guidelines\n\nWhen improving existing code:\n\n1. **Identify boundaries** - where should black box interfaces be?\n2. **Extract interfaces** - define clean APIs for each module\n3. **Move implementation** - hide complexity behind interfaces\n4. **Add tests** - ensure interfaces work as expected\n5. **Validate replaceability** - can you swap out implementations?\n\n## Development Workflow\n\n### For New Features\n\n1. **Design the interface first** - what should this module expose?\n2. **Write tests for the interface** - define expected behavior\n3. **Implement behind the interface** - hide complexity\n4. **Test integration points** - how does this connect to other modules?\n5. **Document the API** - make usage clear for other developers\n\n### For Bug Fixes\n\n1. **Locate the module boundary** - which black box has the issue?\n2. **Write a failing test** - reproduce the problem at the interface level\n3. **Fix the implementation** - solve the problem without changing the interface\n4. **Verify the fix** - ensure tests pass and no new issues introduced\n5. **Check impact** - does this change affect other modules?\n\n## Red Flags in Code\n\nWatch out for:\n\n- **Tight coupling** - modules that know too much about each other's internals\n- **Leaky abstractions** - interfaces that expose implementation details\n- **Monolithic functions** - single functions doing multiple unrelated things\n- **Global state** - shared mutable state between modules\n- **Hard-coded dependencies** - direct references to specific implementations\n\n## Your Role\n\nAs a development assistant:\n\n- **Suggest modular boundaries** when code becomes complex\n- **Recommend interface designs** that hide implementation details\n- **Identify testing gaps** where modules aren't properly validated\n- **Spot coupling issues** where modules are too interconnected\n- **Propose refactoring strategies** to improve maintainability\n\nFocus on creating code that will be easy to understand, test, debug, and replace years from now. Every line of code should contribute to a system that maintains developer velocity as it grows.\n"
  },
  {
    "path": "resources/eskil-transcript.txt",
    "content": "0:02\nSo per request I'm going to give a talk about how to structure uh large uh\n0:08\nsoftware projects and um I'm going to talk about like my\n0:13\nphilosophy for how to do design and how I think about like the structure of large things. Um I recently gave a talk\n0:20\nwhere I talked about how every any piece of software should be able to be written by one person and a lot of people didn't\n0:27\nunderstand or had questions. So it's kind of a followup to that. Um if you\n0:32\nwant to go watch that um go to better software conference their uh channel I\n0:38\nwill link to them and you can see the talk. Um but this is more of a deep dive how to actually build software. So let's\n0:45\nlet's get going. So I'm going to very very brief sort of\n0:52\nhandwavy develop three pieces of software today. And uh I'm going to make a video editor. I'm going to make um a\n0:59\ndigital health health care system because that seems to be something that every government fails at and I'm going\n1:06\nto build a jet fighter. So, um those are all complicated things and uh just\n1:14\nbefore you, you know, start typing that I don't know what I'm talking about, um\n1:21\nI won't go into every detail. Obviously, these are huge software projects. There's lots of new ends and I'm also\n1:27\nnot really a domain expert in any of these. So, um I'm not actually teaching\n1:33\nyou how to write these specific pieces of software. I'm trying to tell you how I approach various pieces of software.\n1:42\nSo, um any of these projects, you know, you would need a lot of people who are\n1:47\nhave like domain expertise. you would need to have like people have a good idea of the problems that need to be\n1:54\nsolved and and so on so forth. I know a little bit. So I'm going to use this as a stepping off point to u talk about how\n2:02\nto develop software. But um if you if you want to know details or about any of\n2:08\nthis like I've never developed software for for a jet fighter. So you know um\n2:13\ndon't take all of that with a grain of salt. That's that's not the point here. Okay. Um so this is about process not\n2:21\nthe specifics. Um, so let's talk about the structure. Like how do we structure\n2:26\nthings? That's the main thing. And when we plan a big project like this, we want to optimize for certain things. We want\n2:33\nto optimize for or I want to optimize for dependability. You want a project that lasts forever and never breaks. You\n2:41\nwant it to be extendable so that you can add new features and capabilities and, you know, things that can change. Um,\n2:48\nyou want to have team scalability and a lot of this comes down to that you want to have very few people or preferably\n2:55\none person working on each section of the problem. And therefore, if they are\n3:00\ninsulated from everybody else, you don't have to have like huge team meetings where everybody's working on the same\n3:06\nthing. You want to create a lot of small projects instead of having one big project. And obviously, you want\n3:14\ndevelopment velocity. You want to be able to get done basically and you don't want, you know, usually with\n3:21\nsoftware, the the longer you work, the slower things get. And you don't want that. You want, you know, same velocity\n3:27\nall the time. Um, and a big portion of this is just reducing risk. Like things are going to\n3:33\ngo wrong. That's is just life. But you want to reduce it. So what you got to do\n3:38\nis you got to think about what your risk profile. What what is most likely going to fail, right? and you want to want to\n3:45\nreally avoid those problems. Um, so here are some of the things that can change, right? Um, platforms can change either\n3:52\nthrough API or maybe they change their terms of service or maybe they're not\n3:58\nhip with the users anymore or things like that. So you want to insulate\n4:03\nyourself from platforms that change. Um, you have language implementations. If\n4:08\nyou write something in, you know, the hip cool language today, if you're building a system that's going to be\n4:14\naround for, you know, 20 years or longer, like a jet fighter will be along\n4:20\naround for 50 years. A healthc care system will probably be around for close\n4:25\nto that, right? U a lot of the video editors are from the 80s and 90s. So\n4:32\nhaving software that can live for decades is really important. And therefore you need to make sure you write it in a language that there will\n4:38\nbe compilers for in the future and things like that. And then obviously changing hardware,\n4:44\nchanging priorities. You may need certain things in the future that you don't need today. And you may lose\n4:50\npeople, right? So what happens if you're a star programmer leaves the the thing?\n4:57\nUm these are things you really want to worry about, right?\n5:02\nSo a lot of small chances of failures equals a big chance of failure, right?\n5:08\nUm a lot of little things that might be easy to fix, um if you have enough of them and they happen frequently enough,\n5:16\nuh things grow really really tiresome, right? So you even if things you know a\n5:22\nlot of people say, well that's an trivial fix, you know, a compile error somewhere that you can just like fix.\n5:29\nThat might be true, but if you're working on something and all of a sudden your software stopped working because\n5:34\nsomebody else added a little problem, you have to context switch and stop working on that and fix this other thing\n5:41\nand you know it grinds to halt. You have to look at code you don't understand and things like that. So you really really want to avoid like even the small speed\n5:49\nbumps because as projects grow you get more and more of those speed bumps and you get more and more you know problems.\n5:56\nSo I'm a C programmer. I use C89. It is the most dependable language you can\n6:03\nhave. Um it will compile everywhere. It will last forever. It you know works\n6:08\nworks works works. Um I am currently actually trying to document what I call\n6:14\ndependable C which is like the subsection of C that you can depend on and it's mostly C89 if you want to be\n6:21\nreally safe but there's some parts of C99 that are pretty safe to use as well. Um but really these rules\n6:29\nit doesn't matter if what language you use like you can you can apply all the other things like if you're um you could\n6:36\nuse C++ you could use Python you could use anything really to to write this. This is not a language specific thing.\n6:43\nUm however I do think like language is one of those risks like Python just\n6:48\nbroke everything when they went from two to three. like if you have a you know millions of code that are in Python 3\n6:55\nand they decide to make Python 4 and break the backwards compatibility you have a major problem on your hands.\n7:02\nSo So yeah, this is kind of the rule. It's like it's faster to write five lines of code today um than to write one\n7:11\nline today and then have to edit it in the future. You really want to finish your code. You want to write code so that it never breaks, right? And if that\n7:18\nmeans typing a little more, being a little bit, you know, more explicit about what you want, that's a good\n7:23\nthing, right? Because you're thinking about it now when you're writing it. And going back, you know, five years from\n7:30\nnow trying to figure out what it does and fixing it, even if it's a trivial fix is really, really hard, right? And\n7:36\nit stops working. You want things that are really dependable. you you leave code when it's done when you know you're\n7:44\nnot going to have to go fix it in a couple years and that's that's really really key. Um so you want to modularize\n7:52\nyour software, right? If you're going to have multiple people working, you want to modularize. So how do we do that? So\n7:58\nin my opinion modules should be pretty much black boxes. What they do should be\n8:03\nexposed through APIs or protocols. So you talk to it and it has an interface\n8:11\nthat you can document that is clear and you understand and then whenever you\n8:17\nwant to use it, you talk to that. But you don't actually have to know what's behind the scenes, right? Somebody wrote\n8:23\nit. It's rock solid. It just works. You don't have to know what it does. You never have to look at the code. You\n8:28\ndon't have to integrate with anything outside of the API. The API is\n8:34\ndocumented. Um, and this is why I like header files in Z because you can have\n8:39\nhuge amount of code and then hide it behind one header file says here's all the functions you're allowed to use.\n8:45\nHere's how you access all the functionality. How I implemented that you don't have to care about because I\n8:50\nsolved it for you, right? Um, so this means you can have one module can be one\n8:57\nperson, right? And that's really key is like you can um you can really split\n9:04\neverything into small modules and each each module can be one person right and\n9:09\nyou have multiple modules and that's what I mean every piece of software should be able to be written by one person and by that means it's like you\n9:16\nsplit it down to modules and the modules are small enough that one person can write it and at some point somebody is\n9:22\ngoing to sort of write the application and they do that by taking a bunch of existing modules modules that other\n9:29\npeople are written and just merging them and using all the those things to to do the thing, right? And that's why you can\n9:35\nhave essentially a single person writing all of these pieces of software that\n9:40\nwe're going to discuss today. Um, so yes, obviously you can have good\n9:46\nprogrammers that can finish a module and then make the next module. That's fine, too. Um, but the rule is that you should\n9:52\nreally avoid having multiple people have to work on a single module. You may have lots of people working on designing a\n10:00\nmodule or like deciding how the API should work, but I really think it's good to have only one person\n10:05\nimplementing it. Um, so yeah, some modules are going to be senior and some are going to be\n10:11\njunior. There's going to be modules that are hard to implement and there's going to be easy stuff. So you want to really\n10:17\nthink about that and give the hard modules to your senior people and you know the easy stuff to your junior\n10:23\npeople. And this is a really interesting thing. What if what if that module breaks or is\n10:29\nterrible in some way? Well, if you have an API for it and that API is good, you\n10:36\ncan actually reimplement that API in a new blackbox that uses, you know,\n10:42\ndifferent algorithms, different everything and all the software is using that will still work, right? And that\n10:49\nmeans that if you have a piece of software that is owned by a certain person, you can actually if that person\n10:56\nleaves, you can write rewrite that from scratch and then gradually move to the next version. And um and that's really\n11:03\nreally powerful. Um so let's talk about the video editor. We're going to talk about you know a\n11:09\nbasic video editor. So uh it's a native application with a UI. So let's start\n11:16\nthere, right? So, you're going to want a stack that looks something like this.\n11:21\nYou want a platform layer. You want to open a window and do things like that. You want to be able to draw, you know,\n11:28\nlines and things. And then you want to be able to do text. Um, text could be in the drawing library. Um, and then you\n11:35\nwant some UI things so that you can do a UI for your application. And the text\n11:40\ncan also be in the UI. It happens to be in in my UI library. So um you really should wrap your\n11:48\nplatform layer and the idea here is that anything that you don't own which would\n11:54\nbe the platform you should not talk to directly you should make a wrapper around that and there are a bunch of\n12:01\nrappers out there so for instance SDL is a wrapper you could use however even if\n12:07\nyou use something that is online and and you know open source and you know generally really good you still don't\n12:13\ncontrol that, right? You don't know the direction of their development. You don't know, you know, if you're going to\n12:20\nneed something else, if you um need to add functionality, you don't know if they're going to accept your patches.\n12:26\nSo, even though you're using, you know, something really good, um you really\n12:32\nwant to wrap it so you don't actually have a bunch of calls directly to code\n12:37\nyou don't have in your code. So, um I can show you this. This is betray.h, H\n12:43\nwhich is the header file for my wrapper. Um and it contains all kinds of things\n12:49\nbut it allows you to you know open a window you know just get input lots of\n12:55\nthings. Um and this was actually implemented over SDL from the beginning\n13:01\nbut SDL didn't have this was SDL 1.0 so it was a long time ago but it didn't have all the features I wanted. So I\n13:09\nmade another backend that was win32 and then we've got lots of other you know\n13:14\noperating systems. Um but this really gives you the control over over the\n13:19\nplatform. Um and um then you want to definitely write\n13:25\nuh a demo application uh test application. So I happen to have mine here. So this is my little test\n13:33\napplication and this um is a minimal application that just opens a window,\n13:38\nreads mouse pointers, draws something. There's like some buttons here that do things. I can click here. I have a\n13:45\nlittle window here. If I, you know, scroll my window, I get all the events. So this is like really really useful\n13:51\nwhen you try to port this API to another platform because if you're building a huge video editor with lots of you know\n13:59\nmillions of lines of code you don't want to have to port all of that code over to the platform. You want to start with\n14:04\nsomething very very small and very simple. So therefore it's super useful to do this. Usually you write this while\n14:11\nyou write the platform later because you need something just to test that what you're doing is correct. Um so this is a\n14:18\ngreat little thing. So I can uh show you you know uh hold on here is a screenshot\n14:26\nof the same software running on Android and it's run on lots of other things and this is like when you pl you move to a\n14:33\nnew platform this would be the first thing you do is it's just um get that going and here is you know the file so\n14:42\nit's it's not huge but it draws some stuff it, you know, it basically tries\n14:50\nto exercise all of the API. Now, normally when you actually implement this, you tend to um comment out most\n14:58\nthings. So, you you start with just like open a window and then when you get that working, you're like, okay, now I'm\n15:04\ngoing to comment out like read the mouse pointer and you you know, as you work through, eventually this whole\n15:11\napplication will run on the new platform.\n15:16\nSo there are things to consider when you do a platform layer and what those are\n15:21\ndepends on your plat your application what you want to do but like what kind of inputs do you want uh you know screen\n15:28\nresolutions um aspect ratios um scale um\n15:34\ndo you want cut and paste do you want file requesters safe spaces is getting\n15:39\nmore and more important meaning basically you know your window may be this big but maybe you're on a phone and\n15:45\nthere's a notch in the way or something like that or rounded corner. So, you shouldn't really put text there. So, you\n15:51\nneed to be able to detect um which areas of the screen are actually safe for UI or for for information. And then you\n15:58\nmight want to support things like multi-user. So, my uh layer um has not\n16:05\njust input from multiple input devices but also from multiple users. So for\n16:11\ninstance, you can have two controllers and therefore um those are two different users giving input. Um, and therefore my\n16:19\nproto um my API supports things like having two mice and two keyboards\n16:25\nconnected to a computer. And therefore you can in my UI toolkit you can click one user can click with a mouse pointer\n16:32\nin a text field and start typing while the other user clicks in another text field and starts typing and the the the\n16:39\ntyping will go to the right window. Now right now there's no platform that actually supports that. So, Windows\n16:46\ndoesn't properly support that and I don't I I I don't know of a platform that supports that. But if there is a\n16:53\nplatform in the future that will support that, all my applications will just work, which is super useful.\n17:00\nUm, so then you also want to consolidate a lot of functionality, right? You want to take all the disperate things that\n17:07\nyou could have on a platform and make them one thing, right? So, um, you know, in my example, all buttons are the same.\n17:15\nIt doesn't matter if they're on a controller, on a keyboard, or a mouse, doesn't matter. All pointers are the\n17:20\nsame. So mouse pointer is the same thing as a touch. So basically, we have multi-touch, multi-pointer, they're all\n17:26\nthe same. And you just, you know, a touch is basically a mouse pointer that\n17:31\ndoesn't move when you're not clicking and that um only has one button, right?\n17:37\nAnd the same goes with axis. So that would be joysticks or pedals or whatever input you have. it gets a little bit\n17:44\nmore complicated. We'll get into that later. So now you want to do a drawing layer. Um you need, you know, basic\n17:51\nthings to draw UI. If you want to do something, want to draw lines, surfaces, images, maybe shaders, maybe geometry,\n17:58\nit depends on what you're trying to do. Um this is mine. This is Relinquish.\n18:04\nIt's built over OpenGL, but it actually designed so that you can run it over Vulcan or any any backend. And I'm\n18:10\nhoping to implement that at some point. Um, and then you want to do text. Obviously,\n18:17\nall applications need text. And here's kind of a an example of how I would implement that. Like you can implement\n18:24\nthe simplest possible text. So, you can take, you know, a font you find online like this one that is like just a bit\n18:31\nmapap font. You load it in, you make a bunch of, you know, squares and you draw\n18:37\nthis, right? And if you implement this um you can make a simple function that draws text uh\n18:46\nfloat there it's supposed to be um you can draw this really really easily right so since you have this way of thinking\n18:53\nabout black boxes now you can actually make a black box that draws text and it can be super simple like like a bit map\n19:00\ntext doesn't do anything complicated but once you have that you can you know\n19:05\npeople can start writing UIs that text and then you can go in and you can have, you know, proper font loading. You can\n19:12\nhave, you know, all kinds of good stuff, right? So, you can do true type fonts\n19:17\nor, you know, anti-aliasing and kerning and all that stuff that you don't care about, right? So, this is a really\n19:24\nimportant thing. It's like you can you can give somebody an API uh for something that isn't actually finished.\n19:30\nLike it it draws text, but it doesn't draw nice text. But that's fine because other people don't need nice text in\n19:36\norder to be able to start building interfaces. They just need text, right?\n19:41\nSo this API that I'm showing here is actually not very good because this one\n19:47\ndoesn't get you all the things you want to do. So I'm going to show you this is my function for drawing text. It's\n19:53\nactually one out of many. So for instance you want to give it what font you want to give it you know the\n19:59\nsize of the letter the spacing of the letter you know the text and you want you don't want the text to be asy you\n20:05\nwant it to be UTF8 or something like that um you want a color and you want a\n20:11\nlength specifier so you can limit how long of the if so you can uh just print a part of the text now and then you want\n20:18\nit to return how long the text is right so even if you implemented it using this\n20:24\nuh this stupid font font with no kerning and nothing. You can still build this interface for it, right? Maybe the font\n20:31\nis, you know, just null for now. And that gives you the default font. And there is no, maybe there's only one\n20:38\nfont. Maybe you can't choose fonts, but you still have a font parameter there. And that means that people start writing\n20:44\nthis can start writing code as if it was done. And then when it gets done the\n20:49\ntext will start looking great but will actually you know nobody has to reimplement all the places where they\n20:57\nwrote uh use the text functionality. So this is really you you want to learn how\n21:03\nto think forward right you want to think what are we going to need in the future right and really avoid implementing ah\n21:10\nis good enough for now um because you want to finish stuff um and if you have\n21:16\nto um you know you know text for instance you may not want to do Arabic\n21:22\nwhich is backwards and things like that or Korean or things like that right maybe your product team can't wait uh\n21:30\nfor for you to implement that because they need to ship something, right? So then you can implement something simple,\n21:37\nbut you never implement a a good enough for now API. The API is the same. You\n21:42\nknow, you think through I'm going to do Korean at some point. So let's make an API that is is good enough for Korean\n21:48\nand then people can use that and even if you can't draw Korean now, it will in the future and they won't have to change\n21:55\ntheir code. So that's really really important. Uh and then you can you know do the same\n22:00\nthing build a UI toolkit. I have a UI toolkit. This can be modularized. Mine\n22:05\nis one big UI toolkit but you can modularize it for button and things like that. And I would argue that making a UI\n22:14\ntoolkit is relatively easy. Like buttons are easy to implement, sliders are easy\n22:19\nto implement. The only thing that is kind of tricky to do in UI is is text input. So, um, not relying on the\n22:27\noperating system, not relying on a platform is is not a big deal. And especially if you're making a portable\n22:33\nthing, a portable application. And if you have to figure out how like three different platforms do a slider, you're\n22:40\ngoing to need more time to do that than to implement your own slider. So, just make a slider.\n22:46\nUm, so, okay. So, now we have this, which is like our our base layer. Now,\n22:53\none of the things you might notice is that like um you can actually none of\n22:59\nthis has to do with the the video editor, right? This is just like stuff\n23:04\nyou can build anything with like any desktop or or mobile app. You can just write it, right? So, once you've done\n23:11\nthis, this is actually a superpower for for yourself, for your company. And to me, it's like amazing that like large\n23:18\nbillion dollar software companies don't own this. like they should just have this so that they quickly can make\n23:25\nwhatever product they want to make in the future. Like you should not have to rely on the operating system to to draw\n23:31\ntext. You know, if you're, you know, even if you're a small company, you should be able to do this. If you're a\n23:36\nhuge company or a big company, you should definitely have this as as part of your tool toolkit.\n23:44\nUm, so yeah, these are all sort of helper libraries, right? And um you really want to put as much as you can in\n23:51\nhelper libraries because helper libraries can be reused for any project, right? So fell parsing, physics engines,\n23:58\nuh scripting, data storage, networking, all kinds of stuff like that, right? So for instance, for networking, you know,\n24:05\nI have Testify, which is a library that does all of the the things you need to\n24:11\ndo and it can figure out what kind of network you're on. It can do, you know,\n24:16\nall kinds of stuff. It opens up ports with port forwarding protocols. It it\n24:22\ncan find peers. It can do all kinds of stuff. And um it's really really\n24:28\npowerful. And um it basically means that I never have to care about like the\n24:34\nsocket API ever again, right? And I can improve this under the hood. So there's\n24:39\ncapabilities of of like how to connect and how to you know u do certain things\n24:44\nthat I can improve under the hood without changing any of the applications that use it.\n24:50\nOkay. So now we're getting to the core which is when you're actually starting to build the application you're building\n24:56\nand this is kind of the majority of this talk and how to how to build a core.\n25:01\nUm so what are the things we are editing? What what is the thing that this application does? How can we\n25:07\ngeneralize what it does, right? So, um, in my opinion, a video editor is not\n25:14\nsomething that edits video. It edits a timeline, right? It's a timeline, a\n25:20\nbunch of clips that overlay each other and they're in time and you can from\n25:26\nthat you can generate a video. You have a bunch of clips, you have an input data and then you have a rearrangement of\n25:32\nthat input data and then you get an output. Right? So, we can think about this as as you know, clips on a timeline\n25:39\nwith animated parameters, right? Because we're going to need parameters. We want to zoom in. We want to color correct. We\n25:44\nwant to do titling. We want to do all kinds of things. So, those are going to be parameters that these clips have.\n25:52\nSo, everything is a clip, right? Now, we've made it really generalized, right?\n25:57\nAnd this is really key. It's like if you can generalize things, you can make really nice software. So Unix everything\n26:05\nis a file right and that means that you know lots of stuff in Unix are\n26:10\ncompatible because it's like this takes a file this outputs a file you can connect those together and things work\n26:17\nright um software like uh Houdini uh I think I have a screenshot here is\n26:22\nbasically a node graph the whole software it's a big visual effects package is basically one big node graphs\n26:30\nwhere each node has parameters on it that that's what Houdini is right and uh\n26:35\nnotch I I just want to bring up because they're awesome is the same thing. It's it's a node graph to do visual effects.\n26:42\nRight? So these are you know basic structures that you can put your whole\n26:48\napplication into. Right? If you take something like Unreal, it gets more\n26:53\ncomplicated. Right? Unreal is C++. It's a bunch of C++ but there's also\n26:58\nblueprints and there's also scene graph with assets. That means that you can't generalize everything quite as easy and\n27:05\nyou end up with situation where like oh we've done this in Bluetooth uh in sort of blueprints sorry uh but we wanted it\n27:12\nto be in in C++ or we did this in C++ but now we can't access it the way we\n27:18\nwant it in blueprints or is this is an asset is it blueprints what is data what\n27:23\nis it gets a little bit more complicated and this is not directly to critique Unreal Unreal does very very complicated\n27:31\nthings. So sometimes you can't simplify things like this, right? Um the world\n27:36\nisn't as simple as you want it to be, right? Um so what you want to think about and\n27:43\nwhat I think a lot about is something I call primitives. And primitives is sort of a word I borrow from computer\n27:48\ngraphics. Um I have a computer graphics background. So I think I think in polygons or or or things like that and\n27:56\nwe want to talk about polygons, right? So if you want to make geometry, you can\n28:01\ndefine them by polygons, right? So typical, here's a Utah teapot. It's a bunch of polygons like little triangles\n28:06\nor quads. And that's a very simple way to express 3D data. But you can also\n28:12\nthink about other ways of doing it. You can do nerves. They are mathematical curves. Um they can actually do, you\n28:19\nknow, curves. Uh polygons can't do curves. So if you want to do a car modeler, you nerves are way better. Uh\n28:26\nbut nerbs are really really complicated mathematically and they're not easy to deal with and and you need a lot of code\n28:33\nto manage them. Um you can also do something like this like this is tear\n28:39\ndown. So tear down everything is built out of voxels little cubes if you will\n28:44\neven though they're not. Um and that means that it's super easy to do collision detection. It's easy to do\n28:49\ndestruction. It's easy to do a whole bunch of things that are super hard to do with triangles. Um, on the other\n28:57\nhand, there things like making a smooth surface with a bunch of little cubes is\n29:02\npretty much impossible, right? So, you win some and you lose some basically.\n29:08\nAnd then, you know, we can go further. This is, you know, sign distance fields which are, you know, a new hot way of of\n29:15\ndoing mathematical shapes. um that gives you a bunch of other advantages um and\n29:20\ndisadvantages or you know my favorite is subduction surfaces. This is from my subdution surface modeler which gives\n29:27\nyou a poly mesh that gets rounded into a a smooth surface or a smoothish surface.\n29:35\nBut which one of these you choose really makes you choose what kind of software\n29:42\nyou're building. And some of the more advanced softwares like you know Maya and and others they allow you to have\n29:49\nmultiple different representations of geometry. But that also means you get a lot of complexity in your software\n29:55\nbecause now there's functionality you can do on nerbs you can't do on polygons or things you can do on on your voxels\n30:02\nbut you can't do on your polygons. So you have to convert back and forth and you get lost and it be getcomes really\n30:09\ncomplicated. So if you can find a primitive to store your data um that is consistent and that works for everything\n30:16\nthat's really really neat, right? So um Unix uh let's talk about Unix some\n30:25\nmore. Like Unix is a good example actually of this. So Unix everything is files, right? Pretty much text files.\n30:32\nThey're not any file. And that means you can grap it for a piece of text and you can find it and that's great. But it\n30:39\ndoesn't work for like you can't GP for a quote from you know a MP4\n30:45\nfile that contains Casablanca. You can't find all the good quotes because GP works on text not on video right. So by\n30:53\nlimiting yourself and saying everything is a text file, you can do a lot of things with text files, but when you\n30:59\nwant to do video editing or image editing or something that isn't text, you know, Unix and the command line is\n31:06\nnot really a good interface. And there here's I want to talk about um\n31:11\nprimitives versus structure, right? So in Unix you could say that the structure\n31:16\nhow we use um this is we use command lines with pipes to pipe things between\n31:22\napplications right but the thing that moves between the application the format\n31:27\nof the data that goes from A to B that is files and that's the primitive right\n31:32\nand if we change the primitive we could make a command line system that where you can pipe video from A to B and then\n31:38\nthe primitive would be video but we'd still have the same structure right or we can also have a structure where we\n31:44\nhave you know a UI as a node graph but where through the cables we push text\n31:50\nright so we use the same primitive so these are two different things you have to think about like when you choose how\n31:56\nto design this right and here's an example so Photoshop has the structure\n32:02\nof a bunch of layers which isn't really true in modern um Photoshop because Photoshop is complicated but we can\n32:08\nthink of it as a bunch of layers of bit maps right whereas Nuke which is a compositing software. Uh I have a\n32:15\nscreenshot here. This is a node graph um from Nuke that allows you to composite,\n32:21\nyou know, video essentially. Um the primitive is still bit maps. There's still bit maps moving through this\n32:27\nthing. Um but it's a tree structure now. So again, you know, both of these, you\n32:33\nknow, they're not really always bit maps. They're, you know, they can do curves and things like that, but sort of generally you can think about these as\n32:40\ntwo different things. Um so in our case when we want to do a a video editor we\n32:46\nsay that all tools that we want to make operate on clips right when you move in\n32:51\nyour timeline you're basically editing a clip or you're changing parameters of that clip that's all you do all the UI\n32:58\neverything does that that's what the application actually is so we want to\n33:04\nbuild a black box that stores this information right stores a timeline and have an API so we can access it Right.\n33:12\nSo, uh, an example of something that actually exists that does that is open timeline io, which is an open, um, API,\n33:19\nPython API to create a timeline. Um, you would probably build your own.\n33:25\nUm, so when you build this core that keeps\n33:31\nall your data from your application, you can enforce these kind of guarantees. So, in our case, we kind of want to do\n33:38\ncertain things. For instance, we want, you know, clips not to have negative time or, you know, maybe we want clips\n33:45\nto never be longer than the asset they are using. Maybe we want, you know,\n33:51\nconsistency in time. Maybe we want whatever we think is important and that we want to guarantee. And that means\n33:57\nthat when APIs call this, they don't have to care about that, right? They know that the data they are going to is\n34:02\ngoing to have, you know, certain requirements and and be clean, if you will. Another thing you might want to do\n34:09\nis undo, right? Other application can just say change the clip like this and\n34:14\nautomatically this you know storage container of will actually manage\n34:20\nfiguring out what the changes are from the last version and be able to undo those. Um so therefore you want to build\n34:26\nthat into your core structure. Okay. So what kind of clips do we want to support? Like we want to load all\n34:33\nkinds of video, right? So, how do we do that? Well, if the core has a definition\n34:40\nof every clip you could ever want, every video format, every effect, everything,\n34:45\nthen the core is huge and it's not possible for one person to write it. So, we really, really don't want to do that.\n34:52\nSo, we want to build a plug-in architecture. We want to build an API where, you know, a piece of code can go\n34:58\nin and say, I can do this. I can show you video of MP4 and I will give you\n35:05\nthis information about the length and resolution and things like that and I will need you know the speed you want it\n35:12\nto be played back at and the default of that is you know 1x and you know you\n35:17\nwant to describe this plugin basically um and this plugin so you basically get\n35:24\nsomething like this this is my structure for this so you have a core with a bunch\n35:30\nof plugins and And then we have our UI toolkit. The core here um doesn't\n35:36\nactually have a UI, doesn't do anything. It's it's just a core, right? That you can, you know, read in plugins and then\n35:42\nyou can access the plugins. So let's have a look at what you want to write next. Well, you want to write a\n35:48\nlauncher, right? You want to write something that you know starts up the platform, starts up the core, loads in\n35:55\nall the plugins, and actually does something. So, uh, in my case, uh, let's\n36:02\nsee. I think I'm missing something here. Um, I'm going to show you some demos of this in a second. Um,\n36:10\nin my case, you, this might be enough, right? You might just have all the UI\n36:15\nand all the APIs here. You just write a UI for, right? If that's a simple application.\n36:21\nUm, and I'm going to show you a simple application. So uh let me show you an\n36:27\napplication I have written that works kind of like this. So this is stellar. Um it's actually stellar 2.0 which is an\n36:34\napplication to control u lights and\n36:40\nyou can I I'll show you a little bit about how this works. So here is a 3D\n36:46\nworld and here u we have a light fixture. So now I looked on the network\n36:52\nand has to be a light fixture there. I can create a collection of light fixtures which gives me inputs and then\n36:59\nI have a bunch of these which are things that do things and these are plugins. So all the effects in this application are\n37:06\nplugins. So I can for instance create a sphere and I can connect this to this.\n37:13\nSo now you can see I have a sphere here and um I can actually move this sphere.\n37:21\nI can change parameters. I can make it a little fade. I can change the color um\n37:28\nor whatever I want. And then this application happens to be a node graph as you can see. Um I can bring in other\n37:35\nthings like I can create some motion here. connect this to motion and then uh\n37:42\nrun it on a loop. So now it\n37:48\nit moves very fast, right? So now I've created a a simple effect, right? And I\n37:54\ncan bring in some other things like I can bring in\n37:59\ncolor ramp. So I'm going to take this ramp.\n38:06\nSorry. And I'm just going to make it slightly smaller.\n38:13\nSo I'm going to connect this to the ramp instead. So now it gets a single color. And then we're going to drive this ramp\n38:20\nwith this thing. And now I can say a color here and another color here. And\n38:27\nlet's let's make it black here. Right? So now I can remap and do all kinds of\n38:32\nstuff. So um this is kind of what this application does. Um but if we if we\n38:39\nlook under the hood, you can see that actually all of these are plugins. Even this is a plugin. It's a built-in plugin\n38:46\num that just sort of magic plugin that talks to like fixtures. And then these\n38:51\nare all just describing what they do. So if we look at the internals of this um\n38:58\nthis API is what you build your UI from. You basically say here's to create an\n39:05\neffect and you know you can create nodes. You say which node you want. Um\n39:10\nyou can get all of the you get the descriptor that tells you what parameters it has and then you can set\n39:16\nthose and you can build basically a UI. So this this little thing is all you\n39:23\nneed to really build the whole UI, right? So the core can be kind of small and then you on top of that build a UI\n39:30\nand that means I can rebuild the UI without ever rebuilding the core. And one of the things about this application\n39:36\nwhich you might want to do with a video editor is you can actually take your core and make a separate application. So\n39:42\nlet's say you have you know your video editor and then you save a video editing file. Maybe you want to have a, you\n39:49\nknow, a command line tool that can just take that and process the video for it because you want to run that on a server\n39:54\nor something like that. Well, then you can have the core and then you skip all the UI, all opening window and just make\n40:00\na little command line thing and all of the core of the application that does all the processing is completely\n40:06\nseparated from the UI. Um, and we can actually I will show you\n40:12\na plugin. So here is um a file that is a bunch of plugins and what you do to\n40:19\ncreate a plug-in is you these live in a separate DL and that means that um the\n40:24\napplication stays kind of small and you can have people writing DLLs and you can add those one by one and those people\n40:31\ncan basically work completely isolated. They don't have to know the people who write the co core. They can just follow\n40:37\nan API and and make any plug-in they want. And most of the interface, most of\n40:43\nthe the functionality in the application sits inside of those plugins. So here's kind of a simple way you say, \"Hey, I\n40:50\nwant to do a sphere,\" which was the effect we saw. It's it will output color. It's part of a shape. You know,\n40:57\nsome text you can put in UI that describe what it does. And then you list all of the inputs of it, what what\n41:03\nthey're called, what the default values are, you know, a little bit of UI hints of how you might want to draw this. And\n41:10\nthen you also give it a function. And if we go to that function, this is the\n41:15\nfunction that actually does the the computation, right? So this allows you to implement new features really really\n41:23\nquickly. So, um, and actually just to be really\n41:29\nnerdy about it, um, this API, this kind of plug-in API, I also have that for for\n41:35\nfor Betray, which is my platform library. So, if we look here, this is\n41:41\nthe platform. This is a plug-in for for doing uh controllers on on Xbox\n41:46\ncontroller, basically Windows controllers. So that means that when I build my system, I don't have to link in\n41:54\nspecial code for for Windows. That's a separate plugin that can be built separately. And therefore, you know, I\n42:01\ndon't have a dependency on that. Um I only have a small DL that has a dependency and the system will work just\n42:08\nfine without it. It's just sort of an optional thing. And that means that it's you can have a lot of little\n42:14\ndependencies, but you don't ever need all of them to build it. you need no almost no dependencies to build the the\n42:20\nthe project but then you can add the the the stuff you want. Okay, let's move on.\n42:27\nUm so um you want to present um information and\n42:35\ncapabilities and this is kind of a pattern that comes up almost always to me. And when you build structures for\n42:43\nthings, you want to be able to have things say what they can do and what they um what they can tell you, right?\n42:51\nSo here's like a very simple washing machine, right? If you look at these two strcts, what am I doing? You can think\n42:57\nof type defaf. It's like I am a washing machine. I'm currently running, you know, and you have an enum for what kind\n43:04\nof mode you're in. What's my current temperature? What's my current load? And how many seconds do I have left? Right?\n43:10\nIf you if you get this information with the information of the structure like if\n43:15\na if a washing machine can say these are the parameters I can tell you about\n43:21\nmyself that's all you need to build a UI right you could build an app that works with this right and then the same thing\n43:28\nis like you need a struct to say basically here's the parameters you need to send me in order to tell me what to\n43:34\ndo like you know you need to tell me if I should run or not in which mode and in which temperature, right? And I can't\n43:42\nfor the life of me why believe why the um the people who do IoT stuff um can't\n43:48\nget this right. But really, you want to you don't have to know that it's a washing machine to build this system,\n43:54\nright? All you need to know is this is the stuff that it wants to tell you. This is the stuff it needs to know,\n44:01\nright? And whether that's a washing machine or a toaster or a whatever doesn't matter, right? And I'm actually\n44:08\nworking on a project called Marshall, which I hope to make a new video about that will solve a lot of these issues.\n44:15\nOkay, so here's our new updated design. We might have a core, bunch of plugins,\n44:21\nbut we may also have a launcher UI and then plugins to that, right? So if we\n44:26\nhave a complicated UI, um we may have a launcher that starts it and then says,\n44:33\n\"Okay, there's a bunch of panels here. the panels that show information, they\n44:38\nare themselves plugins and they talk to the other plugins and do the graphics and therefore we can split up the UI. So\n44:45\nwe have one engineer doing just a timeline and one doing you know the video view or color correction or like\n44:52\nall the different sections we we may split those up and not have one code base, right?\n44:58\nOkay. So let's build a health care system and you're going to see that it's very very similar. Um so first obviously\n45:06\nyou want to figure out your requirements. uh you want to figure out what's the primitive what is the data\n45:11\nthat flows through you know health care system and uh maybe medical journals\n45:16\nright that's what people think well probably not the greatest things I think we should probably have healthc care\n45:23\nevents right because if you think about it your health care journal is a bunch\n45:29\nof events like starting with you being born and a bunch of things happen every time you go to a doctor that's an event\n45:35\nright and what's neat about that is you can then also have future events like your appointments and you can also\n45:43\naccess the data in a different way. So you may for instance want to say I want to get all of the health care events at\n45:48\nthis clinic today, right? And that means I want to access everybody who is going\n45:54\nto be here and when they're going to be here today, but I don't want their full journal, right? I might be a clerk\n46:00\nsomewhere. I'm not allowed to read all the information, but I need to know who's going to be here. I need to know\n46:06\nwhen there is a, you know, gap in the schedule, and I need to know that, right? So let's go with that. Let's say\n46:13\nwe're doing a bunch of events, right? And then we do exactly the same thing as\n46:18\nwe've done before. We build a blackbox and you know, here's what people start\n46:24\nout with. They say, \"Well, you know, what kind of storage would you choose? Would you do SQL or blah blah blah or\n46:30\nAmazon or whatever?\" And that to me is completely the wrong way to go about it. What you want to do is what are we\n46:36\nstoring and how are we accessing, right? And that is a blackbox how it's actually\n46:42\nstored, right? So I would probably store it at some kind of open-source\n46:48\nthing that I would find good. You can write your own or whatever, but to all\n46:53\nthe users of the system, none of that matters, right? And that means you can actually change your storage anytime you\n47:00\nwant. You can rewrite it and go somewhere else, right? You don't want to lock yourself to, you know, Amazon or a\n47:06\ncertain vendor. You don't want to even lock yourself to, you know, MySQL or something that is stable and open\n47:12\nsource. Who knows what you're going to want to use in the future, right? So, you really, you know, for the users of\n47:18\nthe system, they shouldn't have to know, they shouldn't have to like do SQL calls\n47:24\nbecause there might not be SQL behind it, right? You need to make your own interface for how to access this thing.\n47:31\nAnd that means you're way more flexible. Okay. So the second thing you can do\n47:36\nonce you built this is once you have an a API between your black box you can\n47:42\ntake whatever old system because guess what your health care system probably has something anient that you want to\n47:47\nget rid of but you don't want to switch over right that's what a lot of projects like this they fail because they switch\n47:54\nover right and the switch is really really painful so why do that so what you do is you write a little piece of\n48:00\nglue code that uses your access API with the old access API Okay. And just moves\n48:05\nall the data between it. So when you get a new event or new data into your\n48:11\nsystem, you move it into the old system, when the old system gets something new, you read that out, put in the new\n48:16\nsystem, right? So now nothing will break. Now you can gradually move over, right? And this is super useful that you\n48:23\ndon't want to have this breaking change where you say we go from system A to system B. No, no, you want to have both\n48:29\nsystem at the same time, right? And then you can start doing other glue\n48:34\ncodes on top of this, right? So let's say you have this black box. Maybe you want to have multiple APIs to use it,\n48:42\nright? Maybe you want a C API, but hey, nobody's going to write C, right? Maybe the hardcore people want to write a high\n48:48\nperformance C thing, but you know, most developers not going to use C. So you can make a C++ API on top of it. You can\n48:55\nmake a Python binding. You can make all kinds of bindings on top of S. and they\n49:00\njust use the same API. And then you can get, you know, your hardcore C++ nerd to write the perfect C++ thing. Actually,\n49:07\nthere is no perfect C++, but whatever, right? You can have different people writing these glue codes that that gives\n49:14\npeople multiple ways of accessing the system u without needing, you know, to\n49:20\nbasically use the the core APIs. And then of course when there's new languages, new capabilities or new ways\n49:27\npeople want to access, you can write new GL glue codes, right? And then you can\n49:32\nwrite stuff on top of that. So on top of your glue, you can say, well, now we take data out of the blackbox and you\n49:39\nknow, we send it over the internet and now we can write a app that does something very specific, right? So we\n49:46\ncan have hundreds of different apps for different kinds of health care people for machines that you know do things\n49:53\nwith healthcare and they can all report back through the internet and they can use their own way of of talking just as\n49:59\nlong as it ends up in in one of these sockets right and now we can build a website right so we you know let's say\n50:06\nwe use Python so we can take you know a Python API and we can generate a website\n50:12\nand you can use a browser to access the information Right? So you can sort of fan this out and grow a tree of stuff,\n50:18\nbut everything goes through this central black box of thing, right? Um now in\n50:25\nreality that blackbox might run on one machine or a thousand machines or you know but to the users to these\n50:33\napplications it's just an API you talk to and you don't have to know what happens in the background if there's a\n50:39\nbig server infrastructure to store all this data. you know, how it's sliced and\n50:45\ndice. None of none of that you have to care about because this is an API to you.\n50:50\nUm, so let's build a jet fighter. Okay. And that you're going to see that it's pretty much the same thing. Okay. So,\n50:58\num, we have lots of things here. We have lots of sensors, weapon systems, like capabilities forever, right? And a lot\n51:04\nof these capabilities, we don't even know what they are because if you build a jet fighter today, it's going to be\n51:09\naround for 50 years. So who knows what kind of missile or drone or sensor or\n51:14\nwhatever you want to put on this thing you know 25 30 years from now. So even\n51:20\nif you can probably survey this and you can probably have some really smart people who can tell you all these things\n51:26\neven they are not going to be able to know. So you can't really architect a system knowing what it's going to be\n51:32\nright. Okay. So what is a primitive we might be able to use? So we might say\n51:39\nwell the primitive here is the state of the world like a whereas a health care system cares about history um a jet\n51:47\nfighter mostly cares about what's going on right now right it wants to know where are all the contacts where are the\n51:53\nenemies how much fuel do I have how many bullets do I have left you know which radar can detect which object you know\n52:01\nwhat's the wind temperature all kinds of things right that all these sensors and\n52:06\nthings are are giving you, right? And you want to care about some things that are specific to, you know, aircraft. So,\n52:14\nyou know, you want to have confidence, right? How how, you know, how much do I trust this thing, right? Um, and you may\n52:21\nnot trust everything in a war, turns out, right? You want accuracy, right? If you have two different things that\n52:27\nmeasure the same thing, you want to know the accuracy of those things, right? Um, you want to know what the source is,\n52:33\nright? So if you get temperature from something, you want to know what the source of that temperature is. Um you\n52:39\nwant to know what the format is, right? So you might have multiple formats of things like maybe I want to know where\n52:45\nposition of this enemy. Do I want it, you know, in relation to the the jet\n52:50\nfighter or do I want to know where it is in the world? Like those are two different things, two different ways of\n52:56\nasking where a thing is, right? And then I want a bunch of capabilities. Like I\n53:02\nwant to know if you put on a missile on the plane, you want to know what can this missile do, right? And when you\n53:09\nfire it, you want that capability to be gone, right? And you want people to be able to add new capabilities, new\n53:15\nmissiles, new things. And then the system should be able to understand that now you have a new capability. And then\n53:23\num you probably want to have things like damage like things you know accuracy may\n53:28\ngo to zero if somebody has blown off a sensor or something like that.\n53:34\nOkay. So you want to build again a core right uh blackbox to store this. So what\n53:41\nyou do is you make an authorative core. You make a core that has like here's the\n53:47\nworld according to all the sensor and all the stuff. This is the current state, right? But then you're going to\n53:53\nhave lots of little computers around, you know, lots of systems, every every little radar, every, you know, the\n54:00\ndisplays. There's going to be computers everywhere, right? So all of those need to know the state. So then you need a\n54:07\nprotocol so that they can subscribe to information, right? You probably want to have a subscriber model where you know\n54:14\num a certain you know the engine wants to know you know the humidity and it wants to know how much fuel or or you\n54:20\nknow the altitude and things like that but it doesn't need to know like um you\n54:25\nknow how many radar contacts you have. That's not interesting to the engine, right? Doesn't care, right? So you want\n54:31\nto basically and you're going to have some parts of the the the plane that are going to have really powerful computers\n54:38\nand some parts going to have like microcontrollers. So you want to be able to subscribe to the information you want. You want that\n54:45\nto be push notificied to you. You may have different rates how often you want\n54:50\ninformation and things like that. And once you have that subscriber, you\n54:55\ncan then on your local chip in your local memory have you know a partial state of the world right and you can\n55:02\nthen use that to um make decisions right and then you can even you know when you\n55:09\nwhen you build this system you can say well we might want to have different ways of encoding this information\n55:14\nbetween the subscriber and the authorative core because we may have different types of cables different\n55:20\ntypes of you know hardware connectors basically, right? We might want to support multiple of those with\n55:26\ndifferent bandwidth, different requirements, what have you, right? But this still means that if you're\n55:32\nbuilding a piece of equipment for this, you now have a stable API, an API you can call to know what's going on and to\n55:40\nsend information. So if you're building a radar, you can, you know, get the humidity or whatever you need from the\n55:47\nsystem and then you can send all the contacts you find to the authorative core and the authorative core can send\n55:53\nthat on to, you know, the pilot or the visualization system or the screens or\n55:58\nthe head-up display or whatever system is interested in that information. Okay, so it's not really a storage\n56:06\nsystem here. Like here's a pass through system, right? you're passing data from one end of the plane to the other. Um,\n56:12\nand you can obviously store as well if you if if that's a requirement. Um, and\n56:17\nhere is a really important thing um that goes for all of these project and that's if you build something like this, you\n56:23\nwant to do a lot of tooling, right? So, let's say we're building a new jet fighter. Um, we haven't figured out what\n56:29\nit's going to look like, but we build this core, right? and we're going to have all these different contractors and\n56:34\npeople building missiles and things and they all have to somehow connect to this thing. How do we do that? Right? They\n56:41\ncan't like how do you how do you test a missile when the button in the uh that the pilot is going to press isn't done\n56:47\nyet, right? So therefore, you want to have lots of toolings, right? So you want to be able to take all the input\n56:53\nfrom various things and record it, right? So now you have a blackbox recorder, right? Because all the information goes through this thing. So\n56:59\nyou can have a little recorder that subscribes to all the information and stores that, right? Great. And then you\n57:05\ncan have a playback. So now if you have, you know, your first flight, you can record information and then you can put\n57:11\nthat to a missile and say behave. Here's a real flight that we recorded. Here's all the data from it. Now we can\n57:18\nsimulate that, right? You may want a Python API because maybe you want to, you know, when you test a certain thing,\n57:24\nyou want to simulate that, you know, um, something happens like what happens if\n57:29\nthis goes away or the radar stops working or whatever. Now, you can simulate things like you want a logger\n57:34\nso you can see what's going on. Maybe I'm just implementing my radar and I need to be able to see when the radar\n57:40\noutputs that it outputs correctly, that the the data coming into the system is correctly. Just having something that\n57:46\ncan print it on screen is like super useful. Um, you can have visualizer to\n57:51\nsee what's going on. You can have full simulators, right? And all this code that I'm showing on on the slide are\n57:57\nstuff that never actually going to go into the jet fighter, but they're going to be really, really helpful because it\n58:03\nallows all these separate people who are trying to write to this code to be able to get the code to do what they want so\n58:10\nthey can test their code, right? And that's going to help them once you actually start putting the plane\n58:15\ntogether and all these pieces talk to each other. You know, if you can have a\n58:20\nmissile and you can simulate what the cockpit does and then you can record\n58:26\nwhat the missile does, you can send that recording to the people who make the um the cockpit and they can say, \"Okay,\n58:32\nthis is what we're expecting to get from the the missile when when the missile is firing or when the missile is finding a\n58:38\nlock or whatever the missile does, right? And and this would go for almost all the\n58:44\nprojects I've talked about, like almost like always write a bunch of tools that\n58:49\nthat you can get your data out of your black boxes and and or your core boxes and and make them do things. Um at this\n58:57\npoint, um this black box doesn't actually know anything about aircraft,\n59:03\nright? It does it can't actually do anything. It doesn't do, you know, avionics. It doesn't do target tracking.\n59:09\nIt doesn't do it doesn't visualize anything. It it doesn't it doesn't do anything. It just passes data through it, right? And we're not actually giving\n59:17\naway anything secret here, right? So, this could actually be open source, right? You could give this away to anybody, right? You could put it on a\n59:24\nwebsite and says this, you know, we're not going to tell you how far our missile goes, but here's how our missile\n59:31\ntells the system how far it can go, right? And that means you can have all these contractors that can have these\n59:36\nmanuals and go out and try to build parts and you can have an open uh\n59:42\nbidding for making stuff that fits into this plane, right? And and that makes it\n59:47\na lot easier to to do things. Um because you you've removed all the secret stuff.\n59:53\nYou're just saying this is how we collaborate. Um but you know um um the\n59:59\nactual secrets and how it actually works that's up up to the end points and yes yes I know that no real military would\n1:00:07\never make anything you know um open source because they don't understand this kind of things. Um, so yeah, now\n1:00:15\npeople can add all these bits. Now people can add sensors and weapons and UIs and connectors and all kinds of\n1:00:20\nstuff, right? But then you say, well, this is a crappy system because now we\n1:00:25\nhave everything centralized. It's bad, bad, bad. Like what if, you know, somebody blows off this computer that is\n1:00:31\nrunning the core thing now everything is terrible. You know, the plane crashes, nothing works. That's true, right? So\n1:00:37\nthat's a requirement for a jet. Like jets have redundant systems. So you\n1:00:42\ncan't have like one central core where everything goes through, right? That wouldn't work. Well, you could easily\n1:00:50\nbuild multiple cores. The the thing here is that you can have any number of cores\n1:00:55\nthat sits on lots of different computers. You can have lots of interconnects between all these systems\n1:01:01\nthat are redundant and over redundant, but the subscribers get their\n1:01:06\ninformation through the same API. Right? So that means you can make a single core that's very simple to implement. You can\n1:01:13\nimplement that, give that to everybody. They can get started on their missiles and equipment and all this stuff and\n1:01:19\nthen you can spend three years making this advanced system that has multiple\n1:01:24\ncores that vote on which is one that can detect which one has been blown up and doesn't work. And you can build all that\n1:01:31\nand then you present to the same people here's the same API the same way you get the same information. It's a drop in\n1:01:36\nreplacement, right? But instead of waiting three years to get that, everybody could get it, you know, in six\n1:01:43\nmonths, right? And that's really, really core to this blackbox thinking. You can\n1:01:48\nredesign the inner core to be more complicated. And sometimes you do that, you know, because you figure things out\n1:01:56\nand sometimes you do it because you need to get product out. So this is this is exactly the same thing as we did with\n1:02:02\nthe text rendering. We started with simple text rendering but with the same API and then we made nice text rendering\n1:02:09\nafterwards but the users of that API didn't need to change anything because it just works right\n1:02:16\nokay so here's a cool thing you could put this in a tank now right it doesn't have to be in a plane it could be on\n1:02:21\nanything right if you now that you have connection between things you can connect multiple planes together they\n1:02:28\ncan share this information right so now instead of saying you know I got a radar lock because my radar found this enemy.\n1:02:34\nYou can have my neighbor, the other ship, you know, fighter found it or the ground radar found it or anything found\n1:02:41\nit. It doesn't matter, right? Because now you have a way to communicate about the state of the world, right? And\n1:02:47\nyou're obviously going to have lots of encryption and lots of things to control what you want to get in and out. But\n1:02:52\nreally, once you have a system like this, you can, you know, make it very generalized. It doesn't have to be in a fighter jet. It could be on transport\n1:02:59\njet. It could be, you know, on a tank. It could be on anything. And that means that now the people who make missiles,\n1:03:06\nthey may want to make a missile that can be launched from a tank and be launched from a plane and they have the same\n1:03:12\ninterconnect, right? they don't have to write two software stacks to control these two different things in two\n1:03:17\ndifferent um things and things become a lot more interconnected and even if\n1:03:22\nthere's going to be lots of differences you can actually have the same knowhow and people will know people can move\n1:03:29\nfrom different you know different projects and they know oh when I talk to the system this is the API this is how\n1:03:34\nyou talk even though the thing I'm doing now is completely different hardware-wise or capability wise from\n1:03:40\nthe last thing I was Okay, so let's wrap up. Um I've talked\n1:03:45\nfor a long time. Um so um this is really uh\n1:03:53\ncan I make this smaller? There we go. Um core to all software design in my opinion is format design. And format\n1:04:00\ndesign is something that isn't really taught and I wish people would teach it.\n1:04:06\nUh, I'm trying to write a really long article in a book about this because it's it's really is what we do as\n1:04:14\nsoftware developers and a lot of things are formats if you think about it. An API is a format. It's a format for\n1:04:21\nsending calls to some code. Files are a format. It's a format of how you store\n1:04:27\nthings in a file. Protocols like network is how do I store information in in a way that's a format. Programming\n1:04:34\nlanguages are formats. It's a way you store how you know instructions for a\n1:04:39\ncomputer and um it's also you know you write in that instruction language. It's\n1:04:45\na format of of what you can and what you cannot do in this way to describe in\n1:04:50\ninstructions. So formats are really important. There are some things you should think about.\n1:04:56\nOne is the difference between uh semantics and structure. Right? So\n1:05:01\nsometimes um you store semantics only. So for instance uh the metric system is\n1:05:07\nonly semantics. If I tell you 3 m everybody can figure out what 3 meters\n1:05:13\nis. But I'm not giving you you know how do I structure that? I gave you that through words that came in sound. That's\n1:05:21\nnot defined. You can write it down on a piece of paper. You can you know type it into a computer. Doesn't matter. A meter\n1:05:28\nis a meter. Right? We we describe what semantically it means but not\n1:05:33\nstructurally how we send it right and reversely you can think of something\n1:05:39\nlike JSON JSON is a format gives you a structure for storing data but doesn't tell you anything what that data means\n1:05:46\nthere has no semantic meaning it's an array of things but it doesn't say what those things are right so you need to\n1:05:53\nthink about these things and what you make semantic and what you make structure a lot of times you want to\n1:05:58\nhave a simple structure and then you can have more complicated semantics because then you can reuse\n1:06:05\ncode that reads uh the semantics right so JSON again a JSON loader can load any\n1:06:13\nJSON it can store healthcare data or you know weapons data or um or video editing\n1:06:20\ndata doesn't matter right semantics doesn't matter you can use the same loader for all these kinds of things and\n1:06:25\nthat's kind of useful right but it also has its limits because yeah you can load it but you can't really do anything with\n1:06:31\nit because you don't understand it right you don't know what it means and formats need to be implementable and\n1:06:38\nthis is really really key right it's like if you want all these people to\n1:06:43\ncome together and work if the API or the format is too complex it becomes really\n1:06:50\nreally hard right if I'm going to make a a UI and the data that I'm trying to\n1:06:55\nmake a UI for is super super complex text then I'm going to halfass it and I make a UI that can only display like\n1:07:02\nsimple stuff right and then you start getting incompatibilities right people\n1:07:07\nstart saying you know oh I I don't support those things and languages are a great example right the larger a\n1:07:13\nlanguage you have the the fewer implementations you get or the more bugs you get in your implementations or you\n1:07:20\nknow there's more things that you know more people can't read it it gets more and more complicated right smaller\n1:07:26\nformats are easier to implement and therefore the quality of implementation are generally better, right? So you want\n1:07:33\nto pack as much power as mo possible into a simple interface, right? A simple\n1:07:40\nformat. And that's the thing is is formats are are two-ended, right? It's like if you\n1:07:45\nsave a file, you have to load a file. If you send a network pack, you have to load a network package. And if you make\n1:07:52\na complicated API, u somebody has gonna have to use that complicated API, right?\n1:07:58\nSo it's like a language, right? So the more you make it complicated for your,\n1:08:05\nyou know, other people, you make it more complicated for yourself. And it it sort of squares a lot of times, right? If you\n1:08:11\nhave 10 different people and they each want a feature, you're going to get, you\n1:08:18\nknow, 10 features and now everybody has to implement this. And a very common thing is to say people say you know I\n1:08:25\nwish this file format um you know let's say we have polygons and nerves and some\n1:08:30\npeople think polygons are good and some people think nerbs are good and they say I wish this was nerbs and not you know\n1:08:38\nbut the problem is if you support both polygons and nerbs even if you want nerbs you're going to have to implement\n1:08:43\nnerbs and polygons and the other end is going to have to implement polygons and nerbs. So now both have to implement the\n1:08:49\nthe system they don't like and the system they do like, right? So everybody has to do more work and it's actually\n1:08:56\nbetter to just pick one of them and then some people are going to be less happy. But even if they're less happy, they\n1:09:02\nonly have to implement one thing. They don't have to implement two things. Even though, you know, it's better to\n1:09:08\nimplement one bad thing than implement one bad thing and a good thing. That's more work, right? So you really want to\n1:09:15\nmake it as small as possible. Um, so make choices. That's really important, right? Like a lot of people\n1:09:23\nwhen it comes to formats, it's like, look, my format can do a million things. And whenever I see that, that's like\n1:09:28\nyour format's going to fail because nobody's going to implement all those things, right? Um, so um, and also\n1:09:38\nmanage constraints like what can I require, what's the requirements of this format? If I know certain things, then\n1:09:45\nthat helps, right? If I know that all the data coming from the the core of the\n1:09:51\nfighter jet is in metric, that's great. I can, you know, do that. Or even if I\n1:09:56\ndon't like metric, maybe the core lets me choose and I know that I can be\n1:10:01\nguaranteed that it gives me feet if I want feet and and meters if I want meters and the core is going to handle\n1:10:09\nthat for me. That's great. I can rely on that. it's, you know, I don't have to think about it. Um,\n1:10:17\nthink about interactions. That's that's a very core thing. You know, if we're making a video editor, we have a\n1:10:22\ntimeline or do we have multiple timelines? Do we have a video stream or maybe want to support multiple video\n1:10:29\nstreams? Are are we supporting stereoscopic video or we maybe we want to have like video all around us like 50\n1:10:36\ndisplays at the same time. Can we edit that? Can we you know and and this is really important like how many\n1:10:42\ninteractions do you have right and it goes for almost everything like can you can can this fighter jet have one radar\n1:10:50\nor many radars or can it have a world view or can it have multiple world\n1:10:55\nviews? Can I you know should the pilot be able to pull up a world view from\n1:11:00\nanother plane? Is that a useful thing? Or do they live in the same world? Like who knows, right? These are things you\n1:11:07\nhave to decide and it's really easy to forget to to split them up and get too\n1:11:12\nlittle interaction but it's also really easy to have too many levels of interaction so it's like gets really\n1:11:18\nreally complicated to traverse and find the thing you want right\n1:11:23\num and then you want implementation freedom and I talked a little bit about that about the health care system you\n1:11:28\nwant to basically say this is how you talk to me about health care but how I implement healthare is none of your\n1:11:35\nbusiness Right? I there's many many different ways to build build a server farm that holds healthcare data and I\n1:11:41\nwant to be able to change that and I don't want to in my API say you know oh\n1:11:46\nyou can you know if my API has a a function that says oh you can send in\n1:11:51\nyour own SQL query right and I allow you to do that well then all sudden now I'm\n1:11:58\nrequired to have an SQL query language and if they start sending queries for\n1:12:04\ncertain properties. Those properties have to be in that SQL query and work.\n1:12:11\nAnd now I've locked myself into SQL on the back end. Right now I I'm screwed.\n1:12:16\nRight? And if I want to move to a backend that doesn't use SQL, game over,\n1:12:22\nright? So you really really want to make sure that that you you put locks between\n1:12:27\nthese things. And basically it's same thing with text rendering, right? You can do it as a bit map. You can do it as\n1:12:33\ncurves or polygons or whatever. The user just draws text. They don't have to know how it's implemented. So if you want to\n1:12:40\nchange our implementation approach in the future, we can do that.\n1:12:45\nOkay. Uh another big question is plug-in systems. So do you want a plug-in system where you plug yourself in or you get\n1:12:53\nplugged in? Right. So um I tend to think if you can make things that can get\n1:12:59\nplugged in that's good because um you don't want other system to dictate how\n1:13:06\nyour code works. And I I I said this for it's like you don't want to live in somebody else's world. You want to live\n1:13:12\nin your world and accept other people into your world. You don't want to go in somebody else's world and live in their\n1:13:18\nworld. So when you make a plugin that plugin lives in your world. it lives in the world of the the thing it plugs\n1:13:25\ninto, right? So, if you can make things that are not plugins, um, then that's a\n1:13:30\ngood thing. If you can make them as modules that are standalone that do not require to be plugged into something,\n1:13:37\nthat's a great thing. But a lot of times that's not possible. So, therefore, plug-in interfaces are often the right\n1:13:43\nright way to go. But uh if you can try to make things um that can be plugged in\n1:13:49\ncan be reused and plugged into other things. Um that's it. Um that's my talk. So I\n1:13:57\nwould definitely like to thank everybody for watching and um you can always find me on stream on Twitch uh or keels.com\n1:14:05\nor on my Twitter or all the other socials at Kelsar. Thank you for\n1:14:11\nwatching. Bye everybody."
  },
  {
    "path": "resources/usage-guide.md",
    "content": "# Usage Guide - AI Architecture Prompts\n\nA practical guide to applying Eskil Steenberg's black box architecture principles using AI tools for maximum development velocity.\n\n## 🎯 Quick Start Workflow\n\n### 1. Choose Your Scenario\n\n- **New Project** → Start with Claude Prompt (planning)\n- **Refactoring Existing Code** → Start with Claude Code Prompt\n- **Debugging/Testing Issues** → Use Cursor Prompt\n- **Architecture Review** → Use Claude Prompt\n\n### 2. Prepare Your Context (Recommended)\n\nExtract relevant code context using AI context tools:\n\n```bash\n# For JavaScript/TypeScript projects\nnpx repomix --include \"src/**/*.{js,ts,jsx,tsx}\" --output context.xml\n\n# For Python projects\ngit clone https://github.com/jimmc414/onefilellm.git\ncd onefilellm\npython onefilellm.py ./your-project/src/ --output context.xml\n\n# For specific folders only\nnpx repomix --include \"src/components/**\" --output component-context.xml\n```\n\n### 3. Apply the Appropriate Prompt\n\nCopy the relevant prompt from this repo and paste it into your AI tool, then include your context and specific question.\n\n## 📋 Detailed Usage Scenarios\n\n### Scenario 1: Planning a New Project\n\n**Tool**: Claude (Web/Desktop)  \n**Prompt**: `claude-prompt.md`\n\n**Example Session**:\n\n```\n[Paste Claude Prompt]\n\nI'm building a real-time chat application that needs to support:\n- Multiple message types (text, images, files)\n- User presence indicators\n- Message history persistence\n- Mobile and web clients\n\nCan you help me architect this using black box principles?\n```\n\n**What You'll Get**:\n\n- Module breakdown (MessageStore, PresenceManager, ClientAdapter, etc.)\n- Interface specifications between components\n- Risk assessment and mitigation strategies\n- Implementation roadmap with priorities\n- Team organization recommendations\n\n### Scenario 2: Refactoring Complex Code\n\n**Tool**: Claude Code  \n**Prompt**: `claude-code-prompt.md`\n\n**Example Session**:\n\n```\n[Paste Claude Code Prompt]\n\n[Attach context.xml from your project]\n\nThis React component has grown to 500+ lines with complex state management,\nDOM manipulation, and API calls all mixed together. How can I break this\ninto replaceable black box modules?\n```\n\n**What You'll Get**:\n\n- Identification of black box boundaries\n- Specific refactoring steps\n- New interface designs\n- Code examples for each module\n- Testing strategy for the refactored code\n\n### Scenario 3: Debugging and Testing Strategy\n\n**Tool**: Cursor  \n**Prompt**: `cursor-prompt.md`\n\n**Example Session**:\n\n```\n[Paste Cursor Prompt]\n\n[Include relevant code files]\n\nI have integration issues between my payment module and user authentication.\nThe tests pass individually but fail when used together. How should I debug\nthis using black box principles?\n```\n\n**What You'll Get**:\n\n- Debugging methodology for module boundaries\n- Test isolation strategies\n- Interface validation approaches\n- Mock/stub recommendations\n- Root cause analysis guidance\n\n## 🔧 Advanced Workflows\n\n### The Context + Prompt Combination\n\n**Most Powerful Approach**: Combine AI context extraction with architecture prompts\n\n1. **Extract Focused Context**\n\n   ```bash\n   # Focus on specific problem area\n   npx repomix --include \"src/auth/**\" --include \"src/payments/**\" --output modules-context.xml\n   ```\n\n2. **Apply Architecture Analysis**\n\n   ```\n   [Claude Code Prompt]\n\n   [Attach modules-context.xml]\n\n   These two modules are tightly coupled and causing issues.\n   How can I create clean black box interfaces between them?\n   ```\n\n3. **Implement Incrementally**\n   - Use the AI's suggestions to refactor one module at a time\n   - Maintain existing interfaces during transition\n   - Test each change in isolation\n\n### Multi-Stage Architecture Evolution\n\n**Stage 1: Strategic Planning** (Claude Prompt)\n\n- Define overall system architecture\n- Identify major module boundaries\n- Plan implementation phases\n\n**Stage 2: Implementation** (Claude Code Prompt)\n\n- Build individual modules\n- Create clean interfaces\n- Implement black box boundaries\n\n**Stage 3: Testing & Debugging** (Cursor Prompt)\n\n- Validate module interfaces\n- Debug integration issues\n- Optimize performance\n\n### The \"Folder Focus\" Method\n\nPerfect for large codebases:\n\n1. **Identify Problem Folder**\n\n   ```bash\n   # Extract context for specific folder\n   npx repomix --include \"src/components/editor/**\" --output editor-context.xml\n   ```\n\n2. **Analyze with Architecture Prompt**\n\n   ```\n   [Claude Code Prompt]\n   [Attach editor-context.xml]\n\n   This folder contains our text editor components. They're becoming\n   hard to maintain and test. How can I restructure this using\n   black box principles?\n   ```\n\n3. **Implement Suggested Changes**\n   - Refactor one component at a time\n   - Maintain backward compatibility\n   - Test interfaces thoroughly\n\n## 🎨 Prompt Customization Tips\n\n### Adapting for Your Domain\n\nAdd domain-specific context to any prompt:\n\n```markdown\n## Additional Context\n\nYou are working on a [HEALTHCARE/FINTECH/GAMING] application where:\n\n- [Specific regulatory requirements]\n- [Performance constraints]\n- [Security considerations]\n- [Integration requirements]\n\nApply black box principles while considering these domain constraints.\n```\n\n### Technology-Specific Adaptations\n\n**For React Projects**:\n\n```markdown\n## React-Specific Considerations\n\n- Components should be black boxes with clear prop interfaces\n- State management should be isolated within modules\n- Side effects should be contained and testable\n- Context should not leak implementation details\n```\n\n**For Backend APIs**:\n\n```markdown\n## API-Specific Considerations\n\n- Each endpoint should represent a clear business capability\n- Database interactions should be hidden behind service interfaces\n- External API dependencies should be wrapped and mockable\n- Error handling should be consistent across all modules\n```\n\n## 🚨 Common Pitfalls & Solutions\n\n### Pitfall 1: Over-Engineering\n\n**Problem**: Creating too many tiny modules  \n**Solution**: Use the \"one person rule\" - each module should be maintainable by one developer\n\n### Pitfall 2: Leaky Abstractions\n\n**Problem**: Interfaces that expose implementation details  \n**Solution**: Test if you could completely rewrite the implementation using only the interface\n\n### Pitfall 3: Context Overload\n\n**Problem**: Including too much code context, confusing the AI  \n**Solution**: Focus on specific folders or files relevant to your question\n\n### Pitfall 4: Ignoring Dependencies\n\n**Problem**: Not considering how modules connect  \n**Solution**: Always ask about interface design and integration points\n\n## 📊 Measuring Success\n\n### Before/After Metrics\n\nTrack these improvements:\n\n- **Lines of code per module** - should decrease\n- **Interface complexity** - fewer public methods/functions\n- **Test isolation** - can modules be tested independently?\n- **Replacement difficulty** - how hard is it to rewrite a module?\n- **Developer onboarding** - how quickly can new devs contribute?\n\n### Architecture Quality Checklist\n\nAfter applying the prompts, verify:\n\n- [ ] Each module has a single, clear responsibility\n- [ ] Interfaces are documented and obvious to use\n- [ ] Implementation details are completely hidden\n- [ ] Modules can be tested without knowing internals\n- [ ] External dependencies are wrapped, not used directly\n- [ ] Any module could be rewritten using only its interface\n\n## 🔄 Iteration Strategy\n\n### Continuous Architecture Improvement\n\n1. **Weekly Architecture Reviews**\n\n   - Pick one module that's causing friction\n   - Apply the appropriate prompt\n   - Implement one suggested improvement\n\n2. **New Feature Integration**\n\n   - Before building new features, use Claude Prompt for planning\n   - Ensure new code follows black box principles\n   - Update existing interfaces if needed\n\n3. **Bug-Driven Refactoring**\n   - When bugs occur, use Cursor Prompt to understand root cause\n   - Often bugs indicate poor module boundaries\n   - Fix the architecture, not just the symptom\n\n## 💡 Pro Tips\n\n### Combining with Other Tools\n\n- **Use with GitHub Copilot**: Let Copilot generate code, then use these prompts to structure it properly\n- **Integration with IDEs**: Keep prompt snippets in your IDE for quick access\n- **Documentation**: Use the architectural insights to improve your README and API docs\n\n### Team Collaboration\n\n- **Share Architecture Decisions**: Use Claude Prompt outputs as design documents\n- **Code Review Focus**: Review interfaces and module boundaries, not just implementation\n- **Onboarding**: New team members can use these prompts to understand the codebase architecture\n\n### Long-term Maintenance\n\n- **Architecture Debt**: Regularly review and refactor using these prompts\n- **Technology Migration**: Black box architecture makes it easier to migrate technologies\n- **Scaling Preparation**: Well-architected modules handle growth better\n\nRemember: The goal isn't perfect architecture immediately, but architecture that stays maintainable as your project grows. Use these prompts iteratively to continuously improve your codebase structure.\n"
  }
]