Tutorial: How to use Leaf

Yeey time to learn leaf — a templating language to easily generate views!

You can find the result of this tutorial on github here

This tutorial is a natural follow-up of How to set up a Vapor 2 project. You can either go for that tutorial first and come back or just skip it and read on 😊

1. Create a new project

Vapor toolbox is so nice it let’s you easily create new projects using any git-repo as a template. Since we will build upon the outcome of the aforementioned tutorial, we will create a new project using it as a template:

vapor new yourProjectName --template=vaporberlin/my-first-route --branch=vapor-2

NOTE: You can see what vapor toolbox is all capable of by typing vapor --help in your terminal :)

Our command will create a project with the name yourProjectName using my-first-route from vaporberlin as a template (thanks vapor toolbox 🤜🏻 🤛🏻 ).

2. Generate the Xcode project

Before we generate an Xcode project we would have to add the Leaf-Provider as a dependency and also change the package name within Package.swift:

// swift-tools-version:4.0import PackageDescriptionlet package = Package(
name: "yourProjectName", // changed
products: [
.library(name: "App", targets: ["App"]),
.executable(name: "Run", targets: ["Run"])
],
dependencies: [
.package(url: "https://github.com/vapor/vapor.git", .upToNextMajor(from: "2.1.0")), // don't forget that comma 😉
.package(url: "https://github.com/vapor/leaf-provider.git", .upToNextMajor(from: "1.1.0")) // added
],
targets: [
.target(name: "App", dependencies: ["Vapor", "LeafProvider"],
exclude: [
"Config",
"Public",
"Resources",
]
),
.target(name: "Run", dependencies: ["App"]),
.testTarget(name: "AppTests", dependencies: ["App", "Testing"])
]
)

Now in the terminal at the root directory yourProjectName/ execute:

vapor update -y

It may take a bit fetching the dependency, generating the Xcode project and opening it for you. But when done you should have a project structure like this:

yourProjectName/
├── Package.swift
├── Sources/
│ ├── App/
│ │ ├── Routes/
│ │ │ └── Routes.swift
│ │ └── Setup/
│ │ ├── Config+Setup.swift
│ │ └── Droplet+Setup.swift
│ └── Run/
├── Tests/
├── Config/
├── Public/
├── Dependencies/
└── Products/

3. Configure your project to be able to use Leaf

Our first step is to add the LeafProvider in our Setup/Config+Setup.swift:

import LeafProvider // addedextension Config {
public func setup() throws {
try setupProviders()
try setupPreparations()
}
/// Configure providers
private func setupProviders() throws {
try addProvider(LeafProvider.Provider.self) // added
}
/// Add all models that should have their
/// schemas prepared before the app boots
private func setupPreparations() throws {}
}

Next is to set leaf as a view renderer anywhere within Config/droplet.json:

{
...
"//": "The type of view renderer that drop.view will use",
"//": "leaf: Pure Swift templating language created for Vapor.",
"//": "static: Simply return the view at the supplied path",
"view": "leaf",
...

}

4. Create your first template

Our view renderer leaf is expecting a directory called Resources/ and right underneath it a directory called Views/ to hold all view-files. So you will end up with a structure like the following: yourProjectName/Resources/Views/

NOTE: They have to be directories (blue folder) and not groups (yellow folder). I created them in terminal with mkdir -p Resources/Views

You may have to re-generate your Xcode project with vapor xcode -y in order to let Xcode see your new directories. When done in Resources/Views/ create a new file named myview.leaf with following code:

<!DOCTYPE html>
<html>
<head>
<title>Leaf</title>
</head>
<body> <h1> My first leaf template! </h1> </body>
</html>

5. Implement a route to serve the view

In your Routes/Routes.swift add a new route, let’s call it.. 🤔

import Vaporextension Droplet {
func setupRoutes() throws {
get("name") { req in
return "Ethan Hunt"
}
get("age") { req in
return "\(23)"
}
get("json") { req in
return try JSON(node: ["name": "Martin J. Lasek", "age": 26])
}
get("view") { req in
return try self.view.make("myview")
}
}
}

If you now hit cmd + r or the play button on top of Xcode, it will start the application. The console in Xcode tells you where. For me it’s 127.0.0.1/8001

Note: make sure to select Run as a scheme next to your button before running the app

NOTE: The port from where you can reach your app is defined within Config/server.swift — you can change it as you like and re-run the app :)

If you now fire up 127.0.0.1:8001/view in your browser you will get a view served using Leaf as a templating language! 🙌🏻

6. BONUS: Passing data to the view

It’s super easy to pass data into a view. And this is how it looks like:

import Vaporextension Droplet {
func setupRoutes() throws {
get("name") { req in
return "Ethan Hunt"
}
get("age") { req in
return "\(23)"
}
get("json") { req in
return try JSON(node: ["name": "Martin J. Lasek", "age": 26])
}
get("view") { req in
return try self.view.make("myview")
}
get("bonus") { req in
return try self.view.make("mydataview", ["name": "Taichi"])
}
}
}

If you now create a new file in Resources/Views/ called mydataview.leaf you can access the passed data in it like so:

<!DOCTYPE html>
<html>
<head>
<title>Leaf</title>
</head>
<body>
<h1> You rule #(name)! </h1>
</body>
</html>

Now re-run your application and fire up 127.0.0.1:8001/bonus :D!
That’s it! You successfully implemented a leaf template project 🎉 !!

Thank you a lot for reading! If you have any suggestions or improvements - Let me know! I would love to hear from you! 😊

--

--

--

I'm an always optimistic, open minded and knowledge seeking fullstack developer passionate about UI/UX and changing things for the better :)

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Digital Citations — A Paperless Parking Citation System (An All-Amazon Serverless Cloud Solution)

Automate paperwork and never copy manually data from a PDF again with Box and Docparser

How Technologies Are Connected?

Kubernetes Cluster Running Out of IP Addresses on AWS EKS

How to Build an eBay Price Tracker using Python

Python for Quick Financial Functions

How to Extract Houzz Product Images with Python & BeautifulSoup

CompArts Week 4

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Martin Lasek

Martin Lasek

I'm an always optimistic, open minded and knowledge seeking fullstack developer passionate about UI/UX and changing things for the better :)

More from Medium

Start using Vapor 4 without Toolbox / Homebrew

SwiftUI Tutorial: Working with Toggle

How to convert .ogg/.oga audio into .wav in Swift using C++, Objective-C and Swift Package Manager

Swift programming: Math