At some point, we all come to the same conclusion: we have to upgrade our website.
For us, it meant modernizing the visual profile (including new logo and colors) and starting from scratch technically. An important requirement was that the new website had to be easy to maintain in a busy everyday life. So we contacted the best design bureau in town, our sister company Northern Beat (not kidding, they're the best design bureau in Norway: https://aretsbyra.no/resultater/). They came up with a clean and elegant design.


novanet.no screenshot

Technology

With the requirement of simple maintainability and the new design we started to consider what technology to use.

Content management: Sanity.io

Our previous website was pretty static and hard to maintain, so we needed some type of content management system. Having experienced development in the more traditional types of CMS, we wanted a solution that gave us more freedom in developing the front end. We had also heard positive things about using a Headless CMS, and Sanity.io in particular. So, we decided to check out Sanity.io! Sanity.io is great for structural content, without connecting it to a specific page template. Sanity.io provides an API where you query your content and get a JSON structure back. Then you can use it as you please. We've written a blog post about it here. We also got great support from the Sanity developers.

Getting started with Sanity.io was very easy. Getting the content structure right was more challenging. In Sanity.io you define the content structure in javascript, then you add and edit content in Sanity Studio. We changed the structure several times to get it right. We wanted to avoid having content connected to a specific page, but ended up having some of the content in a "Pages" structure to hold texts (and some other stuff) related to specific pages. While some content could be abstracted from the GUI, there were certain elements which we felt we had to pin to a given page.

On a side note - Sanity.io has a feature called hot-spot for presenting images, which gives you coordinates in a photo for ideal presentation. In our case we used it in our employees list to ensure everyone’s face was centered. Since we have rounded profile pictures, this feature was essential for the presentation.
Image using sanity hotspot

Frontend framework: Angular

If you don't know Angular - check it out. It's an awesome framework for making apps with HTML, TypeScript and CSS. The decision to go with Angular was mostly based on familiarity, and since we decided to use Sanity.io for content delivery we were free to structure our app as we wanted. A big advantage of using a headless CMS.

Developing the frontend was pretty straight forward. The biggest challenges was getting the design just right, and getting to know Sanity's query language, GROQ.

Application state: @ngrx

@ngrx offers a bunch of cool libraries for Angular. The @ngrx/store package gives you a nifty way of putting your front-end data into a separate layer inside your app. We combined it with @ngrx/effects and a facade service for firing off events based on user interaction.

One of the really cool things about @ngrx/store is that it allows you to easily check your content before doing any further actions. Of course, you can do that within an Angular controller, but we find the store approach better (and cooler).

As an example, when we fetch blog posts for a specific person, we call an API. In our @ngrx/store facade service, we first check if the data exist by putting a filter in the pipeline. If the filter tells us it does not contain that specific blog posts - then we fire an action to fetch the blog posts via the API:

public populateBlogPosts(userId: string): void {
    this.getBlogPosts(userId)
      .pipe(
        take(1),
        filter(blogPosts => !blogPosts.length),
        map(() => new peopleActions.LoadPersonsBlogPostsAction(userId))
      )
      .subscribe(this.store);
  }

this.getBlogPosts(userId) reads from the @ngrx/store and returns the users blog posts (if any), and then passes it on to the filter.

Integration: CVPartner

We have all our employees resumés in CVPartner. It includes contact information (like email and twitter account), a textual summary and technical skills. All information we wanted to include on our web page. So, we had to create a migration/integration to move the data to Sanity.io. We could of course just have copy-pasted the data from CVPartner, but it was pretty time-consuming.

We also had to make the integration as easy as possible, so that anyone could do it. Since Sanity Studio is the place to work with content, we wanted to be able to trigger transfer of the CVPartner content to Sanity.io from Sanity Studio.

Sanity.io Plugin

Sanity.io allows you to write your own plugins. We decided to create a simple plugin that calls the CVPartner API for data, then stores the data as documents in Sanity.

Getting started is easy. Just run the command:

sanity init plugin

This will basically create a React component. You can give it a name and assign an image for the icon. Then you write your own React/JavaScript code. We used the CVPartner REST API to get data. Then the Sanity JavaScript Client to create documents in our Sanity schema. We added the plugin to the sanity.json:

  "plugins": [
    "@sanity/base",
    "@sanity/components",
    "@sanity/default-layout",
    "@sanity/default-login",
    "@sanity/desk-tool",
    "@sanity/vision",
    "cv-partner-tool"
  ],

And voilà, we had our own module/plugin in Sanity Studio:

Integration: Ghost.io

All our blog posts, like this one, are created and stored in Ghost.io. Ghost is an open source platform for building online publications, like blogs. We can easily write blog posts (with markup language), publish and host them. We wanted to include the blog posts of an employee on the employee page, like on the bottom of Hallsteins page. So, we used Ghosts API to retrieve metadata for the posts and link to them from the Angular web site.

Result

By combining all these parts we got a nice-looking, flexible web site, thats easy to maintain. Adding new content is really simple, and we're really pleased with the result! So please check out our new website:

novanet.no