# Duck Framework — Complete Component Guide for AI Assistants > This document is the single source of truth for AI assistants working with > Duck Framework components. Read every section before writing any Duck code. > When in doubt about a specific component's API, fetch its docs page at: > `https://docs.duckframework.com/main/api/duck/duck.html.components..html` --- **Note:** This file is formatted in Markdown. All content, including headings, code blocks, and inline formatting, must be parsed and interpreted according to Markdown syntax rules rather than treated as plain text. Read this file twice to avoid making mistakes. --- ## Table of Contents 1. [What Is Duck Framework?](#1-what-is-duck-framework) 2. [The Lively Component System](#2-the-lively-component-system) 3. [Component Base Classes](#3-component-base-classes) 4. [Component Lifecycle](#4-component-lifecycle) 5. [Constructing Components — The Right Way](#5-constructing-components--the-right-way) 6. [Styling and Props](#6-styling-and-props) 7. [Events and Reactivity](#7-events-and-reactivity) 8. [Page Components](#8-page-components) 9. [Container vs Non-Container Components](#9-container-vs-non-container-components) 10. [All Built-in Components](#10-all-built-in-components) 11. [Custom Components](#11-custom-components) 12. [Component Extensions](#12-component-extensions) 13. [Forms](#13-forms) 14. [Force Updates and Immediate Syncing](#14-force-updates-and-immediate-syncing) 15. [JavaScript Execution](#15-javascript-execution) 16. [Utility Functions](#16-utility-functions) 17. [Caching](#17-caching) 18. [Navigation](#18-navigation) 19. [Base Page Pattern — Best Practice](#19-base-page-pattern--best-practice) 20. [Theming Patterns — Best Practice](#20-theming-patterns--best-practice) 21. [Code Style Rules](#20-code-style-rules) 22. [Common Mistakes to Avoid](#21-common-mistakes-to-avoid) 23. [How to Look Up Any Component](#22-how-to-look-up-any-component) 24. [Rules to Follow](#24-rules-to-follow) 25. [Helpful Sources](#23-helpful-sources) --- ## 1. What Is Duck Framework? Duck is a Python web framework that lets you build fully interactive web UIs **without writing JavaScript**. It uses WebSockets (msgpack) to sync component state between the Python server and the browser in real time. Key facts: - UI is defined as Python classes (components) - Events (clicks, inputs, submits) are handled in Python - The DOM updates automatically — only changed parts re-render - Fast navigation between pages without full reloads (vdom diffing) - Templates (Jinja2/Django) are supported but components are preferred --- ## 2. The Lively Component System The Lively system is Duck's reactive engine. It: - Tracks component `props` and `style` set during initial render - Sends minimal DOM patches over WebSocket when state changes - Handles event routing from browser ➝‬ Python handler ➝‬ DOM patch **Critical rule:** Lively performs **non-destructive syncing**. It only updates props and styles it is aware of from the server state, and ignores anything it didn’t create or track. - New props/styles set from Python (e.g. in event handlers) will sync normally - Props/styles added externally (e.g. via `execute_js`) **are not tracked** - Untracked properties will **not be removed or overridden**, even when patches are applied This means Lively will **merge updates**, not replace the entire prop/style object. ```python # Initial render — no background-color btn = Button(text="Click") # Later in Python (event handler) — this WILL sync btn.style["background-color"] = "red" ``` ```javascript // Added externally — Lively does NOT track this element.style.border = "1px solid blue" ``` Even after future updates from Python: ```python btn.style["background-color"] = "green" ``` The `border` style will remain untouched because Lively never tracked it. ### Key takeaway Lively behaves like a **partial diff system**, not a full state replacement system: - ✅ Updates known fields - ✅ Adds new fields from server-side changes - ❌ Does not remove unknown/external fields --- ## 3. Component Base Classes All components ultimately inherit from `HtmlComponent`. You will mostly use: | Class | Import | Use when | |---|---|---| | `InnerComponent` | `duck.html.components` | Component has children / inner body | | `NoInnerComponent` | `duck.html.components` | Self-closing element (like ``) | | `Page` | `duck.html.components.page` | Full HTML page | ```python from duck.html.components import InnerComponent, NoInnerComponent from duck.html.components.page import Page ``` ### Key properties on every component | Property | Type | Description | |---|---|---| | `style` | `StyleStore` (dict-like) | CSS styles | | `props` | `PropertyStore` (dict-like) | HTML attributes | | `id` | str | HTML id (set via `id=` kwarg) | | `klass` | str | CSS class (use instead of `class`) | | `parent` | Component or None | Parent in the tree | | `root` | Component or None | Root of the tree | | `children` | ChildrenList | Child components (InnerComponent only) | | `uid` | str | Auto-assigned unique ID | | `kwargs` | dict | All extra kwargs passed at construction | | `inner_html` | str | Raw HTML inner content | --- ## 4. Component Lifecycle These methods are called in order. Always call `super()` first. ### `on_create()` Called immediately on component instantiation. This is where you build the component's structure — add children, set styles, read kwargs. ```python def on_create(self): super().on_create() # Build structure here self.title = Heading(type="h2", text="Hello") self.add_child(self.title) ``` ### `on_parent(parent)` Called when this component is added to a parent. Use it when you need to know about the parent before doing something, e.g. adding a sibling script. ```python def on_parent(self, parent): parent.add_child(Script(inner_html="...")) ``` ### `on_root_finalized(root)` Called once the root component (usually the Page) is permanently set. You can use this to bind events if you require a stable root i.e. the Page component. ```python def on_root_finalized(self, root): async def on_ready(page, event, value, ws): print("DOM loaded") root.document_bind("DOMContentLoaded", on_ready, update_self=False) ``` ### Lifecycle order summary ``` Component() ➝‬ on_create() ➝‬ [added to parent] ➝‬ on_parent() ➝‬ on_root_finalized() ``` --- ## 5. Constructing Components — The Right Way **Always pass everything at construction time via kwargs.** Do not set attributes after construction unless inside a lifecycle method. ### Correct way: ```python # CORRECT — clean, declarative card = Card( id="featured-card", klass="card featured", style={"background": "var(--theme-surface)", "padding": "16px"}, props={"data-type": "featured"}, children=[ Heading(type="h3", text="Title"), Paragraph(text="Some description here."), ] ) ``` ### Wrong way: ```python # WRONG — imperative, scattered card = Card() card.id = "featured-card" card.style["background"] = "var(--theme-surface)" card.add_child(Heading(type="h3", text="Title")) ``` **Note:** Another thing, instead of using functions to construct components, attach them as methods to the components they belong. **Do this:** ```python from duck.html.components.container import Container class MyComponent(Container): def on_create(self): super().on_create() self.add_child(self.build_some_component()) def build_some_component(self): # Return a component here.. pass ``` **Instead of:** ```python from duck.html.components.container import Container def build_some_component(): # Return a component here.. pass class MyComponent(Container): def on_create(self): super().on_create() self.add_child(build_some_component()) ``` ### Reading kwargs inside components Use `self.kwargs` to access anything passed at construction: ```python def on_create(self): super().on_create() title = self.kwargs.get("title", "Default") # optional user = self.get_kwarg_or_raise("user") # required — raises if missing ``` --- ## 6. Styling and Props ### Style `self.style` is a dict-like store. Set styles using CSS property names: ```python comp.style["background-color"] = "red" comp.style["font-size"] = "1rem" comp.style["display"] = "flex" ``` Or pass at construction: ```python FlexContainer(style={"gap": "16px", "flex-direction": "column"}) ``` ### BasicExtension shortcuts All components include `BasicExtension`, which provides convenience kwargs: | Kwarg | Effect | |---|---| | `id` | Sets `id` property | | `klass` | Sets CSS `class` property | | `bg_color` | Sets `background-color` style | | `color` | Sets `color` style | | `inner_html` | Sets the RAW `innerHTML` of container component | | `text` | Sets ESCAPED `safe innerHTML` of a container component | ```python Button(text="Click me", bg_color="green", color="white") ``` ### StyleCompatibilityExtension Also included by default. Automatically adds vendor prefixes: setting `backdrop-filter` also sets `-webkit-backdrop-filter`, etc. ### Props `self.props` holds HTML attributes. Use for `onclick`, `data-*`, `aria-*`, etc: ```python btn.props["onclick"] = "myJsFunction()" btn.props["aria-label"] = "Close modal" btn.props["data-id"] = "123" ``` ### CSS classes Use `klass` (not `class`) to set CSS classes: ```python Container(klass="hero-section full-width") ``` --- ## 7. Events and Reactivity ### Binding events ```python component.bind( event, # e.g. "click", "input", "submit", "change" handler, # callable (sync or async) update_self=True, # whether this component re-renders update_targets=[other], # other components to re-render ) ``` ### Event handler signature ```python async def on_click(component, event: str, value, ws): """ Args: component: The component that fired the event. event: Event name string. value: Event value (varies by event type). ws: LivelyWebSocketView — use for JS execution. """ component.bg_color = "red" ``` Handlers can be sync or async. Async is preferred for any I/O. ### update_targets Only pass components that actually change. Unnecessary targets waste bandwidth: ```python # Good — only re-renders what changed btn.bind("click", handler, update_self=False, update_targets=[counter_label]) # Bad — re-renders everything unnecessarily btn.bind("click", handler, update_targets=[comp1, comp2, comp3, comp4]) ``` ### Document events Bind to document-level events only on `Page` instances: ```python page.document_bind("DOMContentLoaded", on_load, update_self=False) page.document_bind("DuckNavigated", on_navigate, update_self=False) ``` ### Unbinding ```python component.unbind("click") # failsafe by default component.unbind("click", failsafe=False) # raises if not bound ``` --- ## 8. Page Components `Page` is the root component for full HTML pages. Always subclass it. ### Initialisation ```python from duck.html.components.page import Page class HomePage(Page): def on_create(self): super().on_create() # Page setup goes here ``` In views: ```python def home(request): return HomePage(request=request) ``` ### Page API — all available methods #### Content ```python page.add_to_body(component) # add to page.add_to_head(component) # add to # Note: never use page.add_child() — use add_to_body/add_to_head ``` `add_to_body` accepts a single component or a list: ```python page.add_to_body([Nav(), Hero(), Footer()]) ``` #### Metadata and SEO ```python page.set_title("Page Title") page.set_description("Meta description text.") page.set_author("Author Name") page.set_keywords(["duck", "python", "web"]) page.set_canonical("https://example.com/page") page.set_robots("index, follow") page.set_lang("en") ``` #### Social / Open Graph ```python page.set_opengraph( title="Title", description="Description", url="https://example.com", image="https://example.com/og.png", type="website", site_name="My Site", ) page.set_twitter_card( card="summary_large_image", title="Title", description="Description", image="https://example.com/og.png", site="@handle", ) ``` #### Favicons ```python page.set_favicon("/static/favicon.ico", icon_type="image/x-icon") page.set_favicons([ {"href": "/static/icon-32.png", "sizes": "32x32", "type": "image/png"}, {"href": "/static/icon-apple.png", "rel": "apple-touch-icon"}, ]) ``` #### Scripts and Stylesheets ```python page.add_stylesheet("/static/css/main.css") page.add_script(src="/static/js/app.js", defer=True) page.add_script(inline="console.log('hello')") ``` #### Structured Data ```python page.set_json_ld({ "@context": "https://schema.org", "@type": "WebSite", "url": "https://example.com", "name": "My Site", }) page.set_article_json_ld( headline="Article Title", author_name="Author", date_published="2026-01-01", description="Article description", url="https://example.com/article", ) ``` #### Accessibility ```python page.set_accessibility(lang="en", role="main") ``` #### Analytics ```python page.add_google_analytics("UA-XXXXX-Y") ``` #### Meta tags (custom) ```python page.add_meta(name="theme-color", content="#F5C842") ``` #### Page reload control ```python page.fullpage_reload = True # force full page reload on navigation ``` --- ## 9. Container vs Non-Container Components This distinction is critical. Getting it wrong raises errors. ### Container components (accept `children=`) These extend `InnerHtmlComponent` / `InnerComponent`. They can hold children. - `Container`, `FlexContainer`, `GridContainer`, `FixedContainer` - `Section`, `Card`, `Modal`, `Form`, `Hero` - `Page` (uses `add_to_body`/`add_to_head` instead of `children=`) - Any custom `InnerComponent` subclass ```python FlexContainer( style={"gap": "12px"}, children=[ Button(text="One"), Button(text="Two"), ] ) ``` Content is set via specific kwargs like `text=`, `src=`, `inner_html=`: ```python Heading(type="h1", text="Welcome") Paragraph(text="Some body text.") Script(inner_html="console.log('loaded')") ``` ### Non-container components (no `children=`) These extend `NoInnerHtmlComponent` / `NoInnerComponent`. Self-closing or content-only elements. - `Input`, `FileInput` - `etc` - elements with no closing tags. ```python Image(source="/static/img.png", alt="Description") ``` ### Adding children imperatively (when needed inside on_create) ```python def on_create(self): super().on_create() self.add_child(Button(text="One")) self.add_children([Button(text="Two"), Button(text="Three")]) # Remove children self.remove_child(some_child) self.clear_children() ``` --- ## 10. All Built-in Components Always fetch the specific module docs before using a component to get the exact kwargs. Pattern: `https://docs.duckframework.com/main/api/duck/duck.html.components..html` | Component | Module | Type | Notes | |---|---|---|---| | `Button` | `button` | Non-container | `text=`, `bg_color=`, `color=` | | `FlatButton` | `button` | Non-container | Flat variant | | `RaisedButton` | `button` | Non-container | Elevated variant | | `Card` | `card` | Container | | | `Checkbox` | `checkbox` | Non-container | `name=`, `checked=`, `disabled=` | | `Code` | `code` | Non-container | Code block display | | `Container` | `container` | Container | Basic `
` | | `FlexContainer` | `container` | Container | `display:flex` div | | `GridContainer` | `container` | Container | `display:grid` div | | `FixedContainer` | `container` | Container | `position:fixed` div | | `FileInput` | `fileinput` | Non-container | File upload input | | `Footer` | `footer` | Container | Page footer | | `Form` | `form` | Container | Bind `submit` event | | `Heading` | `heading` | Non-container | `type="h1"..."h6"`, `text=` | | `Hero` | `hero` | Container | Hero section | | `Icon` | `icon` | Non-container | Icon component | | `Image` | `image` | Non-container | `source=`, `alt=` | | `Input` | `input` | Non-container | `type=`, `name=`, `placeholder=` | | `InputWithLabel` | `input` | Container | Wraps Input with a Label | | `Label` | `label` | Non-container | `text=` | | `Link` | `link` | Non-container | `url=`, `text=` | | `Modal` | `modal` | Container | `title=`, `show_close=`, `open_on_ready=`, `modal_style=` | | `Navbar` | `navbar` | Container | Requires jQuery — avoid extending, build custom instead | | `Page` | `page` | Special | Root page component | | `Paragraph` | `paragraph` | Non-container | `text=` | | `ProgressBar` | `progressbar` | Non-container | | | `Script` | `script` | Non-container | `inner_html=` or `src=` | | `Section` | `section` | Container | Semantic `
` | | `Select` | `select` | Non-container | Dropdown | | `Snackbar` | `snackbar` | Container | Toast notification | | `Style` | `style` | Non-container | Inline `