# Lit-Only Architecture (No Build) A minimal, no-build web application using only Lit web components with local state management. > **Note:** This is the `lit-only` branch. For the full-featured version with Zustand state management and IndexedDB persistence, see the `main` branch. ## For TSX/React Developers If you're coming from React/TSX, here's how this minimal architecture maps to familiar concepts: | React/TSX Pattern | This Architecture | |-------------------|-------------------| | `useState` | Lit's `static properties` with `state: true` | | Props drilling | Property passing via `.prop=${value}` | | Custom events | `CustomEvent` with `bubbles: true` | | JSX | Lit's `html` tagged template literals | | CSS-in-JS / CSS Modules | Lit's `css` tagged template literals | | React Router | Simple route state in root component | | Build step (Vite/Webpack) | Import maps (no build!) | ### Key Differences 1. **No Virtual DOM**: Lit uses native Web Components with efficient DOM updates 2. **No Build Step**: Import maps let you use npm packages directly from CDN 3. **Local State Only**: Each component manages its own state, parent manages shared state 4. **Event-Based Communication**: Child components emit events, parent handles them 5. **Tagged Templates**: Instead of JSX, use `html\`
...
\`` ## Architecture Overview * **Lit-based web components** - Standards-based, framework-agnostic UI * **No-build tooling** - Import maps only, no bundler required * **Local state management** - Component properties and state * **Event-driven** - CustomEvents for child-to-parent communication ## Project Structure ``` components/ app-root.js ← Root component with shared state nav-bar.js ← Navigation component page-home.js ← Home page component page-items.js ← Items page component index.html ← Entry point with inline importmap README.md tasks.md ``` ## Data Flow Pattern ### Parent-to-Child (Props) ```javascript // Parent passes data down html`` // Child receives via properties static properties = { items: { type: Array } } ``` ### Child-to-Parent (Events) ```javascript // Child emits event this.dispatchEvent(new CustomEvent('add-item', { detail: { item: newItem }, bubbles: true, composed: true })) // Parent listens html` this.handleAdd(e.detail.item)}>` ``` ## State Management Pattern ```mermaid graph TD A[app-root] -->|.user, .items, .route| B[nav-bar] A -->|.user, .items| C[page-home] A -->|.items| D[page-items] B -->|@navigate event| A D -->|@add-item event| A D -->|@remove-item event| A style A fill:#f9f,stroke:#333,stroke-width:2px style B fill:#bbf,stroke:#333,stroke-width:2px style C fill:#bfb,stroke:#333,stroke-width:2px style D fill:#bfb,stroke:#333,stroke-width:2px ``` ## Quick Start Example ### 1. Define a Component ```javascript // components/counter.js import { LitElement, html, css } from 'lit' class Counter extends LitElement { static properties = { count: { type: Number, state: true } } constructor() { super() this.count = 0 } static styles = css` button { padding: 1rem; font-size: 1.2rem; } ` render() { return html`

Count: ${this.count}

` } } customElements.define('my-counter', Counter) ``` ### 2. Use in HTML (no build step!) ```html ``` ## Component Communication Patterns ### Pattern 1: Shared State in Root ```javascript class AppRoot extends LitElement { static properties = { items: { type: Array, state: true } } constructor() { super() this.items = [] } addItem(item) { this.items = [...this.items, item] } render() { return html` this.addItem(e.detail.item)} > ` } } ``` ### Pattern 2: Local State in Component ```javascript class MyComponent extends LitElement { static properties = { _draft: { type: String, state: true } } constructor() { super() this._draft = '' } render() { return html` this._draft = e.target.value} /> ` } } ``` ## Benefits Over React/TSX ✅ **No build step** - Edit and refresh, instant feedback ✅ **Minimal dependencies** - Just Lit, nothing else ✅ **Smaller bundle** - No framework runtime, just standards ✅ **Better encapsulation** - Shadow DOM, scoped styles ✅ **Framework agnostic** - Works anywhere, even in React apps ✅ **Future-proof** - Built on web standards ✅ **Easy to learn** - Simple mental model, no complex state management ## When to Use This vs. Full Stack ### Use Lit-Only When: - Building small to medium apps - Don't need persistence - State is simple and hierarchical - Want maximum simplicity ### Use Full Stack (main branch) When: - Need IndexedDB persistence - Complex state shared across many components - Need cross-tab synchronization - Want time-travel debugging - Building larger applications ## See Also - [tasks.md](./tasks.md) - Current issues and improvements - [Lit Documentation](https://lit.dev) - [Web Components](https://developer.mozilla.org/en-US/docs/Web/Web_Components) - [Import Maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap)