Introduction | Lucid.js

Lucid.js / Introduction

What is Lucid? 🔗

Lucid is a reactive component-based framework for building apps. It's lightweight and runs entirely in the browser.

Though feature-rich. Lucid is not nearly as deep as React or Vue, meaning it's much quicker to learn.

In Lucid, components are comprised of three elements - a HTML container tag, a script tag nd a style tag, with only the former being mandatory.

  • Reactive Your views update as your data changes - no need to write imperative DOM-updating code
  • Component-based Organise your app into components, each with a single job and with its own logic and styles
  • Clean HTML Handle nearly everything from component JS, not weird directives or invented attributes in the HTML
  • Powerful router Support for hash and push-state navigation, with automated fetch request bindings
  • State mangement State management out of the box - save and revert to previous component states easily
  • Much more Smart event handling, inter-component messaging, semi-reactivity for heavy apps...

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. Here's a few:

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. Full or semi-reactive; the ability to elect for semi- rather than full-reactivity for heavier, more DOM-intensive apps
  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 🔗

create-lucid-app 🔗

These easiest way to start a Lucid app is to use the create-lucid-app scaffolding package:

npx create-lucid-app [options]

Or (equivalently):

npm init lucid-app [options]

This will set up everything you need to get up and running and even install and run a web server. Your app will be available in the browser at http://localhost:8080.

See the NPM readme for details of options you can pass to customise the setup.

Note that the scaffold will pull in Lucid from CDN, not a locally-hosted version.

Manual installation 🔗

To integrate Lucid into an existing setup, Lucid can be installed from Github or loaded via CDN.

<script type=module> import './lucid.js'; //or import ''; </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/bool; default: true) array or bool to govern Lucid's reactivity policy. Either an array of content types ( 'output', 'attrs', 'conds' and 'reps') or true for full reactivity). 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, each Lucid component lives in its own HTML file (the component name, in lowercase, with a .html file extension). It's also possible for all components to live in a single components file. Regardless, components are comprised of up to three parts:

  • HTML template
  • script tag - the component's JavaScript (scoped to the component)
  • style tag - the component's CSS

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

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

Did I help you? Feel free to be amazing and buy me a coffee on Ko-fi!