Like JSX, but native and fast

Overview

esx

Build Status Coverage js-standard-style

High throughput React Server Side Rendering

esx demo

For a simplified example of esx in action, check out esx-demo.

esx is designed to be a high speed SSR template engine for React.

It can be used with absolutely no code base changes.

Use it with a preloader flag like so:

node -r esx/optimize my-app.js

Note: transpiling is still experimental.

Alternatively babel-plugin-esx-ssr can be used to transpile for the same performance gains. The babel plugin would be a preferred option where speed of process initialization is important (such as serverless).

Optionally, esx is also a universal JSX-like syntax in plain JavaScript that allows for the elimination of transpilation in development environments.

  • For the server side, using esx syntax will yield the same high speed results as the optimizing preloader
  • For client side development, using esx syntax can enhance development workflow by removing the need for browser transpilation when developing in modern browsers
  • For client side production esx can be compiled away for production with babel-plugin-esx-browser, resulting in zero-byte payload overhead.

It uses native Tagged Templates and works in all modern browsers.

esx demo

Status

Not only is this project on-going, it's also following a moving target (the React implementation).

This should only be used in production when:

  • It has been verified to yield significant enough performance gains
  • It has been thoroughly verified against your current implementation

esx needs use cases and battle testing. All issues are very welcome, PR's are extremely welcome and Collaborators are exceptionally, extraordinarily, exceedingly welcome.

Install

npm i esx

Tests

There are close to 3000 passing tests.

git clone https://github.com/esxjs/esx
cd esx
npm i
npm test
npm run test:client # test client-side implementation in node
npm tun test:browser # test client-side implementation in browser

Syntax

Creating HTML with esx syntax is as close as possible to JSX:

  • Spread props: <div ...${props}>
  • Self-closing tags: <div />
  • Attributes: <img src="https://example.com/img.png"/> and <img src=${src}/>
  • Boolean attributes: <div draggable />
  • Components: <Foo/>
    • Components must be registered with esx: esx.register({Foo})

Compatibility

  • react v16.8+ is required as a peer dependency
  • react-dom v16.8+ is required as a peer dependency
  • esx is built for Node 10+
  • Supported Operating Systems: Windows, Linux, macOS

Limitations

esx should cover the API surface of all non-deprecated React features.

Notably, esx will not work with the Legacy Context API, but it will work with the New Context API.

While the legacy API is being phased out, there still may be modules in a projects depedency tree that rely on the legacy API. If you desperately need support for the legacy API, contact me..

Usage

As an optimizer

Preload esx/optimize like so:

node -r esx/optimize my-app.js

That's it. This will convert all JSX and createElement calls to ESX format, unlocking the throughput benefits of SSR template rendering.

As a JSX replacement

Additionally, esx can be written by hand for great ergonomic benefit in both server and client development contexts. Here's the example from the htm readme converted to esx (htm is discussed at the bottom of this readme):

// using require instead of import allows for no server transpilation
const { Component } = require('react') 
const esx = require('esx')()
class App extends Component {
  addTodo() {
    const { todos = [] } = this.state;
    this.setState({ todos: todos.concat(`Item ${todos.length}`) });
  }
  render({ page }, { todos = [] }) {
    return esx`
      <div class="app">
        <Header name="ToDo's (${page})" />
        <ul>
          ${todos.map(todo => esx`
            <li>${todo}</li>
          `)}
        </ul>
        <button onClick=${() => this.addTodo()}>Add Todo</button>
        <Footer>footer content here</Footer>
      </div>
    `
  }
}
const Header = ({ name }) => esx`<h1>${name} List</h1>`
const Footer = props => esx`<footer ...${props} />`

esx.register({ Header, Footer })

module.exports = App

In a client entry point this can be rendered the usual way:

const App = require('./App')
const container = document.getElementById('app')
const { hydrate } = require('react-dom') // using hydrate because we have SSR
const esx = require('esx')({ App })
hydrate(esx `<App page="All"/>`, container)

And the server entry point can use esx.renderToToString for high speed server-side rendering:

const { createServer } = require('http')
const App = require('./App')
createServer((req, res) => {
  res.end(`
    <html>
      <head><title>Todo</title></head>
      <body>
        <div id="app">
        ${esx.renderToString `<App page="All"/>`}
        </div>
      </body>
    </html>
  `)
}).listen(3000)

API

The esx module exports an initializer function, which returns a template string tag function.

Initializer: createEsx(components = {}) => esx

The default export is a function that when called initializes an instance of esx.

import createEsx from 'esx'
const createEsx = require('esx')

The initializer takes an object of component mappings which it then uses to look up component references within the template.

When called, the Initializer returns a Template Engine instance.

Template Engine: esx`<markup/>` => React Element

The result of the Initializer is a Template Engine which should always be assigned to esx. This is important for editor syntax support. The Template Engine instance is a template tag function.

import createEsx from 'esx'
import App from 'components/App'
const esx = createEsx({ App }) // same as {App: App}
// `esx` is the Template Engine
console.log(esx `<App/>`) // exactly same result as React.createElement(App)

Component Registration

A component must be one of the following

  • function
  • class
  • symbol
  • object with a $$typeof key
  • string representing an element (e.g. 'div')

createEsx(components = {})

Components passed to the Initializer are registered and validated at initialization time. Each key in the components object should correspond to the name of a component referenced within an ESX template literal.

esx.register(components = {})

Components can also be registered after initialization with the esx.register method:

import createEsx from 'esx'
import App from 'components/App'
const esx = createEsx()
esx.register({ App })
// exactly same result as React.createElement(App)
console.log(esx `<App/>`) 

Each key in the components object should correspond to the name of a component as referenced within an ESX template literal.

esx.register.one(name, component)

A single component can be registered with the esx.register.one method. The supplied name parameter must correspond to the name of a component referenced within an ESX template literal and the component parameter will be validated.

esx.register.lax(components = {})

Advanced use only. Use with care. This is a performance escape hatch. This method will register components without validating. This may be used for performance reasons such as when needing to register a component within a function. It is recommended to use the non-lax methods unless component validation in a specific scenario is measured as a bottleneck.

esx.register.lax.one(name, component)

Advanced use only. Use with care. This is a performance escape hatch. Will register one component without validating.

Server-Side Rendering: esx.renderToString`<markup/>` => String

On the server side every Template Engine instance also has a renderToString method. The esx.renderToString method is also a template literal tag function.

This must be used in place of the react-dom/server packages renderToString method in order to obtain the speed benefits.

import createEsx from 'esx'
import App from 'components/App'
const esx = createEsx()
esx.register({ App })
// same, but faster, result as ReactDomServer.renderToString(<App/>)
console.log(esx.renderToString `<App/>`)

Alias: esx.ssr

esx.renderToString(EsxElement) => String

The esx.renderToString method can also accept an element as its only parameter.

import createEsx from 'esx'
import App from 'components/App'
const esx = createEsx()
esx.register({ App })
const app = esx `<App/>`
// same, but faster, result as ReactDomServer.renderToString(app)
console.log(esx.renderToString(app))

Elements created with esx contain template information and can be used for high performance rendering, whereas a plain React element at the root could only ever be rendered with ReactDomServer.renderToString.

That is why esx.renderToString will throw if passed a plain React element:

// * DON'T DO THIS!: *
esx.renderToString(React.createElement('div')) // => throws Error
// instead do this:
esx.renderToString `<div/>`
// or this: 
esx.renderToString(esx `<div/>`)

Plugins

Pre and Post plugins are also provided to allow for additional manipulation of templates and output. A Post plugin could be used to write output directly to a stream, or inject additional HTML.

esx.plugins.pre((strings, ...values) => [strings, values])

The esx.plugins.pre method registers a Pre plugin. Plugins will be executed in the order that there are registered.

A Pre plugin should be passed a function that has the same signature as a tagged template function.

It must return an array containing two arrays. The first is an array of strings, the second is an array of values.

The pre plugin can be used to reshape the strings array and/or apply mutations to the interpolated values. An example of a Pre plugin could be to apply a transform, turning an alternative template syntax (such as Pug) into ESX syntax.

esx.plugins.post((htmlString) => htmlString))

The esx.plugins.post method registers a Post plugin. Plugins will be executed in the order that there are registered. Unlike Pre plugins, Post plugins can only be used Server Side and will only be invoked for components that are rendered via esx.renderToString.

A Post plugin is passed the HTML string output of a component at the time it is rendered. A Post plugin can be used to inject extra HTML, apply additional transforms to the HTML, or capture the HTML as each component is being rendered.

SSR Options

On the server side the Initializer has an ssr property, which has an options method. The follow options are supported:

createEsx.ssr.option('hooks-mode', 'compatible'|'stateful')

By default the hooks-mode option is compatible with React server side rendering. This means that any stateful hooks, e.g. useState and useReducer do not actually retain state between renders.

The following will set hooks-mode to stateful:

createEsx.ssr.option('hooks-mode', 'stateful')

This means that useState, useReducer, useMemo and useCallback have the same stateful behaviour as their client-side counterpart hooks. The state is retained between renderToString calls, instead of always returning the initial state as with compatible mode. This can be useful where a server-side render-to-hydrate strategy is employed and a great fit with rendering on server initialize.

Contributions

esx is an OPEN Open Source Project. This means that:

Individuals making significant and valuable contributions are given commit-access to the project to contribute as they see fit. This project is more like an open wiki than a standard guarded open source project.

See the CONTRIBUTING.md file for more details.

The Team

David Mark Clements

https://github.com/davidmarkclements

https://www.npmjs.com/~davidmarkclements

https://twitter.com/davidmarkclem

Prior Art

ESX

esx was preceded by... esx. The esx namespace was registered four years ago by a prior author Mattéo Delabre , with a similar idea. He kindly donated the namespace to this particular manifestation of the idea. For this reason, esx versioning begins at v2.x.x. Versions 0.x.x and 1.x.x are deprecated.

Hyperx

esx is directly inspired by hyperx, which was the first known library to this authors knowledge to make the point that template strings are perfect for generating both virtual doms and server side rendering. What hyperx lacks, however, is a way to represent React components within its template syntax. It is only for generating HTML nodes.

HTM

It's not uncommon for similar ideas to be had and implemented concurrently without either party knowing of the other. While htm was first released early 2019, work on esx had already been on-going some months prior. However the mission of esx is slightly broader, with a primary objective being to speed up server side rendering, so it took longer to release.

License

MIT

Sponsors

Comments
  • Webpack: Critical dependency: the request of a dependency is an expression

    Webpack: Critical dependency: the request of a dependency is an expression

    Webpack can't deal with tryToLoad function. As a result – it simply skips requiring a module and ESX has no react in runtime.

    WARNING in ./node_modules/esx/index.js 1000:11-24
    Critical dependency: the request of a dependency is an expression
        at CommonJsRequireContextDependency.getWarnings (/.../node_modules/webpack/lib/dependencies/ContextDependency.js:40:18)
        at Compilation.reportDependencyErrorsAndWarnings (/.../node_modules/webpack/lib/Compilation.js:1356:24)
        at /.../node_modules/webpack/lib/Compilation.js:1164:10
        at AsyncSeriesHook.eval [as callAsync] (eval at create (/.../node_modules/tapable/lib/HookCodeFactory.js:32:10), <anonymous>:24:1)
        at AsyncSeriesHook.lazyCompileHook (/.../node_modules/tapable/lib/Hook.js:154:20)
        at Compilation.finish (/.../node_modules/webpack/lib/Compilation.js:1159:28)
        at /.../node_modules/webpack/lib/Compiler.js:622:17
        at _done (eval at create (/.../node_modules/tapable/lib/HookCodeFactory.js:32:10), <anonymous>:9:1)
        at eval (eval at create (/.../node_modules/tapable/lib/HookCodeFactory.js:32:10), <anonymous>:128:22)
        at /.../node_modules/webpack/lib/Compilation.js:1091:12
        at /.../node_modules/webpack/lib/Compilation.js:1003:9
        at processTicksAndRejections (internal/process/task_queues.js:75:11)
      @ ./src/apps/app/server.js
      @ multi ./src/apps/app/server.js
    
    opened by irudoy 3
  • esx.renderToString not working with element created in another instance

    esx.renderToString not working with element created in another instance

    esx.renderToString throws "%component% not found in registered components" when ESX element that was created in another ESX instance has been passed. I understand that it's kinda unusual case, but as from description of this project:

    It can be used with absolutely no code base changes.

    Example

    // index.js
    const esx = require('esx')()
    const getElement = require('./getElement')
    console.log(esx.renderToString(getElement('hi')))
    
    // getElement.js
    const esx = require('esx')()
    const Say = ({ word }) => esx`<div>${word}</div>`
    esx.register({ Say })
    module.exports = word => esx`<Say word=${word} />`
    

    Output

    ReferenceError: ESX: Say not found in registered components
    

    Repository with repro

    https://github.com/irudoy/esx-repro

    opened by irudoy 2
  • plugin system

    plugin system

    ability to register before / after plugins

    to allow things like: esx-pug or fast css module/styled-component solutions, possibly may also be the basis for multithreading etc.

    plugin interface should be based on of template literal funcs, so then it's easily composable

    const myPrePlugin = (strings, vals) => {
      const result = transform(strings)
      return [result, vals]
    }
    

    transform takes array and returns array

    Implementation would need cache via the original strings array (as usual), transform operation would happen on first run.

    A plugin will also need a browser transpiler counterpart, we'll maybe want something like an esx-plugin-transpiler module or something to make it trivial to build (or even cooler: maybe we can consume the plugin declaration and convert that into a transpiler for the browser)

    aft plugins would receive the complete string for a comps render

    const myPostPlugin = (str) => {
      return transform(str) // return String
    }
    

    This would be expensive and not encouraged, but a better use case is processing the output in some other way, e.g

    const myPostPlugin = (str) => {
      res.write(str) // immediately write string to stream
      return str // return same string (for components to compose with)
    }
    
    opened by davidmarkclements 1
  • Module not found: Error: debug tried to access supports-color (a peer dependency) but it isn't provided by its ancestors

    Module not found: Error: debug tried to access supports-color (a peer dependency) but it isn't provided by its ancestors

    Got those errors during webpack build, using yarn@berry:

        Module not found: Error: debug tried to access supports-color (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound.
    
        Required package: supports-color (via "supports-color")
        Required by: debug@virtual:ef2fb28f3185f9ba345cf0214d372bc8e04344320dd80b839f12ab23fbe300f7c2a62784bfffb92cb431640b461f8eb544464aadcc1823ebefc40d17e8ec16c9#npm:4.1.1 (via /.../.yarn/$$virtual/debug-virtual-be097de51f/0/cache/debug-npm-4.1.1-540248b3aa-3.zip/node_modules/debug/src/node.js)
    
         @ ./.yarn/$$virtual/debug-virtual-be097de51f/0/cache/debug-npm-4.1.1-540248b3aa-3.zip/node_modules/debug/src/node.js
         @ ./.yarn/$$virtual/debug-virtual-be097de51f/0/cache/debug-npm-4.1.1-540248b3aa-3.zip/node_modules/debug/src/index.js
         @ ./.yarn/cache/esx-npm-2.3.3-0851126841-3.zip/node_modules/esx/index.js
    
    opened by irudoy 2
  • optional chaining and rest spread?

    optional chaining and rest spread?

    Hi, my babel transpiling seems to be breaking with other things like optionals and rest spread plugins are used.I've put this esx-ssr at the end of the plugins array but i think maybe the acorn parser in to-esx doesnt read the transpiled code as all plugins are run in parellel maybe? Are you aware of any issues using this with other plugins like babel/plugin-proposal-optional-chaining?

    Error:

    Webpack Build Time For Server Build:  885 ms
    (node:36582) UnhandledPromiseRejectionWarning: Error: Module build failed (from ./node_modules/babel-loader/lib/index.js):
    SyntaxError: <REMOVED>/src/server.js: Unexpected token (36:33)
        at Object.pp$4.raise (<REMOVED>node_modules/acorn/dist/acorn.js:2825:15)
        at Object.pp.unexpected (<REMOVED>node_modules/acorn/dist/acorn.js:689:10)
        at Object.pp$3.parseExprAtom (<REMOVED>/node_modules/acorn/dist/acorn.js:2270:12)
        at Object.parseExprAtom (<REMOVED>/node_modules/acorn-jsx/index.js:445:22)
        at Object.pp$3.parseExprSubscripts (<REMOVED>/node_modules/acorn/dist/acorn.js:2089:21)
        at Object.pp$3.parseMaybeUnary (<REMOVED>/node_modules/acorn/dist/acorn.js:2066:19)
        at Object.pp$3.parseExprOps (<REMOVED>/node_modules/acorn/dist/acorn.js:2010:21)
        at Object.pp$3.parseMaybeConditional (<REMOVED>/node_modules/acorn/dist/acorn.js:1993:21)
        at Object.pp$3.parseMaybeAssign (<REMOVED>/node_modules/acorn/dist/acorn.js:1968:21)
        at Object.pp$3.parseMaybeConditional (<REMOVED>/node_modules/acorn/dist/acorn.js:1998:30)
        at Object.pp$3.parseMaybeAssign (<REMOVED>/node_modules/acorn/dist/acorn.js:1968:21)
        at Object.pp$1.parseVar (<REMOVED>/node_modules/acorn/dist/acorn.js:1228:26)
        at Object.pp$1.parseVarStatement (<REMOVED>/node_modules/acorn/dist/acorn.js:1092:10)
        at Object.pp$1.parseStatement (<REMOVED>/node_modules/acorn/dist/acorn.js:842:19)
        at Object.pp$1.parseBlock (<REMOVED>/node_modules/acorn/dist/acorn.js:1161:23)
        at Object.pp$3.parseFunctionBody (<REMOVED>/node_modules/acorn/dist/acorn.js:2671:24)
    
    

    fails on this line Screen Shot 2020-08-12 at 4 06 36 PM

    babel config Screen Shot 2020-08-12 at 4 02 58 PM

    opened by jamescharlesworth 1
  • `Warning: Each child in a list should have a unique

    `Warning: Each child in a list should have a unique "key" prop` with Text interleaved nodes

    First of all, thanks a lot for the incredible work on this library. I love the idea of not having to transpile only because of JSX and, of course, the performance boost makes it even better.

    Warning:

    Warning: Each child in a list should have a unique "key" prop.
    [1]
    Check the top-level render call using <footer>. See https://fb.me/react-warning-keys for more information.
        in a
        in Footer
        in div
        in AuthorsIndex
        in Context.Provider
        in Context.Consumer
        in Route
        in Context.Consumer
        in Switch
        in App
        in Context.Provider
        in Router
        in StaticRouter
    

    I am getting the warning above with the following code:

    import react from 'react'
    import esx from 'esx'
    
    const e = esx()
    
    export class Footer extends react.Component {
      render () {
        return e`
          <footer>
            Made with ♥ by <a target="_blank" href="x">@x</a>
            for <a target="_blank" href="y">Y</a>
          </footer>
        `
      }
    }
    
    e.register({ Footer })
    

    The same warning does not appear with the equivalent React (createElement) code:

    import react from 'react'
    
    const h = react.createElement
    
    export class Footer extends react.Component {
      render () {
        return (
          h('footer', null,
            'Made with ♥ by ',
            h('a', { target: '_blank', href: 'x' }, '@x'),
            ' for ',
            h('a', { target: '_blank', href: 'y' }, 'y')
          )
        )
      }
    }
    

    I am not sure what's the default React behaviour, but I suspect that this will be interpreted as the following DOM structure:

    footer
    ├── textNode
    ├── a
    └── textNode
    

    And possibly React automatically generates a key for every children element in this case.

    If my assumption is correct, Is this behaviour something that makes sense to implement in esx as well to avoid the warning? I also suspect this might have performance implications at runtime if the vDOM has to reconcile a transition with a big blob of text with anchors and other interleaved elements.

    For the sake of completeness this is the demo project I am testing esx with: univ.

    opened by lmammino 1
  • First of all nice implamentation not esm code but good cjs code

    First of all nice implamentation not esm code but good cjs code

    We Should allow to do dependency injection for react that means we don't put it in here as dependency we allow to init esx with something that does allow createElement and Fragment

    so this can be used with h() and preact and even in other implamentations that would be nice..

    opened by frank-dspeed 0
  • Not working with react-redux hooks API

    Not working with react-redux hooks API

    Invalid hook call. Hooks can only be called inside of the body of a function component.
        at /esx-repro-rr/node_modules/react-dom/cjs/react-dom-server.node.development.js:1136:26
        at resolveCurrentlyRenderingComponent (/esx-repro-rr/node_modules/react-dom/cjs/react-dom-server.node.development.js:1139:5)
        at Object.useContext (/esx-repro-rr/node_modules/react-dom/cjs/react-dom-server.node.development.js:1284:3)
        at Object.useContext (/esx-repro-rr/node_modules/esx/lib/hooks/compatible.js:51:21)
        at useContext (/esx-repro-rr/node_modules/react/cjs/react.development.js:1633:21)
        at useReduxContext (/esx-repro-rr/node_modules/react-redux/lib/hooks/useReduxContext.js:31:44)
        at useSelector (/esx-repro-rr/node_modules/react-redux/lib/hooks/useSelector.js:121:28)
        at A (/esx-repro-rr/app.esx.js:19:16)
        at renderComponent (/esx-repro-rr/node_modules/esx/index.js:516:18)
        at resolveChildren (/esx-repro-rr/node_modules/esx/index.js:956:25)
    

    Repro: https://github.com/irudoy/esx-repro-rr

    opened by irudoy 5
  • Document safety of handling user input (like JSX escaping)

    Document safety of handling user input (like JSX escaping)

    JSX provides automatic escaping which lets you put user input into JSX safely (and without thinking about it).

    Does esx provide this under the hood? I was unsure when looking through the ES6 template string examples so it would be helpful to document this in the readme.

    opened by kumar303 7
Owner
ESX
Like JSX.. but native and fast
ESX
A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebWorker like neither of those.

Amuchina A work-in-progress HTML sanitizer that strives for: performance like window.Sanitizer, readiness like DOMPurify, and ability to run in a WebW

Fabio Spampinato 9 Sep 17, 2022
Next-level academia! Repository for the Native Overleaf project, attempting to integrate Overleaf with native OS features for macOS, Linux and Windows.

Native Overleaf Overleaf is a fantastic webtool for writing and cooperating on LaTeX documents. However, would it not be even better if it were to beh

Floris-Jan Willemsen 40 Dec 18, 2022
✏️ Super lightweight JSX syntax highlighter, around 1KB after minified and gzipped

Sugar High Introduction Super lightweight JSX syntax highlighter, around 1KB after minified and gzipped Usage npm install --save sugar-high import { h

Jiachi Liu 67 Dec 8, 2022
A JSX transformer with extra hints around interpolations and outer templates.

@ungap/babel-plugin-transform-hinted-jsx This plugin is a follow up of this post and it can be used together with @babel/plugin-transform-react-jsx. A

ungap 12 Nov 12, 2022
Web Components engine based on JSX & TypeScript

WebCell Web Components engine based on JSX & TypeScript Usage Demo & GitHub template: https://web-cell.dev/scaffold/ Project bootstrap Command npm ini

null 162 Nov 17, 2022
High performance JSX web views for S.js applications

Surplus const name = S.data("world"), view = <h1>Hello {name()}!</h1>; document.body.appendChild(view); Surplus is a compiler and runtime to all

Adam Haile 587 Dec 30, 2022
Create a html response with JSX.

Htm Create a text/html response with JSX, powered by Preact and UnoCSS. Usage To use Htm, create a server.tsx file like this: /** @jsx h */ import {

X. 34 Dec 9, 2022
Converts JSX to HTML strings at compile time.

unplugin-jsx-string Converts JSX to HTML strings at compile time. Installation npm i unplugin-jsx-string Vite // vite.config.ts import JsxString from

三咲智子 9 Sep 3, 2022
Add the `className` to all JSX elements in your project

Babel Plugin Transform JSX Classes This babel plugin adds the className in each JSX element. Before After function FancyComponent () { return (

Xinhe 13 Jul 15, 2022
Unofficial Library for using Discord.JS with JSX Syntax.

@chooks22/discord.jsx WARNING! This project is in very early stage of development. And while I do have plans to finish it to completion, consider this

Chooks22 4 Nov 14, 2022
Use jsx to make scriptable's layout.

scriptable-jsx This project helps you to write Scriptable widgets with JSX syntax. And add some useful tools by the way. you can check demos in demo f

毛球 8 Oct 10, 2022
🖼️ Tiny JSX helper function for high-DPI (Retina Display) images.

img-srcx Tiny JSX helper function for high-DPI (Retina Display) images. 394 bytes minified and gzipped for ESM (830 bytes for ES5). Installation npm i

Chariz 4 Oct 6, 2022
Like Obsidian Publish but for self-hosting. Plugin integrations for dataview, admonition, and more.

Obsidian Export Obsidian Publish is great but lacks support for many of the plugins we Obsidian addicts have grown accustomed to — in particular Datav

null 12 Nov 28, 2022
Simple but Complete & Fast network monitor for your home network

netmon Netmon is an opensource project for protecting and monitoring your home network. Netmon is written to run on a Raspberry PI and is optimized to

Tommaso Ventafridda 9 Jul 6, 2022
Enables creating databases based on files in Obsidian - like Dataview, but with editing!

Obsidian Database Plugin Do you like Dataview plugin for Obsidian? This one is taking Dataview to next level, but not only allowing you to view the da

Łukasz Tomaszkiewicz 115 Jan 4, 2023
📦 Writing Express but feel like Spring Boot

Springpress Custom top-level framework of Express.js, especially on TypeScript. Springpress provides expressjs utilities out of the box, lets you deep

Vectier 8 Oct 14, 2022
Like useReducer, but runs in a worker.

useWorkerizedReducer useWorkerizedReducer is like useReducer, but the reducer runs in a worker. This makes it possible to place long-running computati

Surma 221 Dec 1, 2022
Javascript library for switching fixed elements on scroll through sections. Like Midnight.js, but without jQuery

Library for Switching Fixed Elements on Scroll Sometimes designers create complex logic and fix parts of the interface. Also they colour page sections

Vladimir Lysov 38 Sep 19, 2022