Osteo multilingual website with Nuxt, Express and Tailwind 🌍
Tags: node, vue, showdev
Published: 2020-04-12 08:48:07

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 :
[https://osteopathe-steffie.fr](https://osteopathe-steffie.fr)

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.

## Stack

If you want to know how it works, here is the "behind the scene":
- [Nuxtjs](https://nuxtjs.org/) 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](https://nuxtjs.org/api/nuxt-render)). In that way, a backend API can be created easily! The community and support around Nuxt and Vuejs is impressive.
- [Tailwind](https://tailwindcss.com/) 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](https://twitter.com/adamwathan) & [Steve Schoger](https://twitter.com/steveschoger)).
- [nuxt-i18n](https://github.com/nuxt-community/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](https://nuxt-community.github.io/nuxt-i18n/lazy-load-translations.html) on demand. Besides, the module is adding metadata automatically to improve SEO with an option to enable ([It may impact the page performance](https://nuxt-community.github.io/nuxt-i18n/seo.html#improving-performance)).
- [nuxt-sitemap](https://github.com/nuxt-community/sitemap-module) This module generates the sitemap automatically from the route you have defined on nuxt, the project is based on the [sitemap.js](https://github.com/ekalinin/sitemap.js) package. It works pretty well except for the lack of information about the multilingual support. Few issues are talking about it ([#91](https://github.com/nuxt-community/sitemap-module/issues/91), [#40](https://github.com/nuxt-community/sitemap-module/issues/40#issuecomment-452555170), [examples](https://github.com/ekalinin/sitemap.js#options-you-can-pass)) and I had to update the sitemap generation. To complete my research, I found [this article by Google](https://support.google.com/webmasters/answer/189077) 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:
```js
// 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 {
      url:
        lang === 'fr'
          ? `${i18nRoutes[keyPages][lang]}`
          : `/${lang}${i18nRoutes[keyPages][lang]}`,
      links: Object.keys(page).reduce((acc, keyLang) => {
        acc.push({
          lang: keyLang,
          url:
            keyLang === 'fr'
              ? `${page[keyLang]}`
              : `/${keyLang}${page[keyLang]}`
        })
        return acc
      }, [])
    }
  })
  routesSiteMap.push(...routes)
})
```
Then `routesSiteMap` is passed to the sitemap module `routes` options
```js
## ...
sitemap: {
    hostname: process.env.BASE_URL,
    gzip: true,
    defaults: {
      changefreq: 'monthly'
    },
    routes: routesSiteMap
}
##...
```
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](https://github.com/schlunsen/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](https://github.com/FullHuman/purgecss/issues/170).
- [nodejs-nodemailer-outlook](https://github.com/Youans/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](https://undraw.co/) All the awesome illustrations on the website are coming from unDraw. It is my favorite resource for open source illustrations.
- [BunnyCDN](https://bunnycdn.com/) 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](https://developers.google.com/search/docs/guides/intro-structured-data).

## Conclusion

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](https://keybase.io/steevepay)

Thanks for reading!