How To Build A Localized Website With Hugo And Strapi

Localizing your site can benefit your business or organization in several ways. By translating your content or site, you expand the markets you target. Adapting your product to the language and cultural preferences of potential customers who were not able to use your product before boosts your conversion rates.

Ultimately, this often leads to a growth in the revenue you generate. With a larger, more widespread customer base, your brand becomes increasingly recognizable and strengthened in newer markets.

A localized website has a higher SEO score which means that users within a specific market can find it easier through a search engine. A recognizable brand and improved SEO score reduce the cost of marketing to users within the markets you target.

We’ve seen that localization has its benefits, but what exactly is it? Localization is the process of revising your website, app, or content that was initially intended for a primary market to suit the needs of a new market you plan on targeting. Localization often involves translating a product into the language used in the market you want to introduce it to. It can also mean adding new things or removing parts of the product, for example, that might offend the market. You may also modify a product by changing its look and feel based on writing systems, color preferences, etc.

Although localization may seem straightforward, it cannot happen if the underlying site or app cannot accommodate these changes. Since it isn’t practical to build the same site for every market you want to enter, it makes sense that your site should switch content, language, UI elements, etc., between markets. That’s where internationalization comes in.

Internationalization is the process of designing and building a site or app to accommodate localization across different markets. For example, an online magazine’s site published in Portugal, Japan, and Ireland needs to accommodate different languages, writing systems, payment processors, and so on.

Before embarking on localization, it is important to pick a backend that will help you manage your site content across different locales. Strapi is one choice that provides this functionality. It’s an open-source headless content management system (CMS) built with Node.js. With it, you can manage and structure content into types using its content types builder on its user-friendly admin panel. For every content type you create, it automatically generates a customizable API for it. You can upload all kinds of media and manage them using its media library.

With its Role-Based Access Control (RBAC) features, you can set custom roles and permissions for content creators, marketers, localizers, and translators. This is especially useful since different people on a team should only be responsible for the content in the locales they manage. In this tutorial, you will learn about its internationalization feature that allows you to manage content in different languages and locales.

Your frontend also needs to handle your content in different languages and present it to multiple locales adequately and efficiently. Hugo is an amazing option for this. It’s a static site generator built with Go. It takes your data and content and applies it to templates. It then converts them to static pages, which are faster to deliver to your site visitors.

Hugo builds sites pretty fast, with average site builds completed in a second or less. It supports several content types, enables theme integration, meticulously organizes your content, allows you to build your site in multiple languages, and write content in markdown. It also supports Google Analytics, comments with Disqus, code highlighting, and RSS. Static sites are faster, have great SEO scores, have better security, and are cheaper and less complicated to make.

Without further ado, let’s dive right in!

Pre-Requisites

Before you can proceed with this tutorial, you will need to have:

  1. Hugo installed.
    You can get it through pre-built binaries, which are available for macOS, Windows, Linux, and other operating systems. You can also install it from the command line. These installation guides are available on the Hugo website explaining how to get it in this way. This tutorial was written using v0.68.
  2. Node.js installed.
    Strapi requires at minimum Node.js 12 or higher but recommends Node.js 14. Do not install a version higher than 14 as Strapi may not support it. The Node.js downloads page offers pre-built installers for various operating systems on its website.
An Example Site

To illustrate how localization can work using Strapi and Hugo, you’ll build a documentation website for a product used in Canada, Mexico, and America. The top three languages spoken in those regions are English, French, and Spanish. So, the documents on this site need to be displayed in each of them. The site will have three pages: a home page, an about page, and a terms page.

The Strapi CMS provides a platform to create content for those pages in those three languages. It will later serve the markdown versions of the content created through its API. The Hugo site will consume this content and display it depending on the language a user selects.

Step 1: Setting Up the Strapi App

In this step, you will install the Strapi app and set up an administrator account on its admin panel. The app will be called docs-server. To begin, on your terminal, change directories to the location you’d like the Strapi app to reside and run:

npx create-strapi-app@3.6.8 docs-server

When prompted:

  1. Select Quickstart as the installation type.
  2. Pick No when asked to use a template.
? Choose your installation type Quickstart (recommended)
? Would you like to use a template? (Templates are Strapi configurations designed for a specific use case) No

This command will create a Strapi quickstart project, install the dependencies it requires, and run the application. It will be available at http://localhost:1337. To register an administrator, head to http://localhost:1337/admin/auth/register-admin. You should see the page below.

Enter your first and last names, an email, and a password. Once you’ve finished signing up, you will be redirected to the admin panel. Here’s what it looks like.

On the admin panel, you can create content types, add content entries, and manage settings for the Strapi app. In this step, you generate the Strapi app and set up an administrator account. In the next one, you will create content types for each of the three pages.

Step 2: Create the Content Types

In this step, you will create content types for each of the three pages. A content type on Strapi, as the name suggests, is a type of content. Strapi supports two categories of content types: collection types and single types. A collection type is for content that takes a single structure and has multiple entries.

For example, a blog post collection type collects multiple blog posts. A single type is for content that is unique and only has one entry. An about content type that models content for an about page, for instance, is a single type because a site typically has only one about page.

To generate these types, you’re going to use the Strapi CLI. You have the option of using the existing Strapi admin panel to create the types if you wish. However, the Strapi CLI can be faster and involves fewer steps.

If the Strapi is running, stop it. Running the commands in this step will cause errors that will crash the app. Once you’ve completed this step, you can run it again with the command below on your terminal within the docs-server directory:

npm run develop

Since you will have three separate pages, you will create three different single types. These will be the home, about, and terms types. Each will have a content and title attribute. These two attributes are just a starting point. You can modify the types later if you’d like to add more attributes or customize them further. To create them, run this command on your terminal within the docs-server directory:

for page in home about terms; do npm run strapi generate:api $page title:string content:richtext ;done

Running the above command will generate the home, about, and terms content types with title and content attributes. It also generates APIs for each of the page types. The APIs are generated within the api/ folder. Here’s what this folder looks like now.

api
├── about
│   ├── config
│   │   └── routes.json
│   ├── controllers
│   │   └── about.js
│   ├── models
│   │   ├── about.js
│   │   └── about.settings.json
│   └── services
│       └── about.js
├── home
│   ├── config
│   │   └── routes.json
│   ├── controllers
│   │   └── home.js
│   ├── models
│   │   ├── home.js
│   │   └── home.settings.json
│   └── services
│       └── home.js
└── terms
    ├── config
    │   └── routes.json
    ├── controllers
    │   └── terms.js
    ├── models
    │   ├── terms.js
    │   └── terms.settings.json
    └── services
        └── terms.js

Each of the content types have models, services, controllers, and configuration created for them. Several API routes are added as well to create, modify, and retrieve content modeled against these types.

In the api/about/models/about.settings.json file, you will change the kind of the about content type from a collection type to a singleType. You will also add a description and enable localization for it and its attributes. Replace the code with the following:

{
  "kind": "singleType",
  "collectionName": "about",
  "info": {
    "name": "about",
    "description": "The about page content"
  },
  "options": {
    "increments": true,
    "timestamps": true,
    "draftAndPublish": true
  },
  "pluginOptions": {
    "i18n": {
      "localized": true
    }
  },
  "attributes": {
    "title": {
      "pluginOptions": {
        "i18n": {
          "localized": true
        }
      },
      "type": "string"
    },
    "content": {
      "pluginOptions": {
        "i18n": {
          "localized": true
        }
      },
      "type": "richtext"
    }
  }
}

In this file, you are adding detail to the content type that you can’t specify when generating them through the CLI. The kind property changes to a singleType from a collection type. Localization is enabled using the pluginOptions property. By setting localized to true under the i18n internationalization property, localization is enabled for the type as well as the attributes that specify the same property.

Next, you will modify its API routes to only have routes that will update, delete, and retrieve content. When you create a content type using the CLI, it is by default a collection type. A collection type has five routes created for it: routes to find, find one, count, delete, update, and post. A single type doesn’t need count, post and find-one routes since there’s just one entry. So you will be removing these. Replace the contents of api/about/config/routes.json with this code:

{
  "routes": [
    {
      "method": "GET",
      "path": "/about",
      "handler": "about.find",
      "config": {
        "policies": []
      }
    },
    {
      "method": "PUT",
      "path": "/about",
      "handler": "about.update",
      "config": {
        "policies": []
      }
    },
    {
      "method": "DELETE",
      "path": "/about",
      "handler": "about.delete",
      "config": {
        "policies": []
      }
    }
  ]
}

Since the other content types share the same attributes, you will make similar changes to the model settings for each of the other types. The content types in this tutorial share the same attributes for demonstration purposes but you can modify them to suit the needs of the pages you create. In the api/privacy/models/home.settings.json file, change the code to:

{
  "kind": "singleType",
  "collectionName": "home",
  "info": {
    "name": "Home",
    "description": "The home page content"
  },
  "options": {
    "increments": true,
    "timestamps": true,
    "draftAndPublish": true
  },
  "pluginOptions": {
    "i18n": {
      "localized": true
    }
  },
  "attributes": {
    "title": {
      "type": "string",
      "pluginOptions": {
        "i18n": {
          "localized": true
        }
      }
    },
    "content": {
      "type": "richtext",
      "pluginOptions": {
        "i18n": {
          "localized": true
        }
      }
    }
  }
}

Similar to the about API routes, you will remove the find-one, count, and post routes for the home content type since it’s a single type. Replace the contents of the api/home/config/routes.json file with this code:

{
  "routes": [
    {
      "method": "GET",
      "path": "/home",
      "handler": "home.find",
      "config": {
        "policies": []
      }
    },
    {
      "method": "PUT",
      "path": "/home",
      "handler": "home.update",
      "config": {
        "policies": []
      }
    },
    {
      "method": "DELETE",
      "path": "/home",
      "handler": "home.delete",
      "config": {
        "policies": []
      }
    }
  ]
}

Lastly, in the api/terms/models/terms.settings.json file, replace the existing code with:

{
  "kind": "singleType",
  "collectionName": "terms",
  "info": {
    "name": "Terms",
    "description": "The terms content"
  },
  "options": {
    "increments": true,
    "timestamps": true,
    "draftAndPublish": true
  },
  "pluginOptions": {
    "i18n": {
      "localized": true
    }
  },
  "attributes": {
    "title": {
      "type": "string",
      "pluginOptions": {
        "i18n": {
          "localized": true
        }
      }
    },
    "content": {
      "type": "richtext",
      "pluginOptions": {
        "i18n": {
          "localized": true
        }
      }
    }
  }
}

To remove the unnecessary find-one, count and post API routes for the terms content type, change the contents of api/terms/config/routes.json to this:

{
  "routes": [
    {
      "method": "GET",
      "path": "/terms",
      "handler": "terms.find",
      "config": {
        "policies": []
      }
    },
    {
      "method": "PUT",
      "path": "/terms",
      "handler": "terms.update",
      "config": {
        "policies": []
      }
    },
    {
      "method": "DELETE",
      "path": "/terms",
      "handler": "terms.delete",
      "config": {
        "policies": []
      }
    }
  ]
}

Now you have content types set up for all three pages. In the next step, you will add locales for the markets your content is targeted to.

Step 3: Adding the Locales

In this step, you will add the different locales you’d like to support. As explained in the example section, you will add English(America)(en-US), French(Canada)(fr-CA), and Spanish(Mexico)(es-MX). Be sure to run Strapi with npm run develop, then go to the Internationalization settings, under Settings then Global Settings, and add these locales by clicking the blue Add a locale button.

In the popup, select a locale then click Add locale. You should add the three locales listed in the table below. They are all available in the Locales dropdown.

Locale Local Display Name
en-US English(America)
es-MX Spanish(Mexico)
fr-Ca French(Canada)

When adding these locales, set one as the default locale under Advanced Settings in the Add a locale pop-up. This makes it easier when adding content the first time around. If you do not, the first entry will always default to the en locale. If you do not need the en locale, it’s best to delete it after setting an alternate default locale.

In this step, you added locales on your Strapi app. These will be used when you add content. In the proceeding step, you will add placeholder content for each of the pages.

Step 4: Add Content to Strapi App

In this step, you will add content to the Strapi app for each of the three pages. You will do this using the content manager on the admin panel. Here are links to content entry forms on the admin panel for each of the types:

  1. About page
  2. Home page
  3. Terms page

Here’s what a content entry form looks like.

Add a title and some content. When adding content, always check the locale. Make sure the language of the content matches the locale language.

Once you’re done, click the bright green Save button then the Publish button in the top right of the entry form. When you want to add new content for a locale, select it from the Locales dropdown in the Internationalization section on the right of the form. Remember to save and publish the new content.

Here’s what you’ll add for each of the pages for the title field:

English (America)(en-US) French (Canada)(fr-CA) Spanish (Mexico)(ex-MX)
About À propos Sobre
Home Accueil Hogar
Terms Conditions Condiciones

For the content, you can use this lorem ipsum text for all the pages. You can add a flag emoji for the country to identify the change in locale. This is placeholder content only for demonstration purposes.

English (America)(en-US) # 🇺🇸

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec neque ultrices, tincidunt tellus a, imperdiet nulla. Aliquam erat volutpat. Vestibulum finibus, lectus sit amet sagittis euismod, arcu eros tincidunt augue, non lobortis tortor turpis non elit.
French (Canada)(fr-CA) # 🇨🇦

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec neque ultrices, tincidunt tellus a, imperdiet nulla. Aliquam erat volutpat. Vestibulum finibus, lectus sit amet sagittis euismod, arcu eros tincidunt augue, non lobortis tortor turpis non elit.
Spanish (Mexico)(ex-MX) # 🇲🇽

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec nec neque ultrices, tincidunt tellus a, imperdiet nulla. Aliquam erat volutpat. Vestibulum finibus, lectus sit amet sagittis euismod, arcu eros tincidunt augue, non lobortis tortor turpis non elit.

In this step, you added placeholder content in multiple languages for different locales. In the next step, you will make the API routes for the content types public.

Step 5: Making the API Routes Public

In this step, you will make the routes that return page content public. These are the GET routes for /home, /about, and /terms. Currently, if you try to access them, you will get a 403 Forbidden error. This is because the permissions set do not allow them to be accessed publicly. You’ll change this so that they are publicly accessible.

To do this:

  1. head over to the Public Roles settings under Users & Permissions Plugin using this link;
  2. in the Application settings, under Permissions, select the find checkboxes for Home, About, and Terms;
  3. click the bright green Save button in the top right of the page.

Here’s a screenshot of what checkboxes to select in the Application Permissions section in the Public Roles settings page:

Now the routes at http://localhost:1337/home, http://localhost:1337/about, and http://localhost:1337/terms are all accessible. They return the content you entered for the pages in the previous step. To specify a locale when fetching content, use the _locale query parameter and assign it the locale. For example, http://localhost:1337/home?_locale=fr-CA will return the home page for the Canadian French locale. If you do not specify a locale, content for the default locale will be returned.

In this step, you made the routes that return content public. In the next step, you will generate a Hugo site that will consume the localized content.

Step 6: Generate a New Hugo Site

The Hugo site that will display the localized content will be called docs-app. To generate it, run the following command on your terminal in a separate directory outside the docs-server project:

hugo new site docs-app

Running this command will generate a new Hugo site. It will scaffold the site with different folders that contain site input. Hugo will use this input and generate a whole site. However, no themes nor content have been added. You will have to add the content and theme. The content will come from the Strapi application. You can view the new site by running:

cd docs-app && hugo server

The app is served at http://localhost:1313/. However, the app is blank since there is no content yet.

In this step, you generated a new Hugo site. In the next step, you will add a documentation theme to it.

Step 7: Add a Theme to the Hugo Site

Hugo provides support for themes. You can add pre-configured theme components to your site. For the purpose of this tutorial, you will use the hugo-book theme, which is a theme for documentation sites. You can pick from a wide range of themes available on the Hugo theme showcase site. However, make sure that the theme supports internationalization.

To add the book theme, make sure you are in the docs-app folder, and if not, run:

cd docs-app

The app needs to have a git repository to add a theme as a git submodule. To initialize an empty one, run:

git init

To add the book theme, run:

git submodule add https://github.com/alex-shpak/hugo-book themes/book

This command adds the book theme repository as a submodule to the site. It clones the book theme into the themes folder. To view thedocs-app site using the book theme, you can run the app with this command:

hugo server --theme book

Here’s a screenshot of what it looks like:

The site is still pretty bare as it does not contain any content yet. You’ll add content to it from Strapi in the later steps.

In this step, you added a theme to your Hugo site that supports internationalization. In the following step, you will modify the setting of the docs-app site to support internationalization.

Step 8: Modify the Hugo Site Settings

While the book theme supports internationalization, you have to modify the settings of the docs-app to enable it. You will also modify other attributes of the site, like its title and base URL. Additionally, you will include other settings to disable search on the book theme and limit the cache lifespan. In the config.toml file, remove the existing code and add the one below:

# The site base URL
baseURL = 'http://localhost:1313/'

# The default site and content language
languageCode = 'en-us'
defaultContentLanguage = 'en-us'

# The site title
title = 'Docs'

# Setting the site theme to hugo-book
theme = 'book'

[params]
# Disabling search here because it falls out of the scope of this tutorial
BookSearch = false
# The Strapi server URL
StrapiServerURL = 'http://localhost:1337'

[caches]
[caches.getjson]
# Sets the maximum age of cache to 10s before it is cleared.
maxAge = "10s"

[languages]
# The US English content settings
[languages.en-us]
languageName = "English (US)"
contentDir = "content"
# The Canadian French content settings
[languages.fr-ca]
languageName = "Français (Canada)"
contentDir = "content.fr-ca"
# The Mexican Spanish content settings
[languages.es-mx]
languageName = "Español (Mexico)"
contentDir = "content.es-mx"

The StrapiServerURL is the URL of the Strapi server. Since it’s running locally for now, you will use http://localhost:1337. You’re going to use the getJSON Hugo function to fetch data from the server. It caches request results. During development, you may change the content on the Strapi app often, and because of cache, it may not reflect the changes you make. So, using the maxAge config property, you will set it to 10s; thus, the most recent Strapi content changes appear on the site. When you deploy the site, you will have to change this to an adequate timespan depending on how often the site is rebuilt, and the content is changed.

For the language settings, you will define three language categories. For each language, you will define a name and a directory for its content. Each of the content directories will be at the site root. The language names will be displayed in a dropdown where users can select what content they want. Here’s a table of the settings for each language.

Language Name Language Code Content Directory
English (US) en-us content/
Español (Mexico) es-mx content.es-mx/
Français (Canada) fr-ca content.fr-ca/

In this step, you added settings to the Hugo app to make it support internationalization. In the next step, you will modify the theme to accept localized content from an external server.

Step 9: Modify the Theme to Accept Strapi Content

In this step, you will modify the theme to accept data from a Strapi server. Although themes already come with pre-configured templates, you can override them by creating similar files in the layouts folder.

For the hugo-book theme, you will modify the template at themes/book/layouts/partials/docs/inject/content-after.html. This template displays whatever is added in it after the main page content. To do this, you will create this file in the layouts/ folder at the site’s root directory and then add content to it. In this file, you will define a template to fetch markdown content from the server, pass it through the markdown processor, and display it. The logic to fetch the content will be placed in a new partial template that you will call strapi-content. So, to create the content-after file, run these commands on your terminal:

mkdir -p layouts/partials/docs/inject/ && touch layouts/partials/docs/inject/content-after.html

Next, you will create the partial template to fetch content from Strapi:

touch layouts/partials/docs/strapi-content.html

In the layouts/partials/docs/strapi-content.html file, add this code:

<!-- Partial to fetch content from Strapi. -->

{{ $endpoint := $.Param "endpoint" }}
{{ $data := dict "title" "" "content" "" }}

{{ if and $endpoint .Site.Params.StrapiServerURL }}

{{ $contentURL := printf "%s%s" .Site.Params.StrapiServerURL $endpoint }}
{{ $data = getJSON $contentURL }}

{{ end }}

{{ return $data }}

In this partial file, you fetch the endpoint page variable for a specific page and store it in $endpoint. This variable is added to the front matter of content files, as you will see in the proceeding step. Next, you create a variable called $data that is returned at the end of the partial. It will hold the content returned from the Strapi server. You will then assign it a default structure with a title and content. This is done in case no endpoint is specified, or a request is unsuccessful. Afterward, you check if a content endpoint and a Strapi server URL is set. You need both of these for a request. If set, you create a URL for the content you need and use the getJSON function to make a request. Lastly, you return the data.

In layouts/partials/docs/inject/content-after.html, add the code below to the file:

{{ $strapiData := partial "docs/strapi-content" . }}
<article class="markdown">
  <h1>{{ $strapiData.title }}</h1>

  {{ $strapiData.content | markdownify }}
</article>

Here, you are fetching the data using the strapi-content partial template. Once you get the content, you add the title as a heading within the article tag. Lastly, you take the returned content, pass it through the markdown processor using the markdownify function, and display it within the article tag.

In this step, you modified the theme by overriding one of its templates and adding a new partial template to fetch content from Strapi. In the next step, you will add content pages for each of the languages.

Step 10: Add Content Pages to the Hugo Site

In this step, you will add content pages. Each language has a content folder, as shown in the previous steps. The content folder is for English(US) content, content.es-mx for Español (Mexico) content, and content.fr-ca for Français (Canada) content. Each content file has to have an endpoint front matter variable which is the Strapi endpoint that provides its content in a specific language. You’ll add this variable in two archetypes files, archetypes/default.md and archetypes/docs.md.

Archetype files are templates for content files. They can be used to specify the front matter and other content. The hugo new command uses archetypes to generate new content files. archetypes/default.md will be the template for all the _index.md content files while archetypes/docs.md will be for all the content files in docs/ folders. archetypes/docs.md and docs/ are specific to the hugo-book theme. To create the archetypes/docs.md file on your terminal:

touch archetypes/docs.md

Next, replace the content of both archetypes/default.md and archetypes/docs.md with:

---
title: "{{ replace .Name "-" " " | title }}"
endpoint: "/"
---

<br/>

The title will be displayed as the page title and in the table of contents. endpoint, as mentioned earlier, is the Strapi endpoint that provides the content. You add the <br/> tag so that the page is not considered blank during a build.

To create the content folders for the other languages, run this command on your terminal:

mkdir content.es-mx content.fr-ca

Next, add content files for each of the pages:

for cont in "_index.md" "docs/about.md" "docs/terms.md"; do hugo new  $cont; done && for langDir in  "content.es-mx" "content.fr-ca" ; do cp -R content/* $langDir; done

This command creates an _index.md file, a docs/about.md file, and a docs/terms.md file in each of the content directories. Here’s what the content directories will look like after you run this command:

content
├── docs
│   ├── about.md
│   └── terms.md
└── index.md
content.es-mx
├── docs
│   ├── about.md
│   └── terms.md
└── index.md
content.fr-ca
├── docs
│   ├── about.md
│   └── terms.md
└── index.md

Here’s the front matter and content you should add for each of the files:

Home (index.md)

  • content
---
title: "Home"
endpoint: "/home?_locale=en-US"
---

<br/>
  • content.es-mx
---
title: "Hogar"
endpoint: "/home?_locale=es-MX"
---

<br/>
  • content.fr-ca
---
title: "Accueil"
endpoint: "/home?_locale=fr-CA"
---

<br/>

About (docs/about.md)

  • content
---
title: "About"
endpoint: "/about?_locale=en-US"
---

<br/>
  • content.es-mx
---
title: "Sobre"
endpoint: "/about?_locale=es-MX"
---

<br/>
  • content.fr-ca
---
title: "À propos"
endpoint: "/about?_locale=fr-CA"
---

<br/>

Terms (docs/terms.md)

  • content
---
title: "Terms"
endpoint: "/terms?_locale=en-US"
---

<br/>
  • content.es-mx
---
title: "Condiciones"
endpoint: "/terms?_locale=es-MX"
---

<br/>
  • content.fr-ca
---
title: "Conditions"
endpoint: "/terms?_locale=fr-CA"
---

<br/>

So, all you need to do now is run the Hugo server. Before you do this, make sure that the Strapi app is running with npm run develop in a different terminal within the docs-server folder, so Hugo can fetch content from it when building the site. You can run the Hugo server using this command:

hugo server

Note About Routine Automated Rebuilds

Since Hugo creates static sites, the content displayed will not be dynamic. Hugo gets the content from the Strapi server during build time and not on the fly when a page is requested. So, if you’d like content to regularly reflect what is on the Strapi server, make sure to automate rebuilds of your Hugo site regularly or as often as changes to the content are made. For example, if your site is hosted on Netlify, you can schedule regular rebuilds of your site.

Conclusion

Hugo is a static site generator that allows you to build fast and efficient static sites. It offers multilingual support using its internationalization feature. You can specify a range of languages, and Hugo will build a site to support each of them. Strapi is a headless CMS that allows its users to manage content with more flexibility. It provides an admin portal to enter and manage content and a customizable API that different frontends can consume the content through. It also offers an internationalization plugin to manage content in different locales.

In this tutorial, you created a Strapi application. Using this app, you added three single content types to represent data for three pages: a home, an about, and a terms page. You added content for each of the pages for three locales: English (US), Español (Mexico), and Français (Canada). You also generated APIs to access content for these pages and made some of its routes public.

After, you generated a Hugo app. In this app, you added a documentation theme, configuration to support internationalization, and content pages for different languages. Lastly, you modified the theme to consume content from Strapi. If you’d like to build out more of the app, try adding more content page types with complex structures or adding content in a new language.

If you’d like to learn more about Hugo, check out their documentation page. To find out more about what you can do with Strapi and the range of features it offers, head to its website here.

How to Set Up a Remote Desktop

Want to just get started? Sign up for Zoho Assist and create your remote desktop today.

In your workplace, there are a few things that you need in order to be productive. Sometimes, you need a second monitor to get all of your work done.

Or, you might need to access certain files that are only stored on your work computer.

If you find yourself in any of these situations, you can set up a remote desktop.

A remote desktop allows you to access another computer as if you were sitting right in front of it. All you need is an internet connection and a computer or mobile device.

The Top Remote Support Software to Set Up a Remote Desktop

If you want to set up a remote desktop, you need to have the right software. Here are the best software solutions to help you do that:

  • Zoho Assist – Best for unattended remote access
  • TeamViewer – Best for efficient remote support
  • BeyondTrust – Best for extra security enforcement
  • AnyDesk – Best for fast, user-friendly remote desktop support
  • Pulseway – Best for personal use

You can read our full reviews of the best remote software solutions here. 

5 Steps to Setting Up a Remote Desktop

Now that you know which software to use, it’s time to set up your remote desktop. Here’s how to get started:

  1. Allow remote connections using Settings or Control Panel
  2. Get started with Zoho Assist
  3. Start your remote support session
  4. Connect to the remote desktop
  5. Use your remote desktop for whatever you need

The Easy Parts of Setting Up a Remote Desktop

A remote desktop can be a useful tool for working from home or accessing your computer from a different location.

Although the process may sound daunting, setting up a remote desktop is actually quite simple. In most cases, all you need is two things:

A Stable Internet Connection

In order to set up a remote desktop, you need to have a stable internet connection. This is because the remote desktop uses your internet connection to create a secure, encrypted connection between your two devices. Without a stable internet connection, the remote desktop will not be able to function properly, and you will not be able to access the other computer.

Without a stable connection, the remote desktop will either not work at all or will be very slow and sluggish, resulting in a poor user experience. This can make it difficult or even impossible to get work done.

The IP Address of the Computer You Wish to Connect To

The IP address is necessary to set up the connection because it is how the computer you are using to access the remote desktop knows where to find the computer you want to control.

When you are using a remote desktop, the computer you are using essentially becomes a controller that sends commands to the computer you want to control.

In order to do this, it needs to know the IP address of the destination computer. The IP address acts as a sort of address or location for the destination computer, so without it, the remote desktop connection cannot be established.

Once you have these two things, you can use any free or paid software options to establish a secure connection.

While there may be some initial setup required, once the connection is established, using a remote desktop is usually just as easy as using your computer in person. 

The Hard Parts of Setting Up a Remote Desktop

While there are certainly many advantages to setting up a remote desktop, there are also a few potential challenges that users should be aware of:

Configuring Your Software

One of the most difficult aspects of setting up a remote desktop is ensuring that all of the necessary software is installed and configured correctly. This can often be a time-consuming and frustrating process, particularly for users who are not familiar with the relevant software.

Without the proper software, the remote desktop will not be able to function properly. In addition, the software must be compatible with the operating system and hardware of the remote desktop.

If the software is not compatible, it may cause errors or crashes. Furthermore, the software must be properly licensed and up-to-date. Otherwise, it may not work correctly or may not be supported by the manufacturer.

Ensuring the Remote Desktop is Secured

Another potential issue is ensuring that the remote desktop is properly secured. This typically involves configuring firewall settings and taking other security precautions.

To check your network security, you can use the Windows Firewall tool or a third-party security program. You should also make sure that your remote desktop software is up-to-date and has all of the latest security patches installed.

Failure to take these steps could result in sensitive data being compromised or malicious actors gaining access to the system. 

Troubleshooting on Remote Desktops

Troubleshooting problems with your remote desktop can be difficult, as it can be hard to determine exactly where the problem lies.

This is because the connection between the two computers is often not as stable as a direct connection. As a result, problems that occur may be due to either the remote desktop or the local computer.

In some cases, it may even be due to the internet connection itself. This can make troubleshooting slow and difficult, as well as frustrating for users who are not familiar with the process.

Despite these challenges, setting up your remote desktop can be a great way to improve workplace productivity and connectivity.

Step 1: Allow remote connections using Settings or Control Panel

To connect a remote computer, remote connections must be enabled. You can do this through the Settings app or the Control Panel.

Enabling Remote Access in Settings

Windows Remote Desktop is a useful tool for working on your office PC from home. By default, remote connections are not allowed on Windows 10 PCs.

However, you can easily enable this feature through the Settings app.

To do so, open the Settings app and go to the “System” category.

Then click Remote Desktop in the left sidebar. In the main pane, toggle the switch next to “Enable Remote Desktop” to the “On” position.

System category in Settings app with Remote Desktop selected in the left sidebar and a red square around the toggle for Enable Remote Desktop

A popup menu will appear. Click Confirm.

Confirmation window for enabling remote desktop

Once you’ve done this, you’ll be able to connect to your PC from another device using the Remote Desktop app.

Once you complete the steps, you can connect to the computer using the modern Remote Desktop app (recommended) or the Remote Desktop Connection app included with Windows 10.

You’ll also find two new options that are there to ensure you can always connect when you’re away.

These are “Keep my PC awake for connection when it is plugged in” and “Make my PC discoverable on private networks to enable automatic connection from a remote device.”

Remote Desktop screen in settings with red square around options to keep PC awake for connection when it is plugged in and make PC discoverable on private networks

If you want to further customize your remote connection settings, you can click the Advanced Settings link in the main pane. From here, you can specify which users are allowed to connect remotely, as well as other options such as network encryption and authentication. 

Advanced Settings screen

Enabling Remote Access in Control Panel

Windows 8 and 10 allow you to add users who can remotely access your computer through the Desktop app. If you have Windows 7, you’ll need to follow a few extra steps. First, open the Control Panel and go to System and Security > System.

Windows System and Security screen with red square around Allow remote access button

Under System, click Allow remote access on the right-hand side.

Windows System Properties screen with red box around option to allow remote connections to this computer

Under the Remote Desktop section, click the Allow remote connections to this computer radio button.

If you want, you can also click the Allow connections only from computers running Remote Desktop with Network Level Authentication (more secure) radio button.

This will prevent anyone without the proper credentials from accessing your computer.

You can also click the Select Users button to specify which users are allowed to connect.

If you want to allow all users on your network to access your computer, click the Allow all users radio button.

When you’re done, click the OK button.

You should now be able to remotely connect to your computer using the Remote Desktop app.

Step 2: Get started with Zoho Assist

Zoho Assist landing page

Zoho Assist is an excellent tool for remotely accessing and controlling another computer. Thanks to its ease of use and accessibility (it’s free), it is an excellent option for small businesses or home users.

Getting started with Zoho Assist is very straightforward. To do so, head to the Zoho Assist website and create a free account. Once you’ve done this, you can download the Zoho Assist client onto your computer.

Zoho Assist signup screen

You will be prompted to enter your email address and create a password.

Once you have done this, your free trial will begin. Zoho Assist is free for personal use, but its enterprise features are free to use for 15 days with all new subscriptions.

After you have signed up and logged in, you will be taken to the main screen.

This is where you can add new computers, view recent activity, and access all of the features of Zoho Assist.

Step 3: Start your remote support session

To start a new remote support session right away, click the Start Now button. If you wish to initiate a session at a later time, you can click Schedule to set up a time in the future.

You will then be asked to locate the person you wish to connect with for your remote support session.

To do so, you can reach them in one of four ways:

  1. SMS invitation: You can send an SMS invitation to the person you wish to connect with. This is useful if they do not have an email address or if you want to connect with them right away.
  2. Email invitation: You can send an email invitation to the person you wish to connect with. This is a good option if they are not available by phone.
  3. Click a link to join the session: You can have your target user go to join.zoho.com to join a session if you don’t have their contact information.
  4. Create and send an invitation: You can create an invitation with your own custom message and branding, then send it to the person you wish to connect with through the messaging app of your choosing.

After you have selected how you would like to reach the person you wish to connect with, proceed to the next step.

Step 4: Connect to the remote desktop

Once you’ve sent the session invitation to the remote customer, connecting with the other computer is very simple.

Once your customer receives the invite and navigates to the session, they will be allowed to join the session through the above methods with a matching ID.

They will be prompted to download the Zoho Assist client if they haven’t done so already.

Once the client is downloaded and installed, you can select the target computer from the “Unattended Access” tab on the main screen.

You will then be asked to enter your email address and password. After doing so, you will be connected to the remote desktop.

You can now view and control the other person’s computer as if you were sitting in front of it.

Step 5: Use your remote desktop for whatever you need

Now that you have your remote device up and running, here are a few best practices to ensure your safety:

  • You have the same access to files and applications as the other person. This means you can view, edit, and delete files just as they can.
  • Be careful what you do on the remote computer. Just as you would not want someone else snooping around on your computer, respect the privacy of others by refraining from snooping on their computer.
  • Do not install any software on the remote computer without the other person’s permission. This includes things like games, programs, and even browser extensions.
  • Be aware that the other person can see everything you are doing on their computer. If you need to step away from the keyboard for a moment, be sure to let the other person know, so they are not left wondering what you are up to.

Now that you have your remote desktop set up, you may be wondering what you can do with it.

The answer is: anything you need!

If you are providing technical support, for example, you can use your remote desktop to view and control the other person’s computer. This can be a huge help when trying to diagnose and solve problems.

Remote desktops can also be used for less serious purposes, such as playing games or streaming movies from another person’s computer.