{"_id":"@bernotieno/mini-framework","_rev":"2-2fc222b300e46e0ac707a3fcafe9cc1a","name":"@bernotieno/mini-framework","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@bernotieno/mini-framework","version":"1.0.0","keywords":["javascript","framework","virtual-dom","state-management","routing","zero-dependencies","es-modules","reactive","component-system","spa","frontend"],"author":{"name":"Mini Framework Team"},"license":"MIT","_id":"@bernotieno/mini-framework@1.0.0","maintainers":[{"name":"bernotieno","email":"bernadokumu1@gmail.com"}],"homepage":"https://github.com/bernotieno/mini-framework#readme","bugs":{"url":"https://github.com/bernotieno/mini-framework/issues"},"dist":{"shasum":"ef59861da6d58252c3e550d2895aa944bb0de9dc","tarball":"https://registry.npmjs.org/@bernotieno/mini-framework/-/mini-framework-1.0.0.tgz","fileCount":10,"integrity":"sha512-VzLFg3yKxhm5oz/Gc7UvdBI8OXeWvUrLqrXm8AuPhoB+wCh4p8o9XQBDiXzsejElXjV3xdFR3RX6LWwzXqxz7Q==","signatures":[{"sig":"MEUCIFcGdCKQIvunKUnRAOA+szfAbFZonHOh+j+hicbL3czXAiEAhnPx1YOGmrmQLceGFpVnkQWOm8TFfdNyBJKX6hMk1lY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":93396},"main":"src/framework.js","type":"module","module":"src/framework.js","engines":{"node":">=14.0.0"},"exports":{".":{"types":"./types/index.d.ts","import":"./src/framework.js"},"./utils":{"import":"./src/utils.js"},"./core/*":{"import":"./src/core/*.js"}},"scripts":{"dev":"npx http-server -p 3000 -c-1","test":"echo \"Tests coming soon\" && exit 0","build":"echo \"No build step required - pure ES modules\" && exit 0","start":"npm run dev","version":"npm run build && git add -A src","postversion":"git push && git push --tags","prepublishOnly":"npm test"},"_npmUser":{"name":"bernotieno","email":"bernadokumu1@gmail.com"},"repository":{"url":"git+https://github.com/bernotieno/mini-framework.git","type":"git"},"_npmVersion":"8.5.1","description":"A lightweight JavaScript framework built from scratch with zero dependencies","directories":{},"_nodeVersion":"12.22.9","dependencies":{},"_hasShrinkwrap":false,"devDependencies":{"http-server":"^14.1.1"},"_npmOperationalInternal":{"tmp":"tmp/mini-framework_1.0.0_1749208709340_0.3440900260839599","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@bernotieno/mini-framework","version":"1.1.0","description":"A lightweight JavaScript framework built from scratch with zero dependencies","main":"src/framework.js","module":"src/framework.js","type":"module","exports":{".":{"import":"./src/framework.js","types":"./types/index.d.ts"},"./core/*":{"import":"./src/core/*.js"},"./utils":{"import":"./src/utils.js"}},"scripts":{"dev":"npx http-server -p 3000 -c-1","start":"npm run dev","test":"echo \"Tests coming soon\" && exit 0","build":"echo \"No build step required - pure ES modules\" && exit 0","prepublishOnly":"npm test","version":"npm run build && git add -A src","postversion":"git push && git push --tags"},"keywords":["javascript","framework","virtual-dom","state-management","routing","zero-dependencies","es-modules","reactive","component-system","spa","frontend"],"author":{"name":"Mini Framework Team"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/bernotieno/mini-framework.git"},"bugs":{"url":"https://github.com/bernotieno/mini-framework/issues"},"homepage":"https://github.com/bernotieno/mini-framework#readme","engines":{"node":">=14.0.0"},"devDependencies":{"http-server":"^14.1.1"},"dependencies":{},"gitHead":"d82fb373b65d6277b2faa6411b92021a0add1e02","_id":"@bernotieno/mini-framework@1.1.0","_nodeVersion":"12.22.9","_npmVersion":"8.5.1","dist":{"integrity":"sha512-87URyt3x5+aVW6NiSZYHExvH1rSR7oP89wBe/MMhg4Z+969Zz5K4/G/D6Ro7HPucsLs1rh1xMr876NdMO+zLyg==","shasum":"8e7d2d1bcbb3dc93c654c45995c77c0deec6eccf","tarball":"https://registry.npmjs.org/@bernotieno/mini-framework/-/mini-framework-1.1.0.tgz","fileCount":30,"unpackedSize":92788,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQD+k3LFmHGKtmq4Duvsl6cqNnNEqo/76P2P4YmJRbMpfAIhAK4KzsbXWYjS1gjWFMjgVw4fVfQXsPehCPaMVAIwuT3g"}]},"_npmUser":{"name":"bernotieno","email":"bernadokumu1@gmail.com"},"directories":{},"maintainers":[{"name":"bernotieno","email":"bernadokumu1@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mini-framework_1.1.0_1749212455307_0.2078626985033707"},"_hasShrinkwrap":false}},"time":{"created":"2025-06-06T11:18:29.233Z","modified":"2025-06-06T12:20:55.657Z","1.0.0":"2025-06-06T11:18:29.579Z","1.1.0":"2025-06-06T12:20:55.475Z"},"bugs":{"url":"https://github.com/bernotieno/mini-framework/issues"},"author":{"name":"Mini Framework Team"},"license":"MIT","homepage":"https://github.com/bernotieno/mini-framework#readme","keywords":["javascript","framework","virtual-dom","state-management","routing","zero-dependencies","es-modules","reactive","component-system","spa","frontend"],"repository":{"type":"git","url":"git+https://github.com/bernotieno/mini-framework.git"},"description":"A lightweight JavaScript framework built from scratch with zero dependencies","maintainers":[{"name":"bernotieno","email":"bernadokumu1@gmail.com"}],"readme":"# Mini Framework\n\nA lightweight, zero-dependency JavaScript framework built from scratch. Mini Framework provides all the essential features you need to build modern web applications without the bloat of larger frameworks.\n\n## Features\n\n- 🎯 **Virtual DOM** - Efficient DOM rendering and updates\n- 🎪 **Custom Event System** - Pub-sub pattern without addEventListener\n- 🔄 **Reactive State Management** - Global state with automatic UI updates\n- 🛣️ **Client-side Routing** - Hash and history-based navigation\n- 📦 **Zero Dependencies** - No external libraries required\n- 🧩 **Component System** - Reusable UI components\n- 💾 **Local Storage Integration** - Built-in persistence helpers\n- 🔧 **Utility Functions** - Common helpers included\n\n## Installation\n\n### NPM Installation\n\n```bash\nnpm install @bernotieno/mini-framework\n```\n\n### CDN Usage\n\n```html\n<script type=\"module\">\n  import { createApp, h, defineComponent } from 'https://unpkg.com/@bernotieno/mini-framework/src/framework.js';\n  // Your app code here\n</script>\n```\n\n## Quick Start\n\n### Using NPM\n\n```javascript\nimport { createApp, defineComponent, h } from '@bernotieno/mini-framework';\n\nconst HelloWorld = defineComponent({\n  render() {\n    return h('div', {}, [\n      h('h1', {}, 'Hello, Mini Framework!'),\n      h('p', {}, 'Built with zero dependencies')\n    ]);\n  }\n});\n\nconst app = createApp();\nconst component = new HelloWorld();\ncomponent.mount(document.getElementById('app'));\n```\n\n### Development Setup\n\n1. Clone this repository\n2. Install dependencies: `npm install`\n3. Start development server: `npm run dev`\n4. Open `http://localhost:3000/examples/todomvc/` to see the TodoMVC demo\n\n## How the Framework Works\n\nMini Framework is built from scratch using vanilla JavaScript with zero dependencies. Here's how each core system works internally:\n\n### Architecture Overview\n\nThe framework consists of four main modules:\n\n1. **Virtual DOM Engine** (`src/core/dom.js`) - Converts JSON-like structures to real DOM elements\n2. **Event System** (`src/core/events.js`) - Custom pub-sub pattern replacing addEventListener\n3. **State Management** (`src/core/state.js`) - Reactive state store with automatic UI updates\n4. **Router** (`src/core/router.js`) - Client-side navigation with URL synchronization\n\n### Virtual DOM Implementation\n\nThe Virtual DOM system works by:\n1. Creating lightweight JavaScript objects representing DOM structure\n2. Rendering these objects to real DOM elements when needed\n3. Providing a simple `h()` function for element creation\n4. Supporting nested elements, attributes, and event handlers\n\n### Event System Architecture\n\nInstead of relying on `addEventListener`, the framework implements:\n1. A custom EventEmitter class with pub-sub pattern\n2. DOM event delegation for efficient event handling\n3. Declarative event binding through element attributes\n4. Global event communication between components\n\n### Reactive State Management\n\nThe state system provides:\n1. Global state store with dot-notation path access\n2. Automatic subscriber notification on state changes\n3. Component-level state isolation\n4. Action pattern for complex state mutations\n\n### Router Implementation\n\nThe routing system handles:\n1. URL parsing and route matching with parameters\n2. History API integration for clean URLs\n3. Hash-based fallback for broader compatibility\n4. Navigation hooks for route guards and side effects\n\n## Core Concepts\n\n### 1. Virtual DOM\n\nThe framework uses a JSON-like structure to represent DOM elements:\n\n```javascript\nimport { h, vdom } from '@bernotieno/mini-framework';\n\n// Create virtual DOM elements\nconst element = h('div', { class: 'container' }, [\n    h('h1', {}, 'Hello World'),\n    h('p', { id: 'description' }, 'This is a paragraph')\n]);\n\n// Mount to real DOM\nvdom.mount(element, document.getElementById('app'));\n```\n\n#### Virtual DOM Structure\n\n```javascript\n{\n    tag: 'div',\n    attrs: { class: 'example', id: 'my-div' },\n    children: [\n        'Text content',\n        {\n            tag: 'span',\n            attrs: { style: 'color: red' },\n            children: ['Nested content']\n        }\n    ]\n}\n```\n\n### 2. Custom Event System\n\nInstead of `addEventListener`, the framework uses a custom pub-sub event system:\n\n```javascript\nimport { eventEmitter, domEvents } from '@bernotieno/mini-framework';\n\n// Global event emitter\neventEmitter.on('custom-event', (data) => {\n    console.log('Event received:', data);\n});\n\neventEmitter.emit('custom-event', { message: 'Hello!' });\n\n// DOM event binding\nconst element = document.querySelector('#my-button');\ndomEvents.bind(element, 'click', (e) => {\n    console.log('Button clicked!');\n});\n\n// Declarative event binding\ndomEvents.bindEvents(element, {\n    click: () => console.log('Clicked!'),\n    mouseover: () => console.log('Hovered!')\n});\n```\n\n### 3. Reactive State Management\n\nGlobal state that automatically triggers UI updates:\n\n```javascript\nimport { globalState, subscribeToState } from '@bernotieno/mini-framework';\n\n// Set state\nglobalState.set('user', { name: 'John', age: 30 });\nglobalState.set('user.name', 'Jane'); // Nested updates\n\n// Get state\nconst user = globalState.get('user');\nconst userName = globalState.get('user.name');\n\n// Subscribe to changes\nconst unsubscribe = subscribeToState('user', (user) => {\n    console.log('User changed:', user);\n});\n\n// Update with function\nglobalState.update('user.age', age => age + 1);\n\n// Actions for complex state changes\nconst userActions = {\n    updateProfile: globalState.action('updateProfile', (state, newData) => {\n        state.set('user', { ...state.get('user'), ...newData });\n    })\n};\n```\n\n### 4. Client-side Routing\n\nSimple routing with URL synchronization:\n\n```javascript\nimport { router } from '@bernotieno/mini-framework';\n\n// Define routes\nrouter.route('/', () => {\n    console.log('Home page');\n});\n\nrouter.route('/users/:id', (route) => {\n    console.log('User ID:', route.params.id);\n});\n\nrouter.route('/products', () => {\n    console.log('Products page');\n});\n\n// Navigate programmatically\nrouter.navigate('/users/123');\nrouter.navigate('/products', { replace: true });\n\n// Navigation hooks\nrouter.beforeEach((to, from) => {\n    console.log(`Navigating from ${from} to ${to}`);\n    return true; // Return false to cancel navigation\n});\n\nrouter.afterEach((to, from) => {\n    console.log('Navigation completed');\n});\n```\n\n## Component System\n\nCreate reusable components using the `defineComponent` function:\n\n```javascript\nimport { defineComponent, h } from '@bernotieno/mini-framework';\n\nconst UserCard = defineComponent({\n    // Initial component state\n    state: {\n        expanded: false\n    },\n\n    // Lifecycle hooks\n    afterMount() {\n        console.log('Component mounted');\n    },\n\n    beforeUnmount() {\n        console.log('Component will unmount');\n    },\n\n    // Methods\n    toggleExpanded() {\n        this.setState('expanded', !this.getState('expanded'));\n    },\n\n    // Render method\n    render() {\n        const { user } = this.props;\n        const expanded = this.getState('expanded');\n\n        return h('div', { class: 'user-card' }, [\n            h('h3', {}, user.name),\n            h('button', {\n                onclick: () => this.toggleExpanded()\n            }, expanded ? 'Collapse' : 'Expand'),\n            expanded ? h('div', { class: 'details' }, [\n                h('p', {}, `Age: ${user.age}`),\n                h('p', {}, `Email: ${user.email}`)\n            ]) : null\n        ]);\n    }\n});\n\n// Use the component\nconst userCard = new UserCard({ user: { name: 'John', age: 30, email: 'john@example.com' } });\nuserCard.mount(document.getElementById('container'));\n```\n\n## Application Setup\n\nCreate and initialize your application:\n\n```javascript\nimport { createApp } from '@bernotieno/mini-framework';\n\nconst app = createApp({\n    routes: {\n        '/': () => console.log('Home'),\n        '/about': () => console.log('About'),\n        '/contact': () => console.log('Contact')\n    }\n});\n\n// Initialize the app\napp.init(document.getElementById('app'));\n\n// Register components\napp.component('UserCard', UserCard);\n\n// Create component instances\nconst userCard = app.createComponent('UserCard', { user: userData });\n```\n\n## Utility Functions\n\nThe framework includes helpful utility functions:\n\n```javascript\nimport { debounce, throttle, storage, validators } from '@bernotieno/mini-framework';\n\n// Debounce function calls\nconst debouncedSearch = debounce((query) => {\n    console.log('Searching for:', query);\n}, 300);\n\n// Throttle function calls\nconst throttledScroll = throttle(() => {\n    console.log('Scrolling...');\n}, 100);\n\n// Local storage helpers\nstorage.set('user', { name: 'John' });\nconst user = storage.get('user');\nstorage.remove('user');\n\n// Validation\nconst isValidEmail = validators.email('test@example.com'); // true\nconst isRequired = validators.required(''); // false\nconst hasMinLength = validators.minLength(5)('hello'); // true\n```\n\n## Event Handling Examples\n\n### Basic Event Binding\n\n```javascript\n// In component render method\nh('button', {\n    onclick: (e) => {\n        console.log('Button clicked!');\n        e.preventDefault();\n        e.stopPropagation();\n    }\n}, 'Click me')\n\n// Multiple events\nh('input', {\n    oninput: (e) => this.setState('value', e.target.value),\n    onkeydown: (e) => {\n        if (e.originalEvent.key === 'Enter') {\n            this.handleSubmit();\n        }\n    },\n    onblur: () => this.handleBlur()\n})\n```\n\n### Custom Events\n\n```javascript\nimport { eventEmitter } from '@bernotieno/mini-framework';\n\n// Component A emits an event\neventEmitter.emit('user-updated', { id: 123, name: 'John' });\n\n// Component B listens for the event\neventEmitter.on('user-updated', (userData) => {\n    console.log('User updated:', userData);\n});\n\n// One-time listener\neventEmitter.once('app-ready', () => {\n    console.log('App is ready!');\n});\n```\n\n## State Management Patterns\n\n### Local Component State\n\n```javascript\nconst Counter = defineComponent({\n    state: {\n        count: 0\n    },\n\n    increment() {\n        this.setState('count', this.getState('count') + 1);\n    },\n\n    render() {\n        return h('div', {}, [\n            h('span', {}, `Count: ${this.getState('count')}`),\n            h('button', { onclick: () => this.increment() }, '+')\n        ]);\n    }\n});\n```\n\n### Global State with Actions\n\n```javascript\nimport { globalState } from '@bernotieno/mini-framework';\n\n// Define actions\nconst counterActions = {\n    increment: globalState.action('increment', (state) => {\n        const count = state.get('counter.count') || 0;\n        state.set('counter.count', count + 1);\n    }),\n\n    decrement: globalState.action('decrement', (state) => {\n        const count = state.get('counter.count') || 0;\n        state.set('counter.count', count - 1);\n    }),\n\n    reset: globalState.action('reset', (state) => {\n        state.set('counter.count', 0);\n    })\n};\n\n// Use in components\nconst GlobalCounter = defineComponent({\n    afterMount() {\n        this.subscribeToGlobalState('counter.count', () => {\n            this.setState('updated', Date.now()); // Trigger re-render\n        });\n    },\n\n    render() {\n        const count = globalState.get('counter.count') || 0;\n\n        return h('div', {}, [\n            h('span', {}, `Global Count: ${count}`),\n            h('button', { onclick: counterActions.increment }, '+'),\n            h('button', { onclick: counterActions.decrement }, '-'),\n            h('button', { onclick: counterActions.reset }, 'Reset')\n        ]);\n    }\n});\n```\n\n## Routing Examples\n\n### Basic Routing\n\n```javascript\nimport { router, globalState } from '@bernotieno/mini-framework';\n\n// Set up routes\nrouter.route('/', () => {\n    globalState.set('currentPage', 'home');\n});\n\nrouter.route('/users', () => {\n    globalState.set('currentPage', 'users');\n});\n\nrouter.route('/users/:id', (route) => {\n    globalState.set('currentPage', 'user-detail');\n    globalState.set('currentUserId', route.params.id);\n});\n\n// Route with query parameters\nrouter.route('/search', (route) => {\n    globalState.set('currentPage', 'search');\n    globalState.set('searchQuery', route.query.q || '');\n});\n```\n\n### Route-based Component Rendering\n\n```javascript\nconst App = defineComponent({\n    afterMount() {\n        this.subscribeToGlobalState('currentPage', () => {\n            this.setState('updated', Date.now());\n        });\n    },\n\n    render() {\n        const currentPage = globalState.get('currentPage');\n\n        return h('div', { class: 'app' }, [\n            h('nav', {}, [\n                h('a', {\n                    href: '#/',\n                    onclick: (e) => {\n                        e.preventDefault();\n                        router.navigate('/');\n                    }\n                }, 'Home'),\n                h('a', {\n                    href: '#/users',\n                    onclick: (e) => {\n                        e.preventDefault();\n                        router.navigate('/users');\n                    }\n                }, 'Users')\n            ]),\n            h('main', {}, this.renderPage(currentPage))\n        ]);\n    },\n\n    renderPage(page) {\n        switch (page) {\n            case 'home':\n                return h(HomePage);\n            case 'users':\n                return h(UsersPage);\n            case 'user-detail':\n                return h(UserDetailPage, {\n                    userId: globalState.get('currentUserId')\n                });\n            default:\n                return h('div', {}, 'Page not found');\n        }\n    }\n});\n```\n\n## TodoMVC Example\n\nThe `examples/todomvc/` directory contains a complete TodoMVC implementation demonstrating all framework features:\n\n- **State Management**: Global state for todos, filters, and editing state\n- **Components**: Modular components for header, todo items, and footer\n- **Events**: Custom event handling for user interactions\n- **Routing**: URL-based filtering (all/active/completed)\n- **Persistence**: Local storage integration\n\nKey features implemented:\n- ✅ Add new todos\n- ✅ Toggle todo completion\n- ✅ Edit todos (double-click)\n- ✅ Delete todos\n- ✅ Filter todos (All/Active/Completed)\n- ✅ Clear completed todos\n- ✅ Toggle all todos\n- ✅ Persistent storage\n- ✅ URL routing\n\n## API Reference\n\n### Core Functions\n\n- `h(tag, attrs, children)` - Create virtual DOM elements\n- `createApp(options)` - Create application instance\n- `defineComponent(definition)` - Create component class\n\n### State Management\n\n- `globalState.get(path)` - Get state value\n- `globalState.set(path, value)` - Set state value\n- `globalState.update(path, updater)` - Update with function\n- `globalState.subscribe(path, callback)` - Subscribe to changes\n- `globalState.action(name, actionFn)` - Create state action\n\n### Routing\n\n- `router.route(path, handler)` - Define route\n- `router.navigate(path, options)` - Navigate to route\n- `router.beforeEach(hook)` - Add before navigation hook\n- `router.afterEach(hook)` - Add after navigation hook\n\n### Events\n\n- `eventEmitter.on(event, callback)` - Subscribe to event\n- `eventEmitter.emit(event, data)` - Emit event\n- `domEvents.bind(element, event, handler)` - Bind DOM event\n\n## Security Features\n\nMini Framework includes comprehensive security measures to protect against common web vulnerabilities:\n\n### XSS Protection\n- **HTML Escaping**: All text content is automatically escaped to prevent script injection\n- **Attribute Sanitization**: Dangerous attributes like `onclick` with string values are blocked\n- **URL Validation**: `javascript:` and unsafe `data:` URLs are automatically blocked\n- **CSS Sanitization**: Style attributes are cleaned to remove dangerous CSS expressions\n\n### Input Validation\n- **Path Traversal Protection**: Router paths are sanitized to prevent `../` attacks\n- **Prototype Pollution Prevention**: State objects are validated to block `__proto__` manipulation\n- **Event Name Validation**: Event names are sanitized and length-limited\n- **Storage Key Validation**: LocalStorage keys are validated and sanitized\n\n### Resource Limits\n- **Memory Protection**: Limits on subscribers, routes, and event listeners prevent memory exhaustion\n- **Recursion Prevention**: Maximum depth limits prevent stack overflow attacks\n- **Rate Limiting**: Event emission is rate-limited to prevent DoS attacks\n- **Size Limits**: Storage values are size-checked to prevent quota exhaustion\n\n### Error Handling\n- **Graceful Degradation**: Components continue working even when individual parts fail\n- **Error Boundaries**: Rendering errors are contained and don't crash the entire app\n- **Safe Fallbacks**: Invalid operations fall back to safe defaults\n- **Comprehensive Logging**: All security events are logged for monitoring\n\n```javascript\n// Example: Automatic XSS protection\nconst userInput = '<script>alert(\"xss\")</script>';\nh('div', {}, userInput); // Automatically escaped: &lt;script&gt;alert(\"xss\")&lt;/script&gt;\n\n// Example: Blocked dangerous attributes\nh('div', { onclick: 'alert(\"xss\")' }); // Blocked and logged as warning\n\n// Example: Safe URL handling\nh('a', { href: 'javascript:alert(\"xss\")' }); // Blocked and logged as warning\n```\n\n## Error Handling Best Practices\n\nThe framework provides robust error handling throughout:\n\n### Component Error Boundaries\n```javascript\nconst SafeComponent = defineComponent({\n  render() {\n    try {\n      return h('div', {}, this.renderContent());\n    } catch (error) {\n      console.error('Component render error:', error);\n      return h('div', { class: 'error' }, 'Something went wrong');\n    }\n  }\n});\n```\n\n### State Error Recovery\n```javascript\n// State operations are automatically wrapped in try-catch\nglobalState.set('user.profile', userData); // Safe even if userData is invalid\n\n// Subscribe with error handling\nglobalState.subscribe('user', (user) => {\n  try {\n    updateUI(user);\n  } catch (error) {\n    console.error('UI update failed:', error);\n    // Framework continues working\n  }\n});\n```\n\n### Event Error Isolation\n```javascript\n// Event handlers are automatically wrapped for safety\nh('button', {\n  onclick: () => {\n    throw new Error('Handler error');\n    // Error is caught and logged, app continues working\n  }\n}, 'Click me');\n```\n\n## Browser Support\n\n- Modern browsers with ES6+ support\n- Chrome 61+\n- Firefox 60+\n- Safari 12+\n- Edge 79+\n\n## File Structure\n\n```\nmini-framework/\n├── src/\n│   ├── core/\n│   │   ├── dom.js          # Virtual DOM implementation\n│   │   ├── events.js       # Custom event system\n│   │   ├── state.js        # Reactive state management\n│   │   └── router.js       # Client-side routing\n│   ├── framework.js        # Main framework entry\n│   └── utils.js           # Utility functions\n├── examples/\n│   └── todomvc/           # TodoMVC implementation\n├── README.md              # This documentation\n└── package.json           # Project configuration\n```\n\n## Publishing to NPM\n\nThis framework is designed to be published as an npm package. Here's how to publish it:\n\n### Prerequisites\n\n1. **NPM Account**: Create an account at [npmjs.com](https://npmjs.com)\n2. **Login to NPM**: Run `npm login` in your terminal\n3. **Update Package Name**: The package is configured as `@bernotieno/mini-framework`\n\n### Publishing Steps\n\n1. **Package Configuration** (already configured):\n   ```json\n   {\n     \"name\": \"@bernotieno/mini-framework\",\n     \"repository\": {\n       \"type\": \"git\",\n       \"url\": \"git+https://github.com/bernotieno/mini-framework.git\"\n     },\n     \"bugs\": {\n       \"url\": \"https://github.com/bernotieno/mini-framework/issues\"\n     },\n     \"homepage\": \"https://github.com/bernotieno/mini-framework#readme\"\n   }\n   ```\n\n2. **Version Management**:\n   ```bash\n   # Patch version (1.0.0 -> 1.0.1)\n   npm version patch\n\n   # Minor version (1.0.0 -> 1.1.0)\n   npm version minor\n\n   # Major version (1.0.0 -> 2.0.0)\n   npm version major\n   ```\n\n3. **Publish**:\n   ```bash\n   # For scoped packages (recommended)\n   npm publish --access public\n\n   # For unscoped packages\n   npm publish\n   ```\n\n### Using the Published Package\n\nOnce published, users can install and use your framework:\n\n```bash\nnpm install @bernotieno/mini-framework\n```\n\n```javascript\nimport { createApp, defineComponent, h } from '@bernotieno/mini-framework';\n\nconst MyComponent = defineComponent({\n  render() {\n    return h('div', {}, 'Hello from Mini Framework!');\n  }\n});\n\nconst app = createApp();\nconst component = new MyComponent();\ncomponent.mount(document.getElementById('app'));\n```\n\n### Package Features\n\n- ✅ **ES Modules**: Native ES module support\n- ✅ **TypeScript Definitions**: Included for better developer experience\n- ✅ **Zero Dependencies**: No external runtime dependencies\n- ✅ **Tree Shakeable**: Import only what you need\n- ✅ **CDN Ready**: Works with unpkg, jsDelivr, etc.\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch\n3. Make your changes\n4. Add tests if applicable\n5. Submit a pull request\n\n## License\n\nMIT License - feel free to use this framework in your projects!\n\n---\n\n**Mini Framework** - Building modern web apps with zero dependencies! 🚀\n","readmeFilename":"README.md"}