{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreicwrtq2u2hhr7hyys5bftmxfgyl6ylyhwtkflvxitkg7fxn7xgjki",
"uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3moqztkvk3u32"
},
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreicxdgc56wdqpdvcff45booxqr6fmdlxvudm7u344rfclcwf2hl6ma"
},
"mimeType": "image/webp",
"size": 46870
},
"path": "/tengxgfyrz67s/mounting-your-first-application-kl6",
"publishedAt": "2026-06-20T23:20:34.000Z",
"site": "https://dev.to",
"tags": [
"frontend",
"rust",
"tutorial",
"webdev",
"https://github.com/euv-dev/euv"
],
"textContent": "> Project Code:https://github.com/euv-dev/euv\n\nThe `mount` function is the entry point of every euv application. It connects your Rust code to the browser's DOM and kicks off the rendering pipeline. This article explores how mounting works, how to structure your application entry point, and how the rendering engine keeps your UI up to date.\n\n## The Mount Function\n\nAt its simplest, `mount` takes two arguments: a CSS selector string and a function that returns a `VirtualNode`:\n\n\n\n use euv::*;\n\n fn app() -> VirtualNode {\n html! {\n div {\n h1 { \"Hello, euv!\" }\n }\n }\n }\n\n mount(\"#app\", app);\n\n\nThe first argument `\"#app\"` is a CSS selector that identifies the DOM element where your application will be rendered. The second argument `app` is a function that produces the virtual DOM tree. When `mount` is called, euv:\n\n 1. Finds the DOM element matching the selector\n 2. Calls the `app` function to produce a `VirtualNode`\n 3. Renders the virtual DOM tree into the real DOM\n 4. Sets up the reactive system to re-render when state changes\n\n\n\n## Choosing a Mount Target\n\nYou can mount your application to any valid CSS selector:\n\n\n\n // Mount to an element by ID\n mount(\"#app\", app);\n\n // Mount to an element by class\n mount(\".main-content\", app);\n\n // Mount to an element by tag name\n mount(\"body\", app);\n\n\nThe most common pattern is to use an ID selector targeting a dedicated `<div>` element in your HTML:\n\n\n\n <div id=\"app\"></div>\n\n\nThis keeps your application contained and avoids conflicts with other content on the page.\n\n## Structuring the Application Entry Point\n\nAs your application grows, you'll want to organize your entry point into smaller, focused functions. A good pattern is to have your main `app` function delegate to sub-components:\n\n\n\n use euv::*;\n\n fn app() -> VirtualNode {\n html! {\n div {\n {header()}\n {main_content()}\n {footer()}\n }\n }\n }\n\n fn header() -> VirtualNode {\n html! {\n header {\n h1 { \"My Application\" }\n }\n }\n }\n\n fn main_content() -> VirtualNode {\n html! {\n main {\n p { \"Welcome to euv!\" }\n }\n }\n }\n\n fn footer() -> VirtualNode {\n html! {\n footer {\n p { \"Copyright 2024\" }\n }\n }\n }\n\n mount(\"#app\", app);\n\n\nEach function returns a `VirtualNode`, making them composable building blocks. You can embed them inside the `html!` macro using curly braces `{header()}` to insert their output into the parent tree.\n\n## Mounting with Reactive State\n\nThe real power of mounting comes when you combine it with reactive signals. When a signal changes, euv automatically re-renders the affected parts of the DOM:\n\n\n\n use euv::*;\n\n fn app() -> VirtualNode {\n let count: Signal<i32> = use_signal(|| 0);\n\n html! {\n div {\n h1 { \"Counter Example\" }\n p { \"Count: \" {count} }\n button {\n onclick: move || { count.set(count.get() + 1); }\n \"Increment\"\n }\n }\n }\n }\n\n mount(\"#app\", app);\n\n\nHere, `use_signal(|| 0)` creates a reactive signal initialized to `0`. The `{count}` syntax in the `html!` macro automatically subscribes to the signal, so when `count.set()` is called through the button's `onclick` handler, euv re-renders the affected text node.\n\n## Understanding the Rendering Pipeline\n\nWhen `mount` is called, euv sets up the following pipeline:\n\n 1. **Initial Render** — The `app` function is called to produce the initial `VirtualNode` tree, which is then rendered to the DOM.\n 2. **Reactive Tracking** — During rendering, euv tracks which signals are read. This creates a dependency graph.\n 3. **Diffing** — When a signal changes, euv calls the `app` function again to produce a new `VirtualNode` tree, then compares it with the previous tree using its diffing algorithm.\n 4. **Patching** — Only the differences between the old and new trees are applied to the real DOM. This is what makes euv efficient.\n\n\n\nThe renderer uses **incremental rendering** to avoid unnecessary work. It also employs **Keyed Diffing** for list rendering, which uses keys to track individual items across renders, minimizing DOM operations.\n\n## The VirtualNode Type\n\nUnderstanding the `VirtualNode` variants helps you reason about what your `app` function produces:\n\n * **Element** — Represents an HTML element with a tag name and children. Created by standard HTML tags in the `html!` macro.\n * **Text** — Represents a plain text node. Created by string content inside elements.\n * **Fragment** — A collection of nodes without a wrapper element. Useful for returning multiple nodes from a function.\n * **Dynamic** — A node whose content can change based on reactive state. Created when you embed signals in the `html!` macro.\n * **Empty** — Renders nothing. Useful for conditional rendering when you want to show nothing.\n\n\n\nThe `Tag` enum distinguishes between standard HTML elements and custom components:\n\n * **Element(String)** — A standard HTML tag like `\"div\"` or `\"span\"`\n * **Component(String)** — A custom component name\n\n\n\n## Mounting Multiple Applications\n\nYou can mount multiple euv applications on the same page, each targeting a different DOM element:\n\n\n\n use euv::*;\n\n fn nav_app() -> VirtualNode {\n html! {\n nav {\n a { href: \"#home\", \"Home\" }\n a { href: \"#about\", \"About\" }\n }\n }\n }\n\n fn content_app() -> VirtualNode {\n html! {\n main {\n h1 { \"Welcome\" }\n p { \"This is the main content area.\" }\n }\n }\n }\n\n mount(\"#navigation\", nav_app);\n mount(\"#content\", content_app);\n\n\nThis pattern is useful for gradually migrating an existing page to euv or for creating independent widgets that don't share state.\n\n## Using Lifecycle Hooks\n\neuv provides hooks for running code at specific points in a component's lifecycle:\n\n * **use_cleanup** — Register a cleanup function that runs when the component is unmounted\n * **use_window_event** — Listen to window-level events\n * **use_interval** — Set up a recurring timer\n\n\n\n\n use euv::*;\n\n fn app() -> VirtualNode {\n use_cleanup(move || {\n // This runs when the component is unmounted\n });\n\n use_window_event(\"hashchange\", move || {\n // This runs when the URL hash changes\n });\n\n let handle: IntervalHandle = use_interval(1000, move || {\n // This runs every 1000 milliseconds\n });\n\n html! {\n div {\n p { \"Application with lifecycle hooks\" }\n button {\n onclick: move || { handle.clear(); }\n \"Stop Timer\"\n }\n }\n }\n }\n\n mount(\"#app\", app);\n\n\nThe `use_interval` function returns an `IntervalHandle` with a `clear()` method to stop the timer. The `use_window_event` function takes an event name and a closure, making it easy to respond to browser events like `\"hashchange\"`.\n\n## Best Practices for Mounting\n\n 1. **Keep the mount call simple** — The `mount` call should be a single line at the top level of your entry file. Avoid putting logic inside the mount arguments.\n\n 2. **Use a dedicated mount element** — Always have a dedicated `<div id=\"app\">` (or similar) in your HTML. This prevents euv from accidentally modifying other parts of the page.\n\n 3. **Separate concerns** — Keep your `app` function focused on composition. Delegate specific UI sections to separate functions.\n\n 4. **Initialize signals at the top level** — Create your signals at the beginning of the component function, before the `html!` macro call. This makes the data flow clear.\n\n 5. **Use batch for multiple updates** — When you need to update multiple signals at once, wrap them in a `batch` call to avoid unnecessary intermediate renders:\n\n\n\n\n\n\n batch(|| {\n count.set(1);\n });\n\n\n## Summary\n\nThe `mount` function is the bridge between your Rust code and the browser DOM. It takes a CSS selector and a component function, renders the initial UI, and sets up the reactive system for automatic updates. By understanding how mounting works and following the patterns described in this article, you can build well-structured euv applications that are easy to maintain and extend.\n\n> Project Code:https://github.com/euv-dev/euv",
"title": "Mounting Your First Application"
}