Lucid.js / Introduction

What is Lucid? 🔗

Lucid is a lightweight, component-based framework for building web apps. It's not nearly as deep as the likes of React and Vue, but it is super easy to learn and quick to get started.

Lucid is semi-reactive, but can be fully-reactive. It tries to strike a balance between reactivity and performance.

At hte heard of Lucid is the component trinity, where each component has a container tag, a style tag and a script tag (the latter two optional). In this way, it takes its lead from Svelte.

Hello, world! 🔗

Before we go any further, let's do the time-honoured "Hello world" example.

Try it in the Playground!

new Lucid({ container: '#mycontainer', compsFile: 'comps.html' });

And then our components file, comps.html:

<!-- COMPONENT MASTER --> <h1>{{message}}</h1> <script> = 'Hello, world!'; </script>

This demo uses a single components file. It's also possible to have each component in its own, separate file, for larger apps.

Playground 🔗

You can play around with Lucid in the Lucid Playground, a browser-hosted sandbox area for bulding Lucid apps. You can access it at:

Throughout this documentation you'll find links to Playground sessions that demonstrate certain functionality.

Almost everything is possible in the Playground, but some instantiation params are not available.

Philosophy 🔗

Lucid was built with a specific philosophy as follows:

  1. Components should be HTML files, not JSX, or HTML declared inside JavaScript template literals.
  2. Simplistic, minimal API, and a correspondingly shallow learning curve.
  3. HTML templates should be unmuddied with invented syntax. Almost everything is run from a component's JavaScript, not directives declared on HTML tags.
  4. Semi-reactivity (though full reactivity is available); by default, it's not as reactive as, say, Vue, but is nicely performant because of it.
  5. Low religiosity; Lucid does not impose a specific direction of travel for data; parent/ancestor components can interact with child/descendant components, and vice-versa.
  6. No compiler or preparsers; Lucid does its thing at runtime. Lucid likes offloading work to (very capable) modern browsers.

Core concepts 🔗

Here's some of the main concepts behind Lucid:

Components 🔗

Components are self-contained chunks of your app. Each has a HTML template and, optionally, a style tag and script tag to handle its look and behaviour respectively. Components can reference child components, and pass "props" (data) to them.

Read more: Components

Repeaters 🔗

Repeaters are used to output elements or child components iteratively - i.e. a given number of times, each fed different data. An example would be a list of products - we would repeat the li tag once per product, and each li would be fed the name of the product to output.

Read more: Repeaters

Conditionals 🔗

Conditionals are used to handle conditional rendering of elements or child components, based on the evaluation of some condition. The targeted element or component may be rendered or unrendered later if the evaluation result changes.

Read more: Conditionals

Variables 🔗

Variable are used in components' HTML templates and are swapped out for runtime data. The source of this data can vary, and the output can first be run through a filter method if need be (to modify it in some way).

Read more: Variables

Routes 🔗

Routes make your app navigable. By defining routes you can stipulate URL patterns and even web service URIs that should be fetched when the URL becomes active. Routes go great with conditionals; perhaps a child component should render only when and if a certain route is active.

Read more: Routes

States 🔗

States allow you to snapshot a component at a particular time and return to that state later. There's two types of state: indexed states, which work like an undo/redo delta, and persistent states, which have names and can't be overwritten by undo/redo traversal.

Read more: States

Selectors 🔗

CSS-style selectors are used widely with Lucid. Both conditionals and repeaters are declared by targeting the elements/child components to be conditionalised or repeater with selectors. This differs from other frameworks, where such things are handled by directives within the HTML.

Read more: Selectors

Installation 🔗

Lucid can be installed from Github or loaded via CDN.

<script type=module> import './lucid.js'; //or import '[email protected]/lucid.min.js'; </script>

If loading via CDN, it's better to load a specific version, rather than 'latest', as future updates may break your code. Replace "latest" with a release tag such as e.g. 1.0.0.

Then initiate Lucid by instantiating it:

<script type=module> import Lucid from './lucid.js'; let app = new Lucid({ /* params */ }); </script>

Next, we'll take a look at the possible instantiation params.

Instantiation 🔗

As shown above, to use Lucid instantiate it by calling new Lucid(params), where params is an object of instantiation params:

Lucid accepts the following parameters when instantiating it. They are all optional, and all have default values where the param is omitted.

  • container (string; object; default: "body") - the container for the app. Either a reference to an HTML element or a string acting as a selector to it.
  • compsPath (string; default: "./") - the path to the component file(s).
  • compsFile (string; default: null) - the filename of a master components file, which contains data for all components rather than each component having its own file.
  • data (object; default: null) - an optional object of "start" props to pass in to the master component. See Components > Props.
  • masterComponent (string; default: "master") - the name of the app's master component.
  • noCacheCompFiles (boolean; default: false) - if true, the contents of component files will not be cached.
  • methods (object; default: null) - an object of methods that can be used to filter data passed between components. See Variables > Filter methods.
  • routes (object; default: null) - a map of routes data, with keys denoting route IDs and values as objects with route config. See Routes.
  • reinsCaching (bool; array; default: false) - whether child components should be reinstated from cache rather than fresh when they are reinstated by a parent's reprocessed conditional - true for all components, or an array of some component names for which this is true.
  • autoReprocess (array; default: ['output', 'attrs']) - an optional array to govern Lucid's reactivity policy. Valid items in the array are 'output', 'attrs', 'conds' and 'reps'. See Reactivity.
  • usePushState (bool; default: false) - if true, routes will be activated via the Push State API rather than changing the URL hash. See Routes.

Components 🔗

Components are at the heart of Lucid. Usually, Lucid components live in their own HTML file (i.e. with a .html file extension) and are comprised of up to three parts:

  • style tag - the component's CSS
  • HTML template
  • script tag - the component's JavaScript

The style and script tags are optional, whereas the HTML template is mandatory.

Next, we'll take a look at components in more detail.