Nuxt 3: SSR, VUE 3, Quasar, Pinia, KeyCloak & PWA.
Modern way of UI Development!
If you need to quickly build an SEO-friendly and production-ready UI with SSR enabled for optimal performance, then start reading….
Before getting started with Nuxt 3 + SSR, VUE 3, Quasar, Pinia, KeyCloak, and PWA, make sure to install Node and either VSCode or Fleet (I personally liked the preview version of the fleet).
🚛 To set up the basic project, create and run a basic Nuxt App using the following commands:
>> npx nuxi init new_ui
>> cd new_ui
>> npm install
>> code . <-- Opens VS Code
>> npm run dev <-- to test the basic app
🚛 To add Quasar, run the following commands:
npm install quasar @quasar/extras
npm install --save-dev nuxt-quasar-ui
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
modules: ["nuxt-quasar-ui"],
quasar: {
extras: {
font: 'roboto-font',
fontIcons: ['material-icons'],
}
},
});
Then, add the following snippet to app.vue:
<template>
<div>
<q-btn color="primary" label="Primary" />
<QBtn color="secondary" label="Secondary" />
<LazyQBtn color="amber" glossy label="Amber" />
<NuxtWelcome />
</div>
</template>
🚛 Add Aya Vue3 Extension Packs + Volar!
🚛 To install the necessary plugins and modules, run the following commands:
>> npm install @nuxtjs/i18n@next --save-dev
>> npm install @pinia/nuxt
>> npm install @nuxtjs/robots
>> npm install @nuxtjs/eslint-module
>> npm install @nuxtjs/html-validator
>> npx nuxi@latest devtools enable
🚛 Install the Dev Tools: Useful for further debugging.
>> npx nuxi@latest devtools enable
Restart your server and take a look at the Dev Tools.
🚛 To add PWA, run the following command:
npm i --save-dev @nuxtjs/pwa
Then, add the following code to the Nuxt config:
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
modules: ["nuxt-quasar-ui"],
buildModules: ["@nuxtjs/pwa"],
quasar: {
extras: {
font: "roboto-font",
fontIcons: ["material-icons"],
},
},
pwa: {
meta: {
name: "abc",
author: "abc Inc",
description: "abc desc",
},
manifest: {
name: "My Awesome App",
lang: "en",
useWebmanifestExtension: false,
start_url: "abc.com",
display: "standalone",
background_color: "#fff3e0",
theme_color: "#fff3e0",
},
workbox: {
runtimeCaching: [
{
urlPattern: "https://assets.abc.com/.*",
strategyOptions: {
cacheName: "pwa-image-cache",
},
strategyPlugins: [
{
use: "Expiration",
config: {
maxEntries: 100,
maxAgeSeconds: 60 * 60 * 24 * 30,
},
},
],
},
],
},
},
});
- Create a static folder and add your icon (512x512) to it, as Nuxt PWA will auto-generate the necessary icons using this.
- Also, add “sw.*” to .gitignore as this file will be auto-generated as well.
Restart the app by running `npm run dev`. Just to ensure you are not breaking the app with your configs so far!
🚛 Next, create the Nuxt folder structure (here) and add Pinia, the intuitive store for Vue.js, by adding the following code to package.json and running “npm install”:
🚛 Add Pinia: The intuitive store for Vue.js (More details here)
for package.json add the below snippet and run “npm install”
"overrides": {
"vue": "latest"
}
npm install pinia @pinia/nuxt
nuxt.config.ts
modules: ["@pinia/nuxt"],
pinia: {
autoImports: ["defineStore", "acceptHMRUpdate"],
},
If you like to maintain all the stores in one place, create a “stores” dir and let the nuxt know about it for auto imports. Add the below line in nuxt.config.ts
imports: { dirs: ["stores"] },
🚛 To enable SSR, add the following code to nuxt.config.ts:
ssr: true
Retstrat the app to check you are not breaking any configs.
- To add LogRocket and KeyCloak as needed use the following commands:
npm install logrocket
<script setup lang="ts">
import LogRocket from 'logrocket';
LogRocket.init('ulrfwc/test');
LogRocket.identify('Gopi', {
name: 'GOPI',
email: 'test@test.com',
subscriptionType: 'pro',
});
</script>
Add the above snippet to app.vue
🚛 Dot Env:
Set your runtimeConfig inside nuxt.config.ts
runtimeConfig: {
gwEndPoint: '',
public: {
authClientId: '',
authRealm: '',
authUrl: '',
stripeKey: '',
},
},
Create your .env files
.env
.env.local
.env.qa
.env.prod
Have the naming compatible as follows inside the .env files:
NUXT_PUBLIC_AUTH_URL=http://keycloak:9080/auth/
NUXT_GW_ENDPOINT=http://localhost:8080
NUXT_STRIPE_KEY=test_key
NUXT_PUBLIC_AUTH_REALM=Test
NUXT_PUBLIC_AUTH_CLIENT_ID=Test_APP
Now modify the package.json scripts
"dev": "nuxt dev --dotenv .env.local",
Now, you should be able to access the configuration in plugins and files as below:
const runtimeConfig = useRuntimeConfig();
const initOptions: KeycloakConfig = {
url: runtimeConfig.authUrl,
realm: runtimeConfig.authRealm,
clientId: runtimeConfig.authClientId,
};
🚛 KeyClaok:
npm i keycloak-js
over all package.json
"devDependencies": {
"@nuxt/content": "^2.5.2",
"@nuxtjs/pwa": "^3.3.5",
"nuxt": "^3.3.2",
"nuxt-quasar-ui": "^1.3.1"
},
"dependencies": {
"@pinia/nuxt": "^0.4.7",
"@quasar/extras": "^1.16.1",
"keycloak-js": "^21.0.2",
"logrocket": "^4.0.0",
"nuxt-icons": "^3.1.0",
"pinia": "^2.0.33",
"quasar": "^2.11.9",
"sass": "^1.60.0"
},
"overrides": {
"vue": "latest"
}
Create a Keycloak Plugin: (keycloak.client.ts)
import Keycloak, { KeycloakConfig } from 'keycloak-js';
export default defineNuxtPlugin((nuxtApp) => {
const runtimeConfig = useRuntimeConfig();
const initOptions: KeycloakConfig = {
url: runtimeConfig.authUrl,
realm: runtimeConfig.authRealm,
clientId: runtimeConfig.authClientId,
};
const keycloak = new Keycloak(initOptions);
nuxtApp.$keycloak = keycloak;
keycloak
.init({
// Use 'login-required' to always require authentication
// If using 'login-required, check-sso', there is no need for the router guards in router.js - check-sso
onLoad: 'check-sso',
});
console.log('KeyCloak Plugin Loaded: ', nuxtApp.$keycloak);
});
Create a button and click on that in the index.vue
<template>
<q-page-container>
<q-page class="q-pa-md">
<q-btn label="Test KeyCloak" @click="login()"></q-btn>
<q-page-scroller position="bottom">
<q-btn fab icon="keyboard_arrow_up" color="red"></q-btn>
</q-page-scroller>
</q-page-container>
</template>
<style lang="scss" scoped></style>
<script setup lang="ts">
import Keycloak from 'keycloak-js';
function login() {
console.log('----> ', useNuxtApp().$keycloak);
(useNuxtApp().$keycloak as Keycloak).login();
}
</script>
That's all!