Skip to content

brandon-xyzw/simple-esg

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SimpleESG

Simple Esbuild Static Generator

Overview

This is a starter example that provides similar functionality to Eleventy or Astro.

The difference here is that it's not a framework. It's just an example of what is possible with simple tools and some relatively small scripts. Any convention I use is easily changeable just by tweaking the small amount of source code.

I use esbuild, node's built-in packages, and JSX (but only running on the server). On the client, you can use Highway or Taxi to make it a Single Page Application.

This project implements single file components with no client side cost. It builds HTML on the server for the client, with scoped CSS, and even allows you define a script which can be used on the client for hydration.

Instead of needing to learn a specific way to build subpages, or needing to organize your data in a certain way that a framework wants, this repository instead provides a template that you can change it to your liking.

I don't use TypeScript here, but because we're using esbuild, any file can be JS, JSX, TS, or TSX, just by changing the file extension.

Setup

npm i

npm run dev to start watching and building everything.

I recommend you install the Inline HTML plugin for VS Code which will get you CSS styling in the "components" I've defined

Overview

There is seemingly a lot of functionality packed in here, but all of it is accomplished without too much indirection.

The best way to understand what's going on is by reading the source code. There isn't much of it and it's fairly straight to the point. I recommend starting by looking at Layout.jsx, which takes in children components, so that we can reuse that exterior template for all the pages (Home.jsx, for example, places its content inside of the layout).

Layout.jsx defines the layout that all pages have currently. Any styles in here are global and aren't scoped. Here you can see where the bundle and script is included.

The example website you get when you run this project is meant to be some sort of blog. On the /blog route, we have a list of cards highlighing each blog post. Each one has a "See details" button, which opens up a subpage of the blog and a "See tags" button, which dynamically expands to reveal a list of tags. This entire blog is implemented in generator/components/Blog.jsx, which defines all the blog data, an entire page highlighting all the blog posts, defines subpages, with scoped style, and hydration in one file.

generator/generate.js defines essentially the entire "framework" if you want to call it that. It reads in components and generates HTML with an ad-hoc interface.

You could add behaviour to dynamically insert the bundle or style resources here when you are building out your functionality, but I have hardcoded them for simplicity.

Details

npm run dev watches generator/* and src/* for changes, which are then output into public/.

Here are the specifics:

  • generator/components/*.jsx: "Components" which are used in conjunction with generator/generate.js. These can be defined in any way you see fit

  • generator/generate.js: This is essentially the whole "framework".

  • public/: This is the root of where your web app is hosted. Non-generated files go in here, and generated files (HTML, CSS, and JavaScript bundle) currently go here as well.

  • scripts/: These scripts are used from the scripts in package.json. They handle basic operations like building, watching, serving, and cleaning.

  • src/main.js: The entry point for bundle that is generated and stored as public/scripts/bundle.js. It's included in a page via a <script></script> wherever you want. Right now it's included in Layout.jsx, which is used as base for all pages, so the script is available on all pages in this example.

  • src/generated/client.js: is an auto-generated JavaScript file. If you defined a function designated for clientside use in a component, generator/generate.js will make this file as a module which can simply be imported from anywhere.

    • A client side script is defined on the "server" through a component with clientData

      export default {
      	componentId,
      	component: Component
      	clientData: {
      		path: `/${componentId}`,
      		script: hydrateButtons,
      	}
      }

      Which can then get consumed on the client with:

      const clientScript = client.get(location.pathname);
      clientScript?.(); // Hydrate something, or do whatever you want
  • public/style/index.css. A CSS style generated by scraping whatever CSS was defined in a component.

    • If you defined any HTML element with a data-style-scope={componentId} attribute, then you can call
      import { css, scopeSelectors } from '../helpers';
      
      const Component = () => (
      	<article data-style-scope={componentId}>
      		<h2>lab</h2>
      	</artcile>
      );
      
      const componentStyle = scopeSelectors(`[data-style-scope=${componentId}]`, css`
      	p {
      		color: black;
      		margin: 20px;
      	}
      
      	.content {
      		background-color: white;
      		padding: 20px;
      		border-radius: 10px;
      	}
      `);
      
      export default {
      	componentId,
      	component: Component
      	style: componentStyle,
      }

Extra Details

On the client side I'm using https://highway.js.org to make this a single page web app, but you may also want to consider https://taxi.js.org.

You may see data-router-view={componentId} attributes around, and they are for consumption by Highway.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published