Getting Started

Build interactive .NET web apps without the JavaScript fatigue.

The 5-Minute Quick Start

The fastest way to experience Swap.Htmx is with our project templates. They come pre-configured with HTMX, styling, and the correct folder structure.

1. Install Templates

dotnet new install Swap.Templates

2. Create Your Project

Choose the Modular Monolith template (recommended) for a scalable architecture, or MVC for a simple starter.

# Recommended: Full modular architecture
dotnet new swap-modular -n MyApp
cd MyApp/src

# Or: Single project MVC
# dotnet new swap-mvc -n MyApp
# cd MyApp

3. Run It

Our templates use LibMan to manage client assets without Node.js.

libman restore
dotnet run

⚡ Your First Swap Component

Let's build a simple Todo List to see how Swap.Htmx eliminates the need for API endpoints and JSON serialization.

1. The Controller

Inherit from SwapController (not Controller). This gives you access to the Swap ecosystem.

using Swap.Htmx;

public class TodosController : SwapController
{
    private static List<string> _todos = new() { "Install Swap", "Build something cool" };

    // GET: /todos
    // Renders the full page OR the partial, depending on the request type.
    [HttpGet]
    public IActionResult Index() => SwapView(_todos);

    // POST: /todos
    // Adds items and updates the list in place without a page reload.
    [HttpPost]
    public IActionResult Add(string title)
    {
        _todos.Add(title);
        
        // Updates the list (#todo-list) AND the counter (#count) in one go
        return SwapResponse()
            .WithView("_TodoList", _todos)
            .AlsoUpdate(SwapElements.Count, "_Count", _todos.Count)
            .WithSuccessToast("Task added!")
            .Build();
    }
}

2. The View (Index.cshtml)

Use standard Razor. The SwapView helper automatically generates the appropriate response (Full Layout vs Partial).

@model List<string>

<div class="container">
    <h1>My Tasks (<span id="count">@Model.Count</span>)</h1>

    <!-- 
      HTMX Attributes Explained:
      hx-post:   Send a POST request to this URL
      hx-target: Replace the element with ID "todo-list"
    -->
    <form hx-post="@Url.Action("Add")" hx-target="#todo-list">
        <input name="title" placeholder="What needs to be done?" required />
        <button type="submit">Add Task</button>
    </form>

    <ul id="todo-list">
        <!-- Render the partial initially -->
        <partial name="_TodoList" model="Model" />
    </ul>
</div>

3. The Partial (_TodoList.cshtml)

This is what gets sent back over the wire. Small, fast, and HTML-only.

@model List<string> 

@foreach (var todo in Model)
{
    <li class="fade-in">@todo</li>
}

Why This Is Different

In a traditional React/Angular/Vue app, this simple feature would require:

  1. An API Endpoint (Controller)
  2. A JSON DTO Class
  3. A Client-Side Service
  4. Client-Side State Management
  5. A Component Library
  6. A Build Step (Webpack/Vite)

With Swap.Htmx, you just wrote standard C# and Razor. The server treats HTML as the API.


Core Concepts

Concept Description
SwapView The magic return type. Handles full page loads (browser nav) and partial updates (HTMX) automatically.
SwapResponse Fluent builder for complex updates. Update 5 different parts of the page in a single HTTP request.
SwapState Manage state (pagination, filters) entirely on the server via URL encoding. Includes Tamper-Proof security options.
Events Decouple your components. Let the "Add Task" action trigger updates in the "Activity Log" without them knowing about each other.
Error Boundaries Gracefully handle crashes with Toasts instead of broken UI.

Next Steps

Now that you have the basics, dive deeper into the framework capabilities.