Workflow

This page goes over all steps necessary to develop things for the website. We will go over some common tasks first.

Generate a new route

Simply use the provided NX generator @coe/generators:route. You will need to provide the app (main, admin, stichting, api or contract) and the url where you want the page to be found. Additionally you can choose, if your route should get its own folder. This is useful for generating an Angular route with template and style files. All routing files will be generated automatically. If you want to adjust routing specific data you will find metadata for the route in the same file as the implementation for it.

Example

Let's go step by step through the process of creating an entirely new feature.

Step 1: Contract

First we need to define our API endpoint. This is done using oRPC contracts. To generate one we can use the route generator as described above. Either use the NX Plugin to get an UI or use the CLI directly. I'll list the CLI commands.

This will give you a boilerplate contract that will look like this:

Let me explain all the parts in case you are not familiar with oRPC. We define routes using oc.route() we define the path and method here. The input and output structure shoud ideally always be detailed. You can read more about it here. Next we define the input. You can omit it entirely, if you have nothing to write, however you will need to add both your path params and query params if you need them. Last comes the output. Usually just the status and the object definiton will be enough. If a specific status has multiple return types you can use z.union() to combine them.

Here is what the final contract might look like:

Step 2: The Server

Now that our API endpoint is defined we can go ahead and implement it. We'll start again using the route generator. Simply re-use the same url, but change the app to api.

The generated code will look like this:

We define a handler for each method on the specific path. This handler comes from our main server implementer which refers back to the contract. This means the input you see is type safe and also the return for the handler is type safe. So you really can't do anything wrong. You have to stick to the definition of the API.

One important thing to mention is the context. It can be used to get dat for the logged in user, authentification and ultility services. In general we don't use DI on the backend for simplicity. In the boiler plate code you can see config and prisma. config holding information about the environment and prisma being the prisma client you can use to fetch data from the database.

As an example this is what the finished code might look like:

Step 3: The Web

Now that we have a working API we can consume it on the website. Let's take an admin page for events as an example. We will use the same generator with the same url again, but using app admin instead. We'll also add the inlineStyle and inlineTemplate options to have everything in a single file.

The result will look like this:

This is a simple Angular component that you configure to your hearts content. Below the component definition you find the route metadata. This is whats imported into the route file, so it can be used as any other Angular route definition. Going over all the possibilities for a frontend is outside the scope of this page. So here is a quick sample of what a page like this might look like:

This sample has a few things worth mentioning. First it's using the data table component to display data. The page also has the full routing definition needed to add a route to the admin navigation menu. You can read more about that here.

And thats pretty much it. With 3 calls of the same generator we now have a new feature in the app.