DEV Community

Cover image for Osteo multilingual website with Nuxt, Express and Tailwind 🌍

Posted on

Osteo multilingual website with Nuxt, Express and Tailwind 🌍

To help my sister who is an osteopath to gain visibility on the internet, I created a website from scratch. This was an opportunity for me to try new web frameworks that meet the following different needs:

  • Multilingual 🌍
  • Send mail from the contact form 📬
  • A good ranking on search engine = SEO 💯
  • Embed map to localize the office 🗺
  • Nature/Health theme design 🌿
  • Responsive 📱

After 2 weeks of programming during my spare time, here we are :

I did create a website from scratch but I never had technical or design feedback, that why I am sharing with you the link to discuss any improvement possible.


If you want to know how it works, here is the "behind the scene":

  • Nuxtjs It is a framework to build fast and robust websites using Vuejs. To ensure SEO best practice, server side rendering is required. Express is used as a server to render the nuxt instance (learn more). In that way, a backend API can be created easily! The community and support around Nuxt and Vuejs is impressive.
  • Tailwind After using Vuetify for a long time (pretty damn good framework), I wanted to learn different designs and practices. This utility CSS framework brings you to focus more on creating than losing time by searching and solving CSS issues. To make a fully responsive and professional design, I followed the good practice given by the Refactoring UI Book (from Adam Whatan & Steve Schoger).
  • nuxt-i18n Multilingual has been easy to set up with this i18n module for Nuxt, the documentation is straightforward with examples. In the lang folder, each JS file corresponds to a translation of the site in a different language and Nuxt lazy load the content on demand. Besides, the module is adding metadata automatically to improve SEO with an option to enable (It may impact the page performance).
  • nuxt-sitemap This module generates the sitemap automatically from the route you have defined on nuxt, the project is based on the sitemap.js package. It works pretty well except for the lack of information about the multilingual support. Few issues are talking about it (#91, #40, examples) and I had to update the sitemap generation. To complete my research, I found this article by Google of creating a sitemap with localized versions of the pages. In the nuxt.config.js, I created a small function that creates the routes with all the alternative links:
// Routes used for the nuxt i18n module
let i18nRoutes = {
  about: {
    en: '/about',
    fr: '/a-propos'
// Website languages
const langsKeys = ['en', 'fr']
// Routes formatted for sitemap
const routesSiteMap = []
langsKeys.forEach((lang) => {
  const routes = Object.keys(i18nRoutes).map((keyPages) => {
    const page = i18nRoutes[keyPages]
    return {
        lang === 'fr'
          ? `${i18nRoutes[keyPages][lang]}`
          : `/${lang}${i18nRoutes[keyPages][lang]}`,
      links: Object.keys(page).reduce((acc, keyLang) => {
          lang: keyLang,
            keyLang === 'fr'
              ? `${page[keyLang]}`
              : `/${keyLang}${page[keyLang]}`
        return acc
      }, [])
Enter fullscreen mode Exit fullscreen mode

Then routesSiteMap is passed to the sitemap module routes options

## ...
sitemap: {
    hostname: process.env.BASE_URL,
    gzip: true,
    defaults: {
      changefreq: 'monthly'
    routes: routesSiteMap
Enter fullscreen mode Exit fullscreen mode

Successfully, it generates the alternative location links on the sitemap to welcome the web crawlers. Do you have better practices using Nuxt-i18n to generate a sitemap?

  • nuxt-leaflet Open Source Map providing Vuejs components with a lot of options. It is necessary to configure PurgeCSS so as not to remove Leaflet's CSS.. I had to add a PurgeCSS option into nuxt.config.js to whitelist leaflet patterns #170.
  • nodejs-nodemailer-outlook This Github is providing the essential (with one function) to send a mail with Outlook. On the express server, I have created an endpoint POST to send an email when a person is filling the form. I coupled a captcha to the form and a server side input verification to avoid bots/scam/XSS/etc... 🤖
  • unDraw All the awesome illustrations on the website are coming from unDraw. It is my favorite resource for open source illustrations.
  • BunnyCDN To gain speed on loading the website over the world, I decided to host the public static files to BunnyCDN. After comparing services, it is one of the cheapest and top 20 most efficient. It is pretty easy to set up a CDN to Nuxtjs, just change the build config publicPath to the CDN URL and upload the content of .nuxt/dist/client to the CDN. The server is hosted on OVH (VPS).
  • Small Optimizations:
    • Reduced and minimized images (Less than ~100KB)
    • Display the captcha with a v-if. In that way, the google scripts are loaded only after the form is filled.
    • Added a JSON structured data.


The website is loading on average less than 1 second, online SEO tools are rating good and the same goes for the Google Lighthouse. I'm pretty happy with the design result but there is maybe a lot to improve.

What do you think of it globally? Is the design looking good and consistent? Do you see any improvements?

Any advice is greatly appreciated! Also if you come across a security breach, contact me on Keybase: @steevepay

Thanks for reading!

Top comments (2)

nicopennec profile image
Nicolas PENNEC

Great blog post 👍

About the the sitemap module, since the release v2.3.0 you can generate the i18n routes from nuxt-i18n (but only static routes):

Let me know if it works well for you 😉

steeve profile image

Thank you! it was exactly what I was looking for 😀 I'll try this out