Web Rendering Strategies

Client-Side Rendering (CSR) Client-Side Rendering (CSR) is a web rendering strategy where the content of a webpage is generated in the browser using JavaScript. Upon visiting the website, the user’s browser downloads a minimal HTML page, the JavaScript required to render the content, and then executes the JavaScript to generate the webpage dynamically. This approach is widely used in Single Page Applications (SPAs) for its fluid, app-like user experience. ...

12 min

Setting Up a K3s Raspberry Pi Cluster with Ansible

Introduction In today’s world, the Raspberry Pi is not just a tool for hobbyists, but a robust, cost-effective, and scalable solution for a variety of tech projects. But have you ever wondered if there’s a way to harness multiple Raspberry Pis to operate in unison, multiplying their combined computational prowess? Welcome to the realm of Raspberry Pi clusters! In this guide, we’ll embark on an exciting journey, setting up a Raspberry Pi cluster comprising three nodes: one master and two workers. Our destination? Deploying K3s, a lightweight Kubernetes distribution tailored for small-scale clusters and IoT devices, with the power of Ansible—a renowned automation tool that simplifies complex configurations and deployments. ...

8 min

RESTful Design: Best Practices with a .NET example

Introduction This is yet another blog post about how to build a REST API, however from my perspective and focusing on using Microsoft .NET technologies. Guidelines Consistency - While it’s not essential to adhere strictly to particular standards, it’s crucial to maintain consistency in your approach. Follow the OpenAPI spec, either generate the OpenAPI spec from your API or write the spec and generate your API. Having an OpenAPI spec means a client can be generated, documentation can be generated, contract testing tooling can be bootstrapped and more. Use nouns instead of verbs GET /users, not GET /getUsers Use plurals instead of singular nouns GET /users/1/activites/10 and GET /users/1/activites instead of GET /user/1/activity/10 and GET /user/1/activity Use the right verbs GET, Retrieve a record GET /users/1 or collection of records GET /users POST, Create a record PUT, Update a record, should be idempotent - calling it once or many times produces the same result with no side effects DELETE, Delete a record PATCH, Partially update a record by supplying only the necessary information. Can be combined with a standard like JSON Patch Use the right status codes, I most commonly find myself using the following: 200 - OK, Succesful, with the response containing a body. For a GET this might be the requested resource, for a POST this might be the created resource 204 - No Content, Succesful, but no response body. We’ve done a PUT to update a resource 400 - Bad Request, Something in the request object is invalid, this could be something like the name of a property or the value of a property 401 - Unauthorized, You’re not logged in 403 - Forbidden, You’re logged in but you can’t access this resource 404 - Not Found, It doesn’t exist 409 - Conflict, You’re trying to create something that already exists 500 - Internal Server Error, 40x error codes indicate a problem on the client, and 500 indicates something unexpected went wrong on the server. Avoid nesting, or at least avoid nesting more than one level deep. Nesting creates a dependency between the entities. Use the query string to Filter, this could be general filtering based on a value, sorting, paging, or selection of fields. GET /users?country=UK GET /users?sort=birthdate_date:asc GET /users?limit=120&offset=1 GET /users/1?fields=name,email or GET /users?fields=name,email for a collection Error handling should be done in a consistent way that can be handled by the calling client with ease. I like to split an error into a unique identifier, a name, and a description 1 { 2 "code": "validation-error", 3 "message": "Name too long", 4 "description": "Name can't contain more than 100 characters" 5 } Wiggle room As with a lot of patterns and principles, how they’re used can depend on the context. As an example I think it’s fine to do a PUT to update a record and then return that record in the response, sometimes this is more convenient, maybe there are calculated fields that would require the following GET to retrieve but by returning the object in the response we can remove the need for that GET. An example might be that we display the last updated date of the record. What I believe is important is that we’re consistent with this behavior, if we’re returning an object as part of a PUT for one entity we should do it for all. ...

5 min

Using Docker Multi-Stage Builds to Optimise your build pipeline(s)

Quite recently I discovered the power of using multi-stage docker builds with the output argument. This was significant because it enabled me to remove a lot of duplication that occurred between my Dockerfile build process, and the processes that I ran on my build agents helping towards making a 75% time saving on a process where I wanted to get quicker feedback, the release and pull-request app build. ...

4 min

Verticle Slice Architecture

Introduction Often we build abstractions into our projects around technology layers i.e. web, business, domain, data, etc. However this shouldn’t be our primary concern, it’s a secondary concern. We should focus on functional units of work, and we might choose to split these functional units of work by their respective technology layers, however not all functional units of work need to use the same underlying architecture. We want to primarily decouple features so that we’re able to scale in a way that can be supported by our organisational structure. Splitting by functional units of work supports growing from a single team managing a set of features to a team per feature. ...

4 min

Common Vulnerabilities and Exposures (CVE) Detection

Introduction You might not be aware, but you could be at risk of a security incident due to a third-party library or component within your codebase having a vulnerability. This article will help you detect security vulnerabilities in third-party libraries using a free-to-use tool called Trivy. I’ve created a repo to demonstrate scanning a few types of apps here https://github.com/jtbuk/CVEDetection, it has a .NET app, and an angular spa, both of which run in docker, Trivy will scan the docker images, npm packages, and NuGet packages and we use the output to send a formatted slack message containing the results. ...

6 min

Setting up a reverse proxy for a better developer experience

Introduction Are you fed up with using localhost and a range of different ports when developing locally, having difficulty with testing content security policies, having to configure TLS for a range of different server applications, and using different URLs when running applications on your laptop natively vs in docker? Using a reverse proxy can solve all of the above. You can clone the code I’ve written for this article via this GitHub repository. ...

5 min