{"id":30773480,"url":"https://github.com/lablnet/flexi","last_synced_at":"2026-04-12T11:49:24.314Z","repository":{"id":311272846,"uuid":"1043062109","full_name":"lablnet/Flexi","owner":"lablnet","description":"A minimal reactive framework built for learning purposes to understand how modern frontend frameworks like Vue.js and React work under the hood. Flexi demonstrates the core concepts of reactivity and virtual DOM diffing.","archived":false,"fork":false,"pushed_at":"2025-08-23T12:39:40.000Z","size":28,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-23T18:31:24.060Z","etag":null,"topics":["algorithm","diffing","diffing-algorithm","dom","flexi","framework","javascript","proxy","reactive","vdom","vue"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lablnet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"patreon":"lablnet"}},"created_at":"2025-08-23T04:16:09.000Z","updated_at":"2025-08-23T12:39:43.000Z","dependencies_parsed_at":"2025-08-23T18:41:32.609Z","dependency_job_id":null,"html_url":"https://github.com/lablnet/Flexi","commit_stats":null,"previous_names":["lablnet/flexi"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/lablnet/Flexi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lablnet%2FFlexi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lablnet%2FFlexi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lablnet%2FFlexi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lablnet%2FFlexi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lablnet","download_url":"https://codeload.github.com/lablnet/Flexi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lablnet%2FFlexi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273699712,"owners_count":25152285,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-04T02:00:08.968Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algorithm","diffing","diffing-algorithm","dom","flexi","framework","javascript","proxy","reactive","vdom","vue"],"created_at":"2025-09-05T01:52:19.549Z","updated_at":"2026-04-12T11:49:24.309Z","avatar_url":"https://github.com/lablnet.png","language":"TypeScript","readme":"# Flexi - A Lightweight Reactive Framework\n\nA minimal reactive framework built for learning purposes to understand how modern frontend frameworks like Vue.js and React work under the hood. Flexi demonstrates the core concepts of reactivity and virtual DOM diffing.\n\n## 🎯 Learning Objectives\n\nThis project is designed to help you understand:\n\n- **Reactivity System**: How automatic dependency tracking and re-rendering works\n- **Virtual DOM**: How VDOM diffing and patching algorithms function\n- **Component Lifecycle**: How frameworks manage component updates\n- **State Management**: How reactive state triggers UI updates\n\n## 🚀 Quick Start\n\n### Installation\n\n```bash\n# Clone the repository\ngit clone \u003cyour-repo-url\u003e\ncd Flexi\n\n# Install dependencies\npnpm install\n\n# Start development server\npnpm dev\n```\n\n### Basic Usage\n\n```typescript\nimport { Flexi } from \"./src/index\";\nimport { h } from \"./src/vdom\";\n\nconst app = new Flexi({\n  el: \"#app\",\n  state: { count: 0 },\n  render: (state) =\u003e\n    h(\"div\", { class: \"counter\" }, [\n      h(\"h1\", {}, [`Count: ${state.count}`]),\n      h(\"button\", { onClick: () =\u003e state.count++ }, [\"Increment\"]),\n      h(\"button\", { onClick: () =\u003e state.count-- }, [\"Decrement\"]),\n    ]),\n});\n```\n\n## 📚 Core Concepts Explained\n\n### 1. Reactivity System (`src/reactivity.ts`)\n\nThe reactivity system is the heart of modern frameworks. It automatically tracks dependencies and re-runs effects when data changes.\n\n#### Key Concepts:\n- **Reactive Objects**: Wrapped with `Proxy` to intercept property access\n- **Dependency Tracking**: Uses `Map` and `Set` to track which effects depend on which properties\n- **Effect System**: `autorun` function that automatically re-executes when dependencies change\n\n```typescript\n// How it works internally:\nconst state = reactive({ count: 0 });\n\nautorun(() =\u003e {\n  console.log(`Count is: ${state.count}`); // Automatically tracks state.count\n});\n\nstate.count++; // Automatically triggers the effect above\n```\n\n#### Learning Points:\n- **Proxy API**: How JavaScript proxies enable reactive behavior\n- **Dependency Collection**: How frameworks know what to re-run\n\n### 2. Virtual DOM (`src/vdom.ts`)\n\nVirtual DOM is an abstraction over the real DOM that enables efficient updates.\n\n#### Key Concepts:\n- **VNode Structure**: Lightweight representation of DOM elements\n- **Hyperscript Function**: `h()` function for creating VNodes\n- **Element Creation**: Converting VNodes to real DOM elements\n\n```typescript\n// VNode structure:\ninterface VNode {\n  tag: string;\n  props: Record\u003cstring, any\u003e;\n  children: Array\u003cVNode | string\u003e;\n}\n\n// Creating VNodes:\nconst vnode = h(\"div\", { class: \"container\" }, [\n  h(\"h1\", {}, [\"Hello World\"]),\n  h(\"button\", { onClick: handleClick }, [\"Click me\"])\n]);\n```\n\n#### Learning Points:\n- **DOM Abstraction**: Why VDOM exists and its benefits\n- **Element Creation**: How VNodes become real DOM elements\n- **Props Handling**: How attributes and event handlers are applied\n\n### 3. Diffing and Patching (`src/patch.ts`)\n\nThe diffing algorithm compares old and new VNodes to determine the minimal DOM updates needed.\n\n#### Key Concepts:\n- **Tree Diffing**: Comparing VNode trees efficiently\n- **Keyed Updates**: Optimizing list updates\n- **DOM Patching**: Applying changes to the real DOM\n\n```typescript\n// The patch function signature:\npatch(parent: Node, oldNode: VNode | string | null, newNode: VNode | string)\n```\n\n#### Learning Points:\n- **Diffing Strategies**: How to efficiently compare trees\n- **Update Batching**: Minimizing DOM operations\n- **Error Handling**: Dealing with DOM structure mismatches\n\n## 🏗️ Architecture Overview\n\n```\nsrc/\n├── index.ts          # Main framework class\n├── reactivity.ts     # Reactive state management\n├── vdom.ts          # Virtual DOM implementation\n└── patch.ts         # Diffing and patching algorithm\n```\n\n### Framework Flow\n\n1. **Initialization**: Create reactive state and render initial VDOM\n2. **Dependency Tracking**: `autorun` tracks which state properties are accessed\n3. **State Changes**: When state changes, effects are automatically triggered\n4. **Re-rendering**: New VDOM tree is created from current state\n5. **Diffing**: Old and new VDOM trees are compared\n6. **Patching**: Minimal DOM updates are applied\n\n## 📖 Examples\n\n### Counter Example (`examples/counter.ts`)\n\nA simple counter demonstrating basic reactivity:\n\n```typescript\nconst app = new Flexi({\n  el: \"#app\",\n  state: { count: 0 },\n  render: (state) =\u003e\n    h(\"div\", { class: \"counter\" }, [\n      h(\"h1\", {}, [`Count: ${state.count}`]),\n      h(\"button\", { onClick: () =\u003e state.count++ }, [\"Increment\"]),\n      h(\"button\", { onClick: () =\u003e state.count-- }, [\"Decrement\"]),\n    ]),\n});\n```\n\n### Todo List Example\n\n```typescript\nconst app = new Flexi({\n  el: \"#app\",\n  state: { \n    todos: [],\n    newTodo: \"\"\n  },\n  render: (state) =\u003e\n    h(\"div\", { class: \"todo-app\" }, [\n      h(\"input\", {\n        value: state.newTodo,\n        onInput: (e) =\u003e state.newTodo = e.target.value\n      }, []),\n      h(\"button\", {\n        onClick: () =\u003e {\n          if (state.newTodo.trim()) {\n            state.todos.push(state.newTodo);\n            state.newTodo = \"\";\n          }\n        }\n      }, [\"Add Todo\"]),\n      h(\"ul\", {}, \n        state.todos.map(todo =\u003e h(\"li\", {}, [todo]))\n      )\n    ]),\n});\n```\n\n## 🔧 Development\n\n### Running Examples\n\n```bash\n# Start development server\npnpm dev\n\n# Build for production\npnpm build\n```\n\n### Project Structure\n\n```\nFlexi/\n├── src/              # Core framework code\n├── examples/         # Example applications\n├── dist/            # Built files\n└── package.json     # Dependencies and scripts\n```\n\n## 🧠 Deep Dive: How It All Works Together\n\n### 1. State Changes Trigger Updates\n\n```typescript\n// When you do this:\nstate.count++;\n\n// Here's what happens internally:\n// 1. Proxy intercepts the set operation\n// 2. Notifies all effects that depend on 'count'\n// 3. Triggers re-render\n// 4. Creates new VDOM tree\n// 5. Diffs with old tree\n// 6. Patches DOM with minimal changes\n```\n\n### 2. Dependency Tracking in Action\n\n```typescript\nautorun(() =\u003e {\n  // This effect depends on state.count\n  console.log(state.count);\n  \n  // And this effect depends on state.name\n  console.log(state.name);\n});\n\n// When state.count changes, only the first console.log re-runs\n// When state.name changes, only the second console.log re-runs\n```\n\n### 3. VDOM Diffing Process\n\n```typescript\n// Old VDOM:\nh(\"div\", {}, [h(\"span\", {}, [\"Hello\"])])\n\n// New VDOM:\nh(\"div\", {}, [h(\"span\", {}, [\"World\"])])\n\n// Diffing result:\n// - Same tag (div) ✓\n// - Same tag (span) ✓\n// - Different text content → Update textContent\n```\n\n## 🗺️ Roadmap\n\nThis roadmap outlines planned features and enhancements for the Flexi framework. Each item represents a learning opportunity to understand how modern frameworks work.\n\n### Core Framework Enhancements\n\n#### Reactivity System\n- [x] Basic reactive objects with Proxy\n- [x] Dependency tracking with Simple Map and Set\n- [x] Autorun effects\n- [ ] **Computed Properties**: Derived state that automatically updates\n- [ ] **Watchers**: React to specific state changes\n- [ ] **Reactive Arrays**: Special handling for array mutations\n- [ ] **Deep Reactivity**: Nested object reactivity\n- [ ] **Reactive Maps and Sets**: Collection reactivity\n\n#### Virtual DOM Improvements\n- [x] Basic VNode structure\n- [x] Hyperscript function (h)\n- [ ] **Fragment Support**: Multiple root elements\n- [ ] **Portal Support**: Render outside component tree\n- [ ] **Suspense**: Async component loading\n- [ ] **Error Boundaries**: Error handling components\n\n#### Diffing and Patching\n- [x] Basic tree diffing\n- [ ] **Keyed Lists**: Optimized list rendering\n- [ ] **Component Diffing**: Smart component updates\n- [ ] **Batch Updates**: Reduce DOM operations\n- [ ] **Async Rendering**: Non-blocking updates\n\n### Template Engine\n\n#### Template Compilation\n- [ ] **Template Parser**: Parse HTML-like templates\n- [ ] **AST Generation**: Abstract Syntax Tree for templates\n- [ ] **Code Generation**: Convert templates to render functions\n- [ ] **Directive Support**: f-if, f-for, f-model, etc.\n\n#### Template Features\n- [ ] **Conditional Rendering**: `f-if` and `f-else`\n- [ ] **List Rendering**: `f-for` with keys\n- [ ] **Two-way Binding**: `f-model` for forms\n- [ ] **Event Handling**: `@click`, `@input`, etc.\n- [ ] **Class and Style Binding**: Dynamic styling\n- [ ] **Slot System**: Content projection\n\n### Component System\n\n#### Component Architecture\n- [ ] **Component Definition**: Reusable component structure\n- [ ] **Props System**: Parent-child communication\n- [ ] **Emit System**: Child-parent communication\n- [ ] **Component Lifecycle**: mounted, updated, unmounted\n- [ ] **Component Registration**: Global and local components\n\n#### Advanced Components\n- [ ] **Higher-Order Components**: Component composition\n- [ ] **Render Props**: Function as children pattern\n- [ ] **Context API**: Cross-component state sharing\n- [ ] **Provider Pattern**: Dependency injection\n\n### State Management\n\n#### Local State\n- [x] Reactive state objects\n- [ ] **State Composition**: Combining multiple state sources\n- [ ] **State Persistence**: LocalStorage integration\n- [ ] **State Validation**: Schema validation\n\n#### Global State\n- [ ] **Store Pattern**: Centralized state management\n- [ ] **Actions and Mutations**: Predictable state changes\n- [ ] **State Subscriptions**: React to global changes\n- [ ] **State DevTools**: Debugging and time-travel\n\n### Performance Optimizations\n\n#### Rendering Optimizations\n- [ ] **Memoization**: Prevent unnecessary re-renders\n- [ ] **Lazy Loading**: Code splitting and dynamic imports\n- [ ] **Virtual Scrolling**: Large list optimization\n- [ ] **Tree Shaking**: Remove unused code\n\n#### Memory Management\n- [ ] **Garbage Collection**: Proper cleanup of effects\n- [ ] **Memory Leak Prevention**: Component cleanup\n- [ ] **Weak References**: Prevent memory leaks\n\n### Developer Experience\n\n#### Development Tools\n- [ ] **Hot Module Replacement**: Fast development cycles\n- [ ] **Source Maps**: Debug original code\n- [ ] **Error Overlay**: Better error reporting\n- [ ] **Performance Profiling**: Identify bottlenecks\n\n#### Debugging\n- [ ] **Reactivity Inspector**: Visualize dependency graph\n- [ ] **VDOM Inspector**: Examine virtual DOM structure\n- [ ] **State Inspector**: Monitor state changes\n- [ ] **Timeline**: Track render cycles\n\n### Build System\n\n#### Bundling\n- [ ] **Module Bundler**: Rollup/Vite integration\n- [ ] **Tree Shaking**: Remove dead code\n- [ ] **Code Splitting**: Dynamic imports\n- [ ] **Asset Optimization**: CSS, images, fonts\n\n#### Build Features\n- [ ] **TypeScript Support**: Full type safety\n- [ ] **JSX Support**: Alternative to hyperscript\n- [ ] **CSS-in-JS**: Scoped styles\n- [ ] **Static Analysis**: Linting and formatting\n\n### Testing Framework\n\n#### Unit Testing\n- [ ] **Component Testing**: Test individual components\n- [ ] **Reactivity Testing**: Test reactive behavior\n- [ ] **VDOM Testing**: Test virtual DOM operations\n- [ ] **Mock System**: Mock dependencies\n\n#### Integration Testing\n- [ ] **End-to-End Testing**: Full application testing\n- [ ] **Visual Regression**: UI consistency testing\n- [ ] **Performance Testing**: Benchmark rendering\n\n### Documentation and Examples\n\n#### Learning Materials\n- [ ] **Interactive Tutorials**: Step-by-step guides\n- [ ] **Code Sandbox**: Online playground\n- [ ] **Video Tutorials**: Visual learning\n- [ ] **Best Practices**: Framework conventions\n\n#### Example Applications\n- [ ] **Todo App**: Basic CRUD operations\n- [ ] **Shopping Cart**: State management\n- [ ] **Real-time Chat**: WebSocket integration\n- [ ] **Dashboard**: Complex UI patterns\n- [ ] **Game**: Interactive applications\n\n### Ecosystem\n\n#### Plugins and Extensions\n- [ ] **Plugin System**: Extensible architecture\n- [ ] **Router**: Client-side routing\n- [ ] **HTTP Client**: API integration\n- [ ] **Form Validation**: Input validation\n- [ ] **Animation**: Transition system\n\n#### Community\n- [ ] **Package Registry**: Share components\n- [ ] **Template Gallery**: Pre-built templates\n- [ ] **Community Examples**: User contributions\n- [ ] **Documentation Site**: Comprehensive docs\n\n---\n\n### Progress Tracking\n\n**Current Status**: 🟡 In Progress (Core features implemented)\n\n**Next Milestone**: Template Engine and Component System\n\n**Estimated Completion**: Q3 2025\n\n---\n\n## 🎓 Learning Resources\n\nTo better understand the concepts implemented here:\n\n- **Reactivity**: Read about Vue 3's Composition API and React's useState\n- **Virtual DOM**: Study React's reconciliation algorithm\n- **Diffing**: Learn about the diffing strategies used in React and Vue\n- **Proxy API**: MDN documentation on JavaScript Proxies\n\n## 🤝 Contributing\n\nThis is a learning project! Feel free to:\n\n- Add more examples\n- Implement additional features (computed properties, watchers, etc.)\n- Improve the diffing algorithm\n- Add tests\n- Document more learning concepts\n\n## 📄 License\n\nMIT License - feel free to use this for learning and experimentation!\n\n---\n\n**Happy Learning! 🚀**\n\nThis framework demonstrates the fundamental concepts that power modern frontend frameworks. Understanding these concepts will make you a better developer and help you appreciate the complexity and elegance of frameworks like React, Vue, and Svelte.\n","funding_links":["https://patreon.com/lablnet"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flablnet%2Fflexi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flablnet%2Fflexi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flablnet%2Fflexi/lists"}