Deployment with view templates (Render)
Learning objectives
- You know how to deploy an application that uses view templates.
In this example, we continue from the example outlined in Deployment on a server (Render), where we deployed a Deno application on Render.
Practicing deployment
For the purposes of the present example, for practice, and for keeping the end result of the previous deployment example, we've created a new project folder, called wsd-online-deployment-ii
, created a corresponding repository for it, and deployed it with Render.
You can choose to either continue with your prior deployment, or to create a new project folder, a new repository on GitHub, and to deploy the new project to Render. We strongly recommend doing the steps outlined in Deployment on a server (Render) again for practice, and continuing from the new project here.
When doing the deployment for another project, instead of connecting Render with GitHub, you need to choose Configure account (showin in Figure 1).

When clicking configure account, you are shown the configuration page in GitHub, which allows selecting repositories that Render can access. Add the new repository that you have created. In our case, the name of the repository is wsd-online-deployment-ii
, as shown in Figure 2.

Once you've selected the repository, press Save. Once you've clicked Save, you are directed back to the page on Render, where you can select the repository to Connect to the newly created Web Service.
Once you select Connect, you are again shown the window for filling in details for the new Web Service. For the purposes of this example, we use the name artos-unique-wsd-deployment-ii
, but otherwise use the same configuration as outlined Deployment on a server (Render).
At this point, the application responds with the message Hello you!
.
Starting the work on templates
At this point, we have a folder called wsd-online-deployment-ii
and a GitHub repository connected to Render. The contents of the folder are as follows.
tree --dirsfirst
.
├── app.js
├── deps.js
└── Dockerfile
0 directories, 3 files
Adding a view template and a layout
Let's create a folder views
and a folder layouts
into the folder views
. Create a file called layout.eta
and place it into the layouts
folder. Place the following contents to the layout.eta
file. Here, we use PaperCSS
for styles.
<!doctype html>
<html lang="en">
<head>
<title>Title</title>
<link rel="stylesheet" href="https://unpkg.com/papercss@1.8.1/dist/paper.min.css">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta charset="utf-8">
</head>
<body>
<div class="container paper">
<%~ it.body %>
</div>
</body>
</html>
Now, create a file called count.eta
and place it to the views
folder. Place the following contents to the count.eta
file.
<% layout('./layouts/layout.eta') %>
<h1>Current count: <%= it.count %></h1>
At this point, the contents of the `wsd-online-deployment-ii`` folder should be as follows.
tree --dirsfirst
.
├── views
│ ├── layouts
│ │ └── layout.eta
│ └── count.eta
├── app.js
├── deps.js
└── Dockerfile
2 directories, 5 files
Using view templates
Now, we adjust the deps.js
so that it loads and exports the dependencies that we use for view templates. Change the deps.js
so that its contents are as follows (and remember to save the file).
export { serve } from "https://deno.land/std@0.222.1/http/server.ts";
export { configure, renderFile } from "https://deno.land/x/eta@v2.2.0/mod.ts";
We further adjust app.js
to load the dependencies from deps.js
, and configure the view templates to use the views
-folder. We further create a data
object that has a property count
-- the count is set to 0 -- and modify the handleRequest
function so that it is asynchronous and so that it shows the view template on requests to the path /count
.
The contents of the file are now as follows -- note that requests to other paths than /count
still show the message Hello you!
.
import { serve } from "./deps.js";
import { configure, renderFile } from "./deps.js";
configure({
views: `${Deno.cwd()}/views/`,
});
const responseDetails = {
headers: { "Content-Type": "text/html;charset=UTF-8" },
};
const data = {
count: 0,
};
const handleRequest = async (request) => {
const url = new URL(request.url);
if (url.pathname === "/count") {
data.count++;
return new Response(await renderFile("count.eta", data), responseDetails);
}
return new Response("Hello you!");
};
serve(handleRequest, { port: 7777 });
Adding and pushing the changes
Next, we need to add and push the changes to GitHub. As you might remember, there are three key commands git add
, git commit
, and git push
. Now, as we are adding multiple files, we can use git add .
, which adds all the files to the repository.
In practice (once app.js
has been changed and saved), the steps look as follows.
git add .
git commit -m "starting to use view templates"
[main ...] starting to use view templates
// ...
4 files changed, 39 insertions(+), 1 deletion(-)
git push
Counting objects: 8, done.
// ...
To github.com:avihavai/wsd-online-deployment-ii.git
... main -> main
Build failed!
Oh noes, build failed! When you try to access your site, you'll observe that the response in at the path /count
is not as expected.
Inspecting the logs of the web service in Render, among the logs, we see the following error:
error: Uncaught PermissionDenied: Requires read access to <CWD>, run again with the --allow-read flag
views: `${Deno.cwd()}/views/`,
^
at Object.cwd (deno:runtime/js/30_fs.js:73:16)
at file:///app/app.js:5:18
Watcher Process finished. Restarting on file change...
Logs not available?
If the logs are not available, you can initiate a new deployment which will lead to shown logs. This happens by clicking the button "Manual Deploy" and clicking "Deploy latest commit". This will lead to the latest version in GitHub being deployed -- you can follow the logs during the deployment.
Fixing errors
The error highlights that we have not granted read rights to the application. Without read rights, the view templates cannot be read. To fix this, let's adjust the Dockerfile
to include the --allow-read
flag in the run command. Modify the Dockerfile
to match the following and save the file.
FROM denoland/deno:alpine-1.42.2
EXPOSE 7777
WORKDIR /app
COPY deps.js .
RUN deno cache deps.js
COPY . .
CMD [ "run", "--allow-net", "--allow-read", "--watch", "--unstable", "app.js" ]
Now, it's time again for git add
, git commit
, and git push
. This time, as we've modified just a single file, let's use the git add
to add a specific file instead of all the files.
git add Dockerfile
git commit -m "provide read permissions"
[main ...] provide read permissions
// ...
1 file changed, 1 insertion(+), 1 deletion(-)
git push
Counting objects: 3, done.
// ...
To github.com:avihavai/wsd-online-deployment-ii.git
... main -> main
It's alive!
After fixing the error, we see that the deployment is successful. The page with the view template is available at https://artos-unique-wsd-deployment-ii.onrender.com/count, as showin in Figure 3.

Count resets on server restarts
Note that whenever the server is restarted, the count is reset. This is because the count is not stored in any location. We'll look into addressing this when we start working with databases.