New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

mates

Package Overview
Dependencies
Maintainers
1
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mates

Mates is a front end framework for building web applications

latest
npmnpm
Version
0.0.21
Version published
Maintainers
1
Created
Source

Mates

Mates is a lightweight framework that focuses on developer experience. It lets you build great web applications easily with it's awesome state management system. It's typescript First Framework. supports typescript all the way.

🚀 Features (MATES)

  • Mutable State: Mutate state directly through setters to update components (views)
  • Actions: Function utilities to help with business logic
  • Templates: Template functions that return lit-html result
  • Events: Event Utilites for event-driven development
  • Setup functions: These are functions to intialise state needed for the view

📦 Installation


npm  install  mates

# or

yarn  add  mates

🧠 Core Concepts

👁 Views: Components of Mates

Views are similar to components in react. They are closure functions with outer function aka Setup function (the S from the MATES), and inner function is called Template function (the T from MATES) which returns html template string.

import { renderView, setter, html } from "mates";

const CounterView = (props) => {
  // setup function: initialise state
  let count = 0;
  const incr = setter(() => count++);

  // template function: returns html template strings.
  return () => html` <div>
    <h1>Count: ${count}</h1>
    <button @click=${incr}>Increment</button>
  </div>`;
};

// Render the view in any html element by passing it's id
renderView(CounterView, "app");

count is a local let variable that holds value. which can only be changed froma setter function. incr is a setter function, that when called, updates the view. it has to be non-async.

Scopes

Mates introduces a new feature called Scopes. an amazing way to share state with child views (components). using Scopes, child components can access parent's state directly without using props.

Formatting Support:

you can install lit-html plugin on your IDE like vs code or cursor for proper formatting for your template strings.

props()

In Mates, props can be passed to child views as object. props is a funciton and not an object but it's passed as object to child component. the view will have to call props() to get the projects object.

const CounterView = () => {
  let count = 0;
  let incr = setter(() => count++);
  return () => html`
    <div>count is: ${count}</div>
    <div>${view(ChildView, { count })}</div>
  `;
};
const ChildView = (props: Props<{ count: number }>) => {
  return html`parent count is : ${props().count}`;
};

note please don't destructure props into local variables in the outer function, as it breaks connection from the parent object. but you can do this in the inner function as inner function gets executed everytime the parent view is updated. so you will have always the latest value.

⚛️ Atoms: Simple Reactive State

Atoms hold mutable values. they can hold any Javascript value like primitive or objects or maps or sets.etc They store a single value that can be read, set (replaced with new value), or updated (if it's an object). They support typescript fully.


import  {  atom  }  from  "mates";

// Create an atom with initial value
const username  =  atom("guest");

// Read the value
console.log(username());  // "guest"
// or
console.log(username.get()); // "guest"

// set the value
username.set("alice");

// you can also Use setter function
username.set((val)  => val.toUpperCase());

// you can also update the value if it's of object type
const address  =  atom({  street:  ""  });

// you are updating just the street value in an object.
address.update((s)  =>  (s.street  =  "newstreet"));

// supports maps or sets:
const nums = atom(new Map());
// modify the map through update.
nums.update(m=>m.set(1, "one"));

const nums = atom(new Set([1,2,3]);
nums.update(s=>s.add(4));
// get the value
nums(); // Set(4) [1,2,3,4]

Counter app using atoms

const CounterView = (props) => {
  // setup function: initialise state
  const count = atom(0);
  const incr = count.set(count() + 1);

  // template function: returns html template strings.
  return () => html` <div>
    <h1>Count: ${count}</h1>
    <button @click=${incr}>Increment</button>
  </div>`;
};

Units: Independent Object-Based State

Units are perfect for managing object-based state with methods and building store utilities. Units have the following pieces

  • Data: any type of javascript value
  • Setters: methods whose name start with (_)
  • Getters: methods that returns data without changing it
  • Actions: async or non-async methods that call getters or setters for getting, setting data.
import { unit } from "mates";

// Create a users unit
const todoList = unit({
  users: [],
  isLoading = false,
  // setter
  _setIsLoading(value) {
    this.isLoading = value;
  },
  // setter
  _setUsers(newUsers) {
    this.users = newUsers;
  },
  // async action that calls setters to set state
  async loadUsers() {
    this._setIsLoading(true);
    this._setUsers(await fetch("/users").then((d) => d.json()));
    this._setIsLoading(false);
  },
  getUsersCount() {
    return this.users.length;
  },
});

📊 Getters: Computed Values

Getters create computed values that only recalculate when their dependencies change.

import { atom, getter } from "mates";

const firstName = atom("John");

const lastName = atom("Doe");

const fullName = getter(() => {
  return `${firstName()}  ${lastName()}`;
});

console.log(fullName()); // "John Doe"

// Only recalculates when dependencies change

firstName.set("Jane");

console.log(fullName()); // "Jane Doe"

🧬 Molecules: group atoms or units or getters into one molecule

import { molecule, atom } from "mates";

class UserStore {
  name = atom("Guest");

  isLoggedIn = atom(false);

  login(username) {
    this.name.set(username);
    this.isLoggedIn.set(true);
  }

  logout() {
    this.name.set("Guest");
    this.isLoggedIn.set(false);
  }
}

// Create a molecule from the class

const userStore = molecule(UserStore);

// Use the molecule

console.log(userStore().name()); // "Guest"

userStore().login("Alice");

console.log(userStore().isLoggedIn()); // true

🔄 XProvider: Context Management

XProvider allows you to provide and consume context across your application.

import { html } from "lit-html";

import { view, useContext } from "mates";

// Create a context class

class ThemeContext {
  theme = "light";

  toggleTheme() {
    this.theme = this.theme === "light" ? "dark" : "light";
  }
}

// Provider component

const ThemeProvider = view(
  (props) => {
    const themeContext = new ThemeContext();

    return () => html`
      <x-provider .value=${themeContext}> ${props().children} </x-provider>
    `;
  },

  { children: [] }
);

// Consumer component

const ThemedButton = view(() => {
  // Get context instance

  const theme = useContext(ThemeContext);

  return () => html`
    <button class="${theme.theme}-theme" @click=${() => theme.toggleTheme()}>
      Toggle Theme (Current: ${theme.theme})
    </button>
  `;
}, {});

🎮 Complete Example

Here's a complete todo list example that showcases Mates' features:

import { html } from "lit-html";

import { view, bubble, atom } from "mates";

// Create state with a bubble

const todos = bubble((setter) => {
  let items = [];

  let newTodoText = "";

  const setNewTodoText = setter((text) => {
    newTodoText = text;
  });

  const addTodo = setter(() => {
    if (newTodoText.trim()) {
      items.push({ text: newTodoText, completed: false });

      newTodoText = "";
    }
  });

  const toggleTodo = setter((index) => {
    items[index].completed = !items[index].completed;
  });

  const deleteTodo = setter((index) => {
    items.splice(index, 1);
  });

  return () => ({
    items,

    newTodoText,

    setNewTodoText,

    addTodo,

    toggleTodo,

    deleteTodo,
  });
});

// Create a view for the todo app

const TodoApp = view(() => {
  return () => {
    const {
      items,

      newTodoText,

      setNewTodoText,

      addTodo,

      toggleTodo,

      deleteTodo,
    } = todos();

    return html`
      <div class="todo-app">
        <h1>Todo List</h1>

        <div class="add-todo">
          <input
            value=${newTodoText}
            @input=${(e) => setNewTodoText(e.target.value)}
            @keypress=${(e) => e.key === "Enter" && addTodo()}
            placeholder="Add new todo"
          />

          <button @click=${addTodo}>Add</button>
        </div>

        <ul class="todo-list">
          ${items.map(
            (item, index) => html`
              <li class=${item.completed ? "completed" : ""}>
                <input
                  type="checkbox"
                  .checked=${item.completed}
                  @change=${() => toggleTodo(index)}
                />

                <span>${item.text}</span>

                <button @click=${() => deleteTodo(index)}>Delete</button>
              </li>
            `
          )}
        </ul>

        <div class="todo-stats">
          <p>${items.filter((item) => !item.completed).length} items left</p>
        </div>
      </div>
    `;
  };
}, {});

// Mount the app

document.body.appendChild(TodoApp);

🔄 Why Mates?

Mates gives you the power and simplicity of React hooks without the React! As a complete framework, it's perfect for:

  • Building lightweight web apps without other heavy frameworks

  • Adding reactivity to existing applications

  • Creating reusable, reactive components

  • Prototyping ideas quickly

📚 Learn More

Check out our examples to see more usage patterns and advanced framework features.

📄 License

MIT

Keywords

lit-html

FAQs

Package last updated on 31 Oct 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts