Back to HTML, CSS, and JavaScript & Build A Speaker Site with ~200 Lines of Good Old Code
Tags: html, css, javascript
Published: 2019-03-24 18:48:11

Inspired by [Global Diversity CFP Day](https://gdcfp-day-sg.glitch.me/#slide13), and due to an increasing involvement at my local communities, I have been thinking of building my speaker site for a while. And so I was working on it earlier this weekend.

There are existing commercial speakers sites such as [noti.st](https://noti.st/) and [Speaker Deck](https://speakerdeck.com/). Some people have a section for speaking under their personal site.

I currently have existing slides all over the place, google presentation, slides.com, mdx-deck, spectacle, revealjs, etc. I’m happy to put a link if it’s hosted externally somewhere. But those that I built locally, I hope to host them so that I can share them easily in the future.

I don’t have a bound choice of tech stack because I build separate sites for my projects anyway. Even my home page is a separate project. Judge me if you wish 🙈

![](https://d2mxuefqeaa7sj.cloudfront.net/s_FCEFDF89CFD7A6773E20804F5B2453249DFBD80533FD63F98B2BC9A123554B37_1553361309546_image.png)

## Directory structure

I’m imagining this kind of structure:

```shell
.
├── README.md
├── ... # my site?
└── slides
    ├── 2019-03--whats-happening-30-days-css-girls
    └── year-mo--title-to-your-talk
        ├── ...
        ├── index.html
        └── package.json
```

So what about the site?

I decided to forget about static site generators and write one myself. Saturday is for writing genuine HTML, CSS, and JavaScript, join me next Sat?

Although, I would like to mention that this decision did not come quick. I’ve built [three](https://css.codinggirls.sg/) [Gatsby](https://reactknowledgeable.org/) [sites](https://japanese.wgao19.cc/) recently. And I notice that that JAMStack mindset is forming something in my brain. At the end of this day I realized that the whole thing came down to less than 200 lines of code, prettier-ed, my jaw came down. The fact that I didn’t think along this plainer scratch to begin with rings a bell in me.

## index.html

Here to remind myself that apart from linking the CSS and JavaScript as separate files, there is this option to inline them.

- The CSS is under a `<style />` tag
- The JavaScript is under a `<script />` tag

```html
<head>
  <style>
    /* CSS */
  </style>
</head>
<body>
  <p>Hello, this is ...</p>
  <h2 class="display">Upcoming</h2>
  <ul id="upcoming"></ul>
  <h2 class="display">Past</h2>
  <ul id="past"></ul>
  <footer style="position: absolute; bottom: 0; padding-bottom: .25rem">
    ... built with ❤
  </footer>
  <script>
    // JavaScript
  </script>
</body>
```

Then, the idea is that I write a separate `data.js` file to include all the meta data for each talk. And I parse this data and render according to a few simple logic.

It is not very hard to write a script to read all the meta info from each slides. But I decided not to work on that for now.

## There is only one feature 🤞

I check for date for each talk, split between past and upcoming talks, then flush them into their separate sections.

```javascript
const isUpcoming = talk =>
  // I put random things here if it's upcoming
  new Date(talk.when) > new Date() || new Date(talk.when) == 'Invalid Date'

const isPast = talk => new Date(talk.when) <= new Date()

talks.filter(isUpcoming).map(/** renders into upcoming section */)
talks.filter(isPast).map(/** renders into past section */)
```

## Maybe two ✌️, if parsing template strings counts

I wrote in a mixed flavor that I picked up along the many projects I’ve been through 😂 I’m pretty amused by this section of the code to be honest.

```javascript
const parseTalks = (elementId, talk) => {
  // deconstruct talk object
  const { title, when, where, slides, post, intro } = talk
  const titleNode = `
    <div class="topic">
      <i class="fas fa-quote-left"></i>
      <span class="display">${talk.title}</span>
      <i class="fas fa-quote-right"></i>
    </div>
  `
  // ... others

  // create an element for each talk and append to the ul
  const talkElement = document.createElement('li')
  talkElement.innerHTML = [
    `<base target="_blank" />`,
    titleNode,
    whenNode,
    whereNode,
    slidesNode,
    postNode,
    introNode,
  ].join('')
  document.getElementById(elementId).appendChild(talkElement)
}

talks.filter(isUpcoming).map(parseTalks.bind(null, 'upcoming'))
```

## Serving slides

I put all the slides under a directory called `slides/`. They will live in each of their own directory, and have their own separate dependencies and builds. There are mainly two issues to concern: routing if applicable, and building, since I don’t want to keep built file in the repo.

- [Reveal.js](https://revealjs.com/#/)

This one works automatically. You write everything in the index.html, static assets are built with grunt. Unless you write your own theme, there is not even a need to build.

- [Spectacle](https://formidable.com/open-source/spectacle/)

Spectacle is a presentation library built with and for React. It also works beautifully, although it needs a build.

- [mdx-deck](https://github.com/jxnblk/mdx-deck)

Unfortunately, this one currently does not work. Because it routes by statically look up the pathname index 1. Serving mdx-deck under slash separated pathname will not work.

I’ve [created an issue](https://github.com/jxnblk/mdx-deck/issues/291) to hopefully resolve this in the near future.

So now the repo roughly looks like this:

```shell
.
├── README.md
├── data.js
├── index.html
├── lerna.json
├── package.json
└── slides
    ├── 2019-03--whats-happening-30-days-css-girls
    ├── 2019-04--developers-gym-gatsby
    ├── revealjs-boilerplate
    └── spectacle-boilerplate
```

## Lerna + Netlify for build and deploy

Thanks to Netlify, it takes away all the things I don’t want to concern about. The build step is so incredibly easy and without any hiccups at all.

Some of my slides needs a build for static files. Some others don’t. Netlify allows me to supply a build script to run for each build. Writing a script to go through each directory that needs build is not too much of a hassle. But why not use Lerna..

With `lerna bootstrap` and `lerna run build`, it automatically bootstraps (installs all dependencies, symlink if possible) all packages which, in my case slide, and runs build in all packages that specify a build command. And then I’m done!!

## Till next time

How was this site built? I give it a combined credit of kindergarten plus grown-up toys. It’s almost therapeutic.

Will you build a speaker section to your website? And if so, how would you build it?