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