Home

Awesome

<p align="center"> <a href="https://harlemjs.com"> <img src="https://raw.githubusercontent.com/andrewcourtice/harlem/main/docs/src/public/assets/images/logo-192.svg" alt="Harlem"/> </a> </p>

Harlem

Build and Test npm

Powerfully simple global state management for Vue 3. Head over to harlemjs.com to get started or take a look at the demo to see it in action.

<!-- TOC depthfrom:2 depthto:2 --> <!-- /TOC -->

Foundations

Simple

Harlem has a simple functional API for creating, reading and mutating state. From the most basic global state management needs to the most complex, Harlem has you covered.

Safe

All state exposed from a Harlem store is immutable. State can only be changed through mutations/actions making your state predictable and auditable.

Modular

Harlem is super lightweight, tree-shakeable, and dependency-free! It is designed to be used with native ES modules so even unused parts of your stores (getters, mutations, actions etc.) can be tree-shaken.

Extensible

Harlem comes with a suit of official extensions that allow you to add extra features to your stores such as cancellable actions, tracing, transactions, undo/redo, and more. You can even write your own extension or plugin.

Great DX

Harlem has a great developer experience. It's built using TypeScript so all of your state, getters, and mutations are strongly typed. Harlem also has Vue devtools integration so you can explore your stores and see store events on the timeline in realtime.

Battle-Tested

Harlem is built by enterprise software engineers and used in medium-large enterprise software. It's built to handle even the most complex state management use-cases.

Features

Check out the docs for more details.

Getting Started

Getting started with Harlem is easy. Just follow the steps below and you'll be up and running in no time.

Installation

Install harlem and any plugins/extensions you wish to include.

# yarn
yarn add harlem

# npm
npm install harlem

The devtools plugin is enabled by default during development and tree-shaken out of production builds. If you don't need devtools during develpment, you can instead install harlem from @harlem/core

If you're using Nuxt, instead follow the instructions to install the Nuxt module and then resume this guide below, at Create your first store.

Register the Harlem Vue plugin

Register the Harlem plugin with your Vue app instance:

import App from './app.vue';

import {
    createVuePlugin
} from 'harlem';

createApp(App)
    .use(createVuePlugin())
    .mount('#app');

Create your first store

Create your store and define any getters, actions or mutations:

import {
    createStore
} from 'harlem';

// The initial state for this store
const STATE = {
    firstName: 'John',
    lastName: 'Smith'
};

// Create the store, specifying the name and intial state
export const {
    state, 
    getter,
    mutation,
    action,
    ...store
} = createStore('user', STATE);

export const fullName = getter('fullname', state => `${state.firstName} ${state.lastName}`);

export const setFirstName = mutation('set-first-name', (state, payload: string) => {
    state.firstName = payload;
});

export const setLastName = mutation('set-last-name', (state, payload: string) => {
    state.lastName = payload;
});

export const loadDetails = action('load-details', async (id: string, mutate) => {
    const response = await fetch(`/api/details/${id}`);
    const details = await response.json();

    mutate(state => {
        state.details = details;
    });
});

Use your store in your app

To use your store in your app just import the parts of it you need.

<template>
    <div class="app">
        <h1>Hello {{ fullName }}</h1>
        <button @click="loadDetails()">Load Details</button>
        <input type="text" v-model="firstName" placeholder="First name">
        <input type="text" v-model="lastName" placeholder="Last name">
    </div>
</template>

<script lang="ts" setup>
import {
    computed
} from 'vue';

import {
    state,
    fullName,
    setFirstName,
    setLastName,
    loadDetails
} from './stores/user';

const firstName = computed({
    get: () => state.firstName,
    set: value => setFirstName(value)
});

const lastName = computed({
    get: () => state.lastName,
    set: value => setLastName(value)
});
</script>

Extensibility

Harlem uses a combination of extensions and plugins to extend core functionality.

Extensions

Extensions are per-store additions to Harlem's core functionaility. Extensions are often used for adding store features, changing store behaviour and various other low-level tasks. This is the primary method in which Harlem stores are extended. Feel free to choose from some of the official extensions or write your own. See the extensions documentation from more information on the official set of extensions or how to author your own plugin.

The official extensions include:

Plugins

Plugins are global extensions to Harlem's core functionality. Plugins are often used for generic store operations like tracking events and collating state. Feel free to choose from some of the official plugins or write your own. See the plugins documentation from more information on the official set of plugins or how to author your own plugin.

The official plugins include:

Documentation

Full documentation for Harlem is available at https://harlemjs.com.

Credits

Logo design by Ethan Roxburgh