Lithe
Welcome Getting started Routing Build Signals and binding Web component Templates View transitions Fetcher Multiple languages github-circle-black-transparent GitHub github-circle-black-transparent Example app

Getting started

Material theme, colors, motion, font

Install

npm install @thewebformula/lithe
          

Routing

@thewebformula/lithe uses directory based routing. All routes go in a 'routes' folder.
app/
└── routes/
    ├── index/
    │   └── index.js     # /
    ├── 404/
    │   └── index.js     # /404 (or any url that is not found)
    ├── one/
    │   └── index.js     # one/
    ├── two[id?]/
    │   └── index.js     # two/:id?
    ├── three/
    │   └── [id]/
    │       └── index.js # three/:id
    └── four/
        └── [...all]/
            └── index.js # four/* (four/a/b/)
          
app/routes/index/index.js → /
app/routes/one/index.js → one
app/routes/two[id?]/index.js → two/:id?
app/routes/three/[id]/index.js → three/:id
app/routes/four/[...rest]/index.js → four/*
Directory route details
routes/index/index.js Root page (/)
routes/404/index.js Not found page. Auto redirect on non matching routes
index.js Route component file
[id] Directory that represents a url parameter
[id?] Directory that represents an options url parameter
name[id?] Inline url parameter to avoid sub folder
[...rest] Directory that represents catch-all route
[...rest?] Directory that represents optional catch-all route

index.html

<!doctype html>
  <html lang="en">
  
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="Cache-Control" content="no-store" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
    <!-- overridden by page titles -->
    <title>Default Title</title>
    
    <!-- app.js and app.css will automatically be updated to match bundle outputs -->
    <link href="app.css" rel="stylesheet">
    <script src="app.js" type="module"></script>
  </head>
  
  <body>
    <!-- page template render into this element -->
    <page-content></page-content>

    <!-- Alternative using id attribute -->
    <div id="page-content"></div>
  </body>
</html>
          

Splash screen

You can add a splash screen to your app
  • Only shows if load takes longer than 300 milliseconds
  • Splash screen will show for a minimum of 1.2 seconds
  • A default splash screen is provided using the PWA icon
  • You can override the default splash screen with custom HTML (example below)
<!doctype html>
  <html lang="en">
  
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="Cache-Control" content="no-store" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">


    <!-- Add meta tag for splash screen -->
    <meta name="splash-screen" content="true">
  </head>
  
  <body>
    ...
  </body>
</html>
                

<!-- Add custom splash screen HTML -->

<!doctype html>
  <html lang="en">
  
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="Cache-Control" content="no-store" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">


    <!-- Add meta tag for splash screen -->
    <meta name="splash-screen" content="true">
  </head>
  
  <body>

    <!-- Overrides default splash screen -->
    <splash-screen>
      ...HTML
    </splash-screen>
    
    ...
  </body>
</html>
                

Main application file

app.js
Required: Automatically uses app.js as entry file for bundling
/* Main app file
* you can import any code in here
*/

import someModule from './someModule.js';

// routes are automatically loaded
        
Prevent navigation allows you to lock down the app for uses like authentication
import { preventNavigation } from '@thewebformula/lithe';

// if not authenticated redirect to login and prevent navigation
if (!document.cookie.includes('authenticated=true')) {
  if (location.pathname !== '/login') location.href = '/login';
  preventNavigation(true);
}
          

Main application Styles

app.css
Optional: Will bundle and minify into a single file
@import url('./other.css');

body {
  background-color: white;
}
          

Page

page.js and page.html
import { Component, Signal, html } from '@thewebformula/lithe';
import htmlTemplate from './page.html'; // automatically bundles

export default class extends Component {
  // html page title
  static title = 'Page';

  /**
    * Pass in HTML string. Use for imported .HTML
    * Supports template literals: <div>${this.var}</div>
    * @type {String}
    */
  static htmlTemplate = htmlTemplate;

  someVar = new Signal('Some var');
  clickIt_bound = this.clickIt.bind(this);
  
  
  constructor() {
    super();
  }
  
  connectedCallback() {
    console.log(this.urlParameters); // { id: 'value' }
    console.log(this.searchParameters); // { id: 'value' }
  }
  
  disconnectedCallback() { }
  
  // not called on initial render
  beforeRender() { }
  
  afterEnder() {
    this.querySelector('#event-listener-button')
      .addEventListener('click', this.clickIt_bound);
  }
  
  clickIt() {
    console.log('clicked it!');
  }
  
  changeValue() {
    this.someVar.value = 'Value updated';
  }
  
  /**
  * Alternative method for html templates, instead of importing html file
  */
  template() {
    return html`
      <div>Page Content</div>
      <div>${this.someVar}</div>

      ${
        // nested html
        this.show ? html`<div>Showing</div>` : ''
      }

      <!--
        You can comment out expressions
        text
      -->
      
      <!-- "page" will reference the current page class -->
      <button onclick="page.clickIt()">Click Method</button>
      <button id="event-listener-button">Event listener</button>
      <button onclick="page.changeValue()">Change value</button>
    `;
  }
}
          

Build app

build.js
No need for webpack or other bundlers. ESbuild is packed in and pre configured.
Build config
import build from '@thewebformula/lithe/build';

/**
* runs dev server by default on port 3000 with livereload
* basedir defaults to 'app/'
*/
build({ basedir: 'app/' });
        
Run commands
# Development run
node build.js

# Development run with watch to enable livereload
node --watch-path=./app build.js

# Production run. minifies and gzips
NODE_ENV=production node build.js
          
menu