Session 5 – Creating the Landing Page Part 1 – Organize the Project


So far, we are able to serve static files and converting markdown contents to html outputs. However, we have been only serving self-contained test files, and it is still far from serving dynamically generated files that are combined from templates and data.

To get there, we’ll work from a more complex example – we’ll serve the landing page of

Breaking Down The Landing Page

The following image shows the breakdown of the existing landing page:

Which has the following visual components:

  • Header – holds the site title, and a top level menu
  • Jumbotron – holds the top level message, as well as a sign up form
    • Signup Form
  • Proposition – a text to describe the issues this site addresses
  • Benefits – a list of benefits of this website
  • Topics – a list of topics that this website covers
  • Call To Action – Asking the readers to take an action, in this case, it’s to sign up
    • Signup Form
  • Footer

The Signup Form is reused twice. Although none of the other contents are repeated, it’s good to go ahead and compose the landing page out of the above components, since:

  • In the future, we’ll have other pages that will share components with the landing page (like the headers and footers)
  • We can add / remove benefits & topics as necessary with this design.

So let’s get started – we’ll start with trying to re-create the above structure in a template.

Using Pug As Template

Express has a built-in mechanism for handling template-based view generation.

The way templates works in Express is that you need to define a configuration setting called views that points to the template directory, and then you need to define another configuration setting called view engine with the name of the view engine module, which needs to be written to specifically work with Express.

The default template engine for express is Pug, so we’ll leverage pug as well.

npm install --save pug

Then we add the following to our index.ts:

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

Let’s also make sure that the views directory exists:

# in the project's root directory.
mkdir views

Now that we have the root directory, let’s create an index.pug as the starting point of the template:

    title Index page
    div Header Section
    div Body Section
      div Jumbotron
        div Signup
      div Proposition
        div Benefit 1
        div Benefit 2
        div Benefit 3
        div Topics 1
        div Topics 2
        div Topics 3
      div Call To Action
        div Signup
    div Footer Section

Then we need to add a route for the index page.

app.get('/', function (req, res, next) {
  return res.render('index', {});

res.render is how Express leverage the created templates. The section parameter is an object holding the values for substitution (called locals in Express), but since we aren’t defining any variables in our template right now, it’s left empty.

Remember to keep tsc running in the background so any changes you have in your .ts files will get incrementally compiled, so you just need to continue to restart the service (we’ll fix this annoyance later).

./node_modules/.bin/tsc --watch

Then you can restart the web server:

npm start

Open http://localhost:800/ and you’ll see a plain looking html being created from the above template.

The plain look is due to the lack of custom styling, so let’s tackle that as well!

Creating a Style Sheet with Stylus and Bootstrap

Anyone who has work with CSS for a while would quickly recognize that it can be difficult to reuse CSS snippets, and some people have come up with solutions to tackle this issue – instead of writing in CSS directly, write in a “better CSS” that can be compiled into the final CSS. This is the same solution for CSS as the HTML template engines are for HTML, and they are called CSS preprocessors, as they focus on “extending” the CSS language with features, rather than creating a completely different language (though some of them do look quite different).

The most popular CSS preprocessors today are:

They all extend CSS with variables, mixins, etc. Though there are tradeoffs among them, you can’t really go wrong with any of them today, so the choice is largely subjective, and for Module Core we’ll going with Stylus.

Correspondingly, Bootstrap is a very popular CSS framework and is fine as a starting point, so we’ll leverage that as well. There is a stylus-based bootstrap package, so we’ll use that.

npm install --save stylus nib bootstrap-styl 
mkdir stylus # for holding the source stylus
mkdir static/css # for holding 

Then let’s create a main.styl in the stylus folder, and add the following:

@require 'bootstrap/index' // requires the whole bootstrap package.

Let’s then compile the stylus spreadsheet into the final CSS (and we’ll keep it running in the background as well):

./node_modules/.bin/stylus -o static/css/ -u nib -u bootstrap-styl --watch --compress ./stylus/main.styl 

And let’s add the stylesheet reference to index.pug:

    // under head

With the addition of the stylesheet, the page now looks a bit different (fonts and margins):

That’s nice, but not enough for what we are looking for. To fully take advantage of bootstrap, we’ll need to convert our template to utilize bootstrap styles, and add additional styles to match what we are looking for.

Let’s update our template to the following:

    title Index page
    // for mobile
    meta(name='viewport',content='width=device-width, initial-scale=1')/
    // header section
          a.navbar-brand(href='/') Header Section
    // body section
      div.jumbotron Jumbotron section
        div.sign-up Signup
      div.proposition Proposition section
        div.benefit Benefit 1
        div.benefit Benefit 2
        div.benefit Benefit 3
        div.topic Topics 1
        div.topic Topics 2
        div.topic Topics 3 Call to Action
        div.sign-up Signup
    // footer section
    div.footer Footer Section

Then we can also update our stylesheet with:

    @extends .navbar
    @extends .navbar-default
    background: #ffffff
    background-size: cover
    margin-bottom: 0

  > .container-fluid

      @extends .row
      background: #ffffff
      background-image: radial-gradient(farthest-corner at 45px 45px , #ace 0%, rgba(255, 255, 255, 0) 100%)
      background-size: cover
      border-radius: 0
      margin: 0

      @extends .row

      @extends .row

        @extends .col-sm-4 
        @extends .col-md-4

      @extends .row

        @extends .col-sm-4 
        @extends .col-md-4 

      @extends .row 
      margin-left: 5%
      margin-right: 5%
      margin-bottom: 3em

    @extends .row
    background: #ffffff
    background-image: radial-gradient(farthest-corner at 45px 45px , #ace 0%, rgba(255, 255, 255, 0) 100%)
    background-size: cover
    border-radius: 0
    margin: 0
    height: 8em

With the above changes, our page starts to look a bit like the original landing page:

There are more things we can adjust, but to do so, we should start to consider how to populate the content to each of the components. We’ll tackle that in the next session.


In this session, we have start the larger goal of creating a landing page. To get there, we have accomplished the following:

  • Determined how to break down the landing page.
  • Made use of Express’s template engine system with Pug.
  • Created the landing page template.
  • Created the stylesheet with Stylus.

Leave a Reply