# Hello World Example

6 min read (1049 words)

# Table of contents

# Create a Page

Creating a simple page mostly involves two steps:

  • Create a controller: A controller is a ECMAScript class (opens new window) with at least one method that builds the page. These methods are called controller actions in ZenTS. The controller will receive a Context, which contains request information and other helpful things, like response helpers.

  • Create a route: A route is the URL (e.g. http://mypage.com/products) which points to a controller.

We will create both of them in this guide by creating a good old Hello World example.

Setup

This guide assumes that you have already installed ZenTS and the CLI. If you didn't install ZenTS yet please follow the installation guide.

# Create a controller

Start by creating a controller which will serve as endpoint for the URL /hello-world. Thanks to ZenTS CLI, controllers can be created quite easily. Open a terminal and navigate to the project folder. Then type the following:

zen add:controller HelloWorld
1

This command will create a HelloWorldController controller inside /src/controller/HelloWorldController.ts. The generated controller will look like this:

import { Controller, get } from 'zents'

export default class extends Controller {
  @get('/')
  public async index() {
    return await this.render('index')
  }
}
1
2
3
4
5
6
7
8

As you can see, the CLI created already a index() method. We call these methods controller actions. For our Hello World example, we can ignore the index() action, so you can delete it safety. Instead, add a new controller action and call it helloWorld(), which returns a simple "Hello World" message as JSON:

export default class extends Controller {
  public helloWorld() {
    return {
      message: 'Hello World',
    }
  }
}
1
2
3
4
5
6
7

TIP

A controller action can either directly returning a response value or use the async keyword (like the index() action). When using the async keyword, the controller action must return a Promise. Learn more about controllers and controller actions in the controller guide.

Our helloWorld() action returns an object, which will be automatically converted to a JSON response. But currently the controller action isn't reachable, because no route is bound to it.

# Binding a controller action to a route

The next step is to bind a URL for our helloWorld() action we just created. ZenTS use a relative new feature (for TypeScript) called annotations for creating routes.

To create a simple HTTP GET URL route we use the @get() decorator and add it on top of our helloWorld() action:

import { Controller, get } from 'zents'

export class HelloWorldController extends Controller {
  @get('/hello-world')
  public helloWorld() {
    return {
      message: 'Hello World',
    }
  }
}
1
2
3
4
5
6
7
8
9
10

TIP

Learn more about routing and routing decorators in this guide.

That's it! We have just bound our controller action to the /hello-world URL. Try it out and open http://localhost:8080/hello-world (opens new window) in your browser.

You should see this response now:

{
  "message": "Hello World"
}
1
2
3

# Rendering templates

Returning a JSON response is nice for e.g. APIs or as response to a AJAX requests, but web applications usually render some kind of presentation in HTML. ZenTS ships with the fast and powerful nunjucks template engine (opens new window), which will help you to create beautiful webpages (of course, you're still can use frontend frameworks like Vue.js (opens new window), Angular (opens new window) or React (opens new window)).

For now, let us create a simple template which will render a "Hello World" string in the users browser. Add a /src/view/helloworld.njk template file with the following content to your project:

<html>
  <head>
    <title>Hello World</title>
  </head>
  <body>
    Hello World!
  </body>
</html>
1
2
3
4
5
6
7
8

Now we just need to change our helloWorld() action to use the render() method:

export default class extends Controller {
  @get('/hello-world')
  public async helloWorld() {
    return await this.render('helloworld')
  }
}
1
2
3
4
5
6

If you go to http://localhost:8080/hello-world (opens new window), you will see a webpage with a "Hello World!" text. In addition, the controller action is now prefixed with the async keyword, because the render() method will return a Promise.

TIP

You can learn more about Promise and the async / await keywords here (opens new window).

# Route parameters and passing data to templates

Of course, web applications are all about interaction with the user. Route parameters are a common way to get data from a user. In this chapter, we will learn how we add route parameters and pass them into a template.

First we extend our @get() annotation with a name parameter:

@get('/hello-world/:name')
1

Now we need to access the parameter in our controller. In ZenTS this is done by using dependency injection. We use the @context annotation to inject a Context object into our controller action, which holds all kind of useful request data. One of them are the URL parameters which we declared in our routes:

import { Controller, context, Context, get, log } from 'zents'

export default class extends Controller {
  @get('/hello-world/:name')
  public async helloWorld(@context context: Context<{ name: string }>) {
    log.info(context.params.name)

    return await this.render('helloworld')
  }
}
1
2
3
4
5
6
7
8
9
10

TIP

The router supports a variety of parameter declarations. Head over to the routing guide to learn more.

If you open http://localhost:8080/hello-world/bob (opens new window) you will see that bob is logged in your terminal.

The next step is to pass the name parameter into our helloworld.njk template. For that purpose, the render() method has a second argument, which will act as the context for the template:

export default class extends Controller {
  @get('/hello-world/:name')
  public async helloWorld(@context context: Context<{ name: string }>) {
    return await this.render('helloworld', {
      name: req.params.name,
    })
  }
}
1
2
3
4
5
6
7
8

The above example will create a name variable in the template context. To output a variable in a template, we use curly brackets. Go ahead and open /src/view/helloworld.njk and add our name variable:

<html>
  <head>
    <title>Hello World</title>
  </head>
  <body>
    Hello World, {{ name }}!
  </body>
</html>
1
2
3
4
5
6
7
8

When you reload your browser, you should see the message "Hello World, Zen!".

# Next steps

Congratulations! You just finished the getting started guide for ZenTS. You're already familiar with the basic concepts of building fast and maintainable applications.

But wait! There is more to learn about ZenTS and mastering more in-depth look at topics like:

After that, learn more about topics like dependency injection, interacting with databases or services.