Landing Starter Template based on TailwindCSS, AlpineJs and build on esbuild and PostCSS
Tags: starter, html, javascript, css
Published: 2021-02-14 10:27:56

One of the constant requests I have as a freelancer programmer is constructing a landing page for a project/company/research project. Therefore, it is better to have an already starter template adopted as a base to iterate upon it quickly.

[My starter](https://github.com/wittyprogramming/tailwindcss-alpinejs-starter), is an opinionated template that has the following features:

- Tailwind CSS for styling
- Alpine.js for template/dynamic logic
- a simple build system that may help me scale up if the needs arise (for example, add scss for styles or Typescript)

[Tailwind CSS](https://tailwindcss.com/) is a highly customizable, low-level CSS framework gaining popularity lately.  It is not opinionated as it gives you the building blocks for styling your components.

Unfortunately, tailwind requires a build system to take advantage of all its features. Furthermore, during deployment, the unused CSS must be removed because the style file becomes very large (>2Mb). The  [PostCSS](https://postcss.org/) and its plugins come to the rescue.

[Alpine.js](https://github.com/alpinejs/alpine) is very similar to tailwind but for the javascript. It provides the features of [Vue.js](https://vuejs.org/) with a much lower cost and - I think - a most suitable replacement for [jQuery](https://jquery.com/) than other frameworks.  If the code requirements are very light, then a build system is not required. Just add the  Alpine.js package in a script tag and sprinkle your login in the HTML DOM file.

I must say that Alpine.js, which does not use a virtual DOM, has some tricked spots regarding the scope of nested components and their communication or the way nested loops are constructed, but for most cases - e.g., landing pages - is adequate. For more information, check out out my post introducing Alpine.js:

{% link kzagoris/introducing-alpinejs-the-ideal-jquery-replacement-jfa %} 

My preference is to use [Typescript](https://www.typescriptlang.org/) (I love the IntelliSense capabilities that provide); therefore, I use the Evan Wallace's [esbuild](https://github.com/evanw/esbuild), a fast Javascript/Typescript bundler, and a minifier.

Finally, we will use the gorgeous, simple, and versatile landing page design from the [Creative Tim's Tailwind Starter Kit](https://www.creative-tim.com/learning-lab/tailwind-starter-kit/presentation) for our starter template's design. It way better for our productivity to have a well-formed, responsive design as a base.

## Template initialization

Let's initialize our starter:

```shell
md tailwindcss-alpinejs-starter
cd tailwindcss-alpinejs-starter
npm init
```

The structure of the template is straightforward:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ohg1dor44jl97xmnd0x9.jpg)

- `src/css/` folder contains our template's source styles with the file `main.css` as the entry point.
- `src/ts/` folder contains our typescript code with the file `main.ts` as the entry point.

The `assets/` folder contains the static assets - img, files to downloads, etc. Here, the output files from the CSS (CSS and web fonts) and js (js file) build system will be created.

Let's begin by getting the `landing.html` and the Landing Page starter kit's assets folder. We don't need the `vendor` directory (contains fontawesome icons)  as we will self-hosted it ourselves.

Then, install the required packages:

```shell
npm install alpinejs tailwindcss @fortawesome/fontawesome-free
```

## PostCSS configuration

It is time to create a build system for the styles based on [PostCSS](https://postcss.org/), a modern plugin-based CSS parser. The `src/css/` folder contains our source CSS, which builds a minified clean version in the file `assets/style.css`.

Next, install the dev dependencies:

- `postcss` packages,
- its cli version,
- and the plugins:
  - `postcss-import` for using the import function in CSS,
  - `@fullhuman/postcss-purgecss` for the purgings of the unused CSS styles,
  - `postcss-copy` for copying assets referenced as web fonts , and, of course, 
  - the `cssnano` package for the minification.

```shell
npm install postcss postcss-cli postcss-import cssnano @fullhuman/postcss-purgecss  --save-dev
```

Our `postcss.config.js`  is:

```javascript
const purgecss = require("@fullhuman/postcss-purgecss")({
  // Specify the paths to all of the template files in your project
  content: ["./index.html"],
  // This is the function used to extract class names from your templates
  defaultExtractor: (content) => {
    // Capture as liberally as possible, including things like `h-(screen-1.5)`
    const broadMatches = content.match(/[^<>"'`\s]*[^<>"'`\s:]/g) || [];

    // Capture classes within other delimiters like .block(class="w-1/2") in Pug
    const innerMatches = content.match(/[^<>"'`\s.()]*[^<>"'`\s.():]/g) || [];

    return broadMatches.concat(innerMatches);
  },
});

module.exports = {
  plugins: [
    require("postcss-import")(),
    require("tailwindcss")(),
    require("autoprefixer")(),
    require("postcss-copy")({
      dest: "assets/webfonts",
    }),
    ...(process.env.ENV_BUILD === "prod" ? [purgecss] : []),
    ...(process.env.ENV_BUILD === "prod" ? [require("cssnano")()] : []),
  ],
};
```

The postcss.config.js format is straightforward. We define our plugins,  and when we initiate the deployment build by using an environmental variable, we use the purge CSS and minification plugins.

The `package.json` build scripts are:
```json
"watch-css": "postcss src/css/main.css -o assets/css/style.css -w",
"build-css": "cross-env ENV_BUILD=prod postcss src/css/main.css -o assets/css/style.css"
```

The `cross-env` is an npm package that sets environment variables in a cross-platform away.

## esbuild configuration

Next step, the `esbuild` is added. After version v0.8.38, the esbuild added a `-watch` and after the v0.8.45, the esbuild added the `--servedir=` flag, allowing running a built-in web development server. 

I like to use Typescript, as the IntelliSense that provides is impressive and very helpful. I understand that Typescript is not everyone's favourite, and it may complicate some things unnecessary. Hence, the following step is not required, but to acquire the Typescript's Intellisense superpower, install the `typescript` packages and initialize a `tsconfig.js` in the `src/ts` folder.

```shell
npm install --save-dev typescript
```

And in the `src/ts` folder run the following command to initialize the `tsconfig.js` file.

```shell
tsc --init
```

In `main.ts,` import the `alpine.js`. 

The package scripts are very straightforward:

```json
"watch-js": "esbuild src/ts/main.ts --bundle --sourcemap=inline --target=es2016 --outfile=assets/js/main.js --watch",
"debug-js": "esbuild src/ts/main.ts --bundle --sourcemap=inline --target=es2016 --outfile=assets/js/main.js --servedir=./",
"build-js": "esbuild src/ts/main.ts --bundle --minify --target=es2016 --outfile=assets/js/main.js",
```

The `watch-js` command watches for any changes and creates a debug build of our code with a source map. The `debug-js` command is the same as the `watch-js` command, but it runs the esbuild built-in web development server. The `build-js` command executes our deployment pipeline and outputs the minified code.

To run both commands, will use the [concurrently](https://github.com/kimmobrunfeldt/concurrently) npm package:

```shell
npm install concurrently  --save-dev
```

and add the stript:

```json
"start": "concurrently \"npm:watch-css\" \"npm:watch-js\"",
"dev": "concurrently \"npm:watch-css\" \"npm:debug-js\""
```

Finally, the deployment command runs the `build-js` and `build-css` commands and copy the `index.html` and `assets\` folder to a `dist` folder using the `copyfiles` package. This `dist` folder is the deployment folder.

```shell
npm install copyfiles  --save-dev
```

Therefore, during the development (for the watch mode) use:

```shell
npm start
```

If you want a web development server alongside use :

```shell
npm run dev
```

For deployment, run:

```shell
npm run deploy
```

## Starter Github Repository

You can use the provided starter template freely at [https://github.com/wittyprogramming/tailwindcss-alpinejs-starter](https://github.com/wittyprogramming/tailwindcss-alpinejs-starter)