Delgada
An HTML-first web framework for building slim UIs.
Delgada is a small HTML-first web framework for building slim multipage websites using modern web standards and conventions.
Noteworthy features include:
- Ship zero JS to the client by default with static components
- Islands of interactivity with web components
- File-system based routing
- Markdown support out of the box
- Zero config with common sense defaults
Getting started
Try getting started with the Delgada template. Install the template with the following command and then follow the directions in the project readme.
$ npx degit delgada-ui/template my-delgada-project
Concepts
Project structure
The structure of a Delgada website tries to follow modern web conventions and should hopefully feel straightforward and familiar to most reading this.
my-website/
├── public/
│ ├── favicon.png
│ └── global.css
├── src/
│ ├── components/
│ │ ├── islands/
│ │ │ └── WebComponent.js
│ │ └── StaticComponent.js
│ └── pages/
│ ├── blog/
│ │ ├── _template.js
│ │ ├── post-1.md
│ │ └── post-2.md
│ ├── _template.js
│ └── index.js
├── package.json
└── web-dev-server.config.mjs
The root of the project is where various project config files live such as package.json
and notably web-dev-server.config.mjs
. Delgada uses Web Dev Server as its development server and the config file contains a plugin for serving Delgada websites.
A public
directory contains all the static assets. Similar to Next.js, all files in this directory are served to the client (unchanged/unaltered) at the root URL (/
).
If, for example, there's a file called global.css
, it will be served at /global.css
and can be referenced in website markup like so:
<link rel="stylesheet" href="/global.css" />
Finally, a src
directory will typically contain a components
directory and a pages
directory.
The components
directory is where components will live. If you're website has no components at all this directory is optional.
The pages
directory is where website pages will live. This directory is required and supports .js
or .md
files.
Static components
At the core of Delgada is a distinct separation between components that are static (i.e. send HTML/CSS to the client) and components that are dynamic (i.e. send HTML/CSS/JavaScript to the client).
This section will focus on static components –– dynamic components/islands will be dicussed later on.
To quickly break it down:
- Static components are authored in
.js
files - Static components are functions that return a string of HTML
- Static component props are function arguments
- Static component styles are variables that contain a string of CSS
import { html, css } from 'delgada';
export function Greeting({ name }) {
return html`<h1>Hello ${name}!</h1>`;
}
export const styles = css`
h1 {
color: red;
}
`;
Template syntax
Delgada uses tagged templates as its templating syntax. An html
and css
tag function are available and can be used to write expressive markup and styling like so:
// Basic markup and styles
html`<h1>Hello world!</h1>`;
css`
h1 {
color: red;
}
`;
// Use JavaScript expressions directly in markup/styles
const name = 'Universe';
const color = 'purple';
html`<h1>Hello ${name}!</h1>`;
css`
h1 {
color: ${color};
}
`;
// Conditional rendering/styles
const age = 24;
let darkMode = true;
html`<p>You ${age >= 16 ? 'can' : 'cannot'} drive.</p>`;
css`
body {
background: ${darkMode ? 'black' : 'white'};
}
`;
// Mapping over data to generate markup/styles
const fruits = ['apple', 'banana', 'orange'];
const tokens = [
{ name: 'primary-color', value: 'rgb(210, 210, 210)' },
{ name: 'secondary-color', value: 'rgb(180, 180, 180)' },
];
html`
<ul>
${fruits.map((fruit) => html`<li>${fruit}</li>`)}
</ul>
`;
css`
:root {
${tokens.map((token) => css`--${token.name}: ${token.value};`)}
}
`;
The html
and css
function accepts an array of strings that are separated by an arbitrary set of value arguments (which represent JavaScript expressions that may exist in a template). It builds up these different parts into an array of strings that are then joined and returned as the final rendered HTML.
It also notably has some special logic for handling expressions that map over arrays of data to generate markup/styles –– something that is not cleanly handled in regular JavaScript template literals.
A note on tagged template developer experience
By default, tagged templates will be rendered/treated as strings in code editors which results in a less than ideal developer experience when writing component markup/styles. This, however, can be changed with extensions/tooling.
In the case of VS Code, installing the lit-html and es6-string-html extensions make a world of difference while writing HTML/CSS in tagged templates. They can be used to add a ton of helpful features like syntax highlighting, IntelliSense, quick hover info, HTML tag folding, and so on.
Emmet support inside tagged templates can also be enabled in VS Code by changing the "Emmet: Include Languages" setting and adding mappings for "javascript": "html"
and "typescript": "html"
.
Using static components
To use a static component simply import and add the component function within the markup of another static component.
To correctly pick up the styles of a component, they also must be imported and added to the styles of the target component as shown in the below code snippet.
import { html, css } from 'delgada';
import { Greeting, styles as GreetingStyles } from 'Greeting.js';
export function Hero() {
return html`
${Greeting({ name: 'Reader' })}
<p>This is the home page.</p>
`;
}
export const styles = css`
p {
color: blue;
}
${GreetingStyles}
`;
Pages
More details coming soon.
Page templates
More details coming soon.
Routing
More details coming soon.
Dynamic components
More details coming soon.
Markdown
Delgada comes with markdown support built in. More details coming soon.