Skip to content

Repository files navigation

Aitne

Aitne Banner

A lightweight, high-performance web framework built for modern frontend development, featuring fine-grained reactivity and a declarative component model. Inspired by leptos and solidjs.
Supports MBX, a JSX-like component syntax, providing a familiar and expressive way to build reactive web applications.

Getting Started

Installing CLI

macOS/Linux:

curl -fsSL https://raw.githubusercontent.com/Arcelyth/aitne/main/scripts/install.sh | bash

aitne CLI depends on moonbit async library which not supports Windows now

Initializing

aitne init your_project
cd your_project
moon update

Build your project:

aitne build

Running

aitne run

This will start a web server on http://localhost:8000 by default which depends on eirene.toml config file.

Examples

Todo list:

fn todo_app() -> &View {
  let (input_val, set_input_val) = @reactive.create_signal("")
  let (todo, set_todo) = @reactive.create_signal(["Example."])

  let add_item = _ => {
    let text = input_val.get()
    if text != "" {
      set_todo.set(todo.get() + [text])
    }
    set_input_val.set("")
  }

  let remove_item = item => {
    let new_list = todo.get().filter(fn(t) { t != item })
    set_todo.set(new_list)
  }

  <div>
    <h1> Todo List </h1>
    <div>{() => todo.get().length().to_string() }</div>
    <div>
      <input 
        type="text" 
        value={input_val} 
        on:input={ev => set_input_val.set(event_target_value(ev))} 
      />
      <button on:click={add_item}> Add </button>
    </div>
    <ul>
      <ForEach 
        each={()=>todo.get().iter()}
        key={(x)=>{return x}}
        children={(item) => {
          <li>
            {() => item}
            <button on:click={_ => remove_item(item)}> "Delete" </button>
          </li>
        }}
      />
    </ul>
  </div>
}

Simple router usage:

///|
pub fn app() -> &View {
  <Router base="/">
    <Routes fallback={() => <NotFound />}>
        <Route path="/" view={() => <Home />} />
        <ParentRoute 
            path="/users" 
            view={() => <UsersPage />}> 
           <Route path="/:id" view={() => <UserDetailPage />}/> 
        </ParentRoute>
        <ParentRoute 
            path="/t"
            view={() => <TryPage />}> 
           <Route path="/t1" view={() => <TryPage />} /> 
        </ParentRoute>
    </Routes>
  </Router>
}

///|
fn main {
  let _ = @dom.mount_to_body(() => <App />)
}

Style

Aitne provides first-class support for component-scoped CSS directly inside your mbx source files using ${ ... }$ CSS blocks.
You can write inline CSS rules, import external stylesheets use expand syntax !"path.css"/!'path.css', assign styles to variables and reference class names safely inside your component bindings.

pub fn counter_btn(incr?: Int = 1) -> &View {
    let style = ${ 
        !"./counter_btn.module.css"
        .btn {
            background-color: #000000;
        }
    }$ 
    let (count, set_count) = @reactive.create_signal(0)
    <button on:click={(_) => { set_count.update((v) => { v + incr }) }} class={()=>style.btn}>
        Click me:  {() => count.get().to_string()}
    </button>
}

Editor Support

Eirene

Eirene is a simple web server built in MoonBit, specifically designed to serve static assets and handle Single Page Application (SPA) routing fallbacks for the Aitne ecosystem.
An example 'eirene.toml' config file:

[app]
name = "examples"
mode = "development"
entry_html = "index.html"

[build]
target = "js"
src_dir = "src"
out_dir = "."

[server]
host = "127.0.0.1"
port = 8000

Learn more

Book
API Document
Benchmark

This library still work in progress, not production ready!

About

A lightweight and high-performance reactive web framework.

Topics

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages