[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"global-header-tutorials-static":3,"article-securing-nuxt-ssr-app-with-cookies-sessions":4,"initial-similar-fetch":22},[],{"alias":5,"title":6,"description":7,"content":8,"thumbnail":9,"keywords":10,"categories":18,"tags":20,"createdAt":21},"securing-nuxt-ssr-app-with-cookies-sessions","Securing Nuxt SSR Apps with cookies sessions","Nuxt 4 App how to create an authentication system in SSR mode","{\"type\":\"doc\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"In this tutorial, we are going to learn how to create a fully secure system for our Nuxt application.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Here, we are going to consider that your Nuxt App is SSR, and we are going to use \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"nuxt-auth-utils\"},{\"type\":\"text\",\"text\":\" for developing the secure system. \"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"The general workflow will be, instead of the browser talking with our backend server, it will communicate with the Nitro server(SSR), and the Nitro server will communicate with our backend server for fetching data.\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":2},\"content\":[{\"type\":\"text\",\"text\":\"How It Works\"}]},{\"type\":\"bulletList\",\"content\":[{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"The client submits the login credentials to the Nitro Server. Nitro forwards this payload to the backend server. Which then receives the JWT token or any other credentials to manage the Authentication. The \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"nuxt-auth-util\"},{\"type\":\"text\",\"text\":\" will encrypt it and store it in the session under the hood.\"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"We will not expose the token in the browser and secured fully in the Nitro server. \"}]}]},{\"type\":\"listItem\",\"content\":[{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Now, when a user requests the secured endpoint, the Nitro server will get the session token and add it to the header to send to the backend server for data fetching.\"}]}]}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":2},\"content\":[{\"type\":\"text\",\"text\":\"Install nuxt-auth-utils\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Add \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"nuxt-auth-utils\"},{\"type\":\"text\",\"text\":\" in our Nuxt app.\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"bash\"},\"content\":[{\"type\":\"text\",\"text\":\"npx nuxi@latest module add auth-utils\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"The above command will add the following things:\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Inside \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"nuxt.config.ts\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"ts\"},\"content\":[{\"type\":\"text\",\"text\":\"modules: [\\n    .....\\n    'nuxt-auth-utils'\\n  ],\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Inside the \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\".env\"},{\"type\":\"text\",\"text\":\" file\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"bash\"},\"content\":[{\"type\":\"text\",\"text\":\"NUXT_SESSION_PASSWORD=password-with-at-least-32-characters\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Add types for user session\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"We can define  the type of the user session by creating a type declaration file. Under \"},{\"type\":\"text\",\"marks\":[{\"type\":\"italic\"},{\"type\":\"code\"}],\"text\":\"\u002Fshared\u002Ftypes\u002Fauth.d.ts \"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"ts\"},\"content\":[{\"type\":\"text\",\"text\":\"declare module '#auth-utils' {\\n    interface UserSession {\\n        user: {\\n            authenticatedAt: string\\n        },\\n        secure: {\\n            token: string\\n        }\\n    }\\n}\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Here, the user definition must be mandatory for a logged-in user. Here we are using the \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"authenticatedAt\"},{\"type\":\"text\",\"text\":\" field; you can use your user info fields like email, profiles, etc.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"The \"},{\"type\":\"text\",\"marks\":[{\"type\":\"bold\"},{\"type\":\"code\"}],\"text\":\"secure\"},{\"type\":\"text\",\"text\":\" block is the most important part here. The fields or data inside the secure block will be available and accessible only inside the Nitro server and not in the browser. \"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Add Session Expiry\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"To add the expiry of our token or user session and default password, add the below config in our Nuxt config file \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"nuxt.config.ts\"},{\"type\":\"text\",\"text\":\".\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"ts\"},\"content\":[{\"type\":\"text\",\"text\":\" runtimeConfig: {\\n    session: {\\n      maxAge: 60 * 60 * 24 * 7, \u002F\u002F 1 week\\n      password: process.env.NUXT_SESSION_PASSWORD\\n    },\\n  },\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":2},\"content\":[{\"type\":\"text\",\"text\":\"Client Login Component\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Let's create a browser\u002Fclient login. For this, create a file \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"login.vue\"},{\"type\":\"text\",\"text\":\" \"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"vue\"},\"content\":[{\"type\":\"text\",\"text\":\"\u003Cscript setup lang=\\\"ts\\\">\\nconst auth = useAuthStore()\\nconst toast = useToast()\\nconst loading = ref(false)\\n\\nconst state = reactive({\\n  username: '',\\n  password: ''\\n})\\n\\nasync function onSubmit() {\\n  loading.value = true\\n  const success = await auth.login(state)\\n\\n  if (success) {\\n    toast.add({\\n      title: 'Access Granted',\\n      description: 'Redirecting to CSBYTE command center...',\\n      color: 'primary'\\n    })\\n    navigateTo('\u002Fadmin')\\n  } else {\\n    toast.add({\\n      title: 'Authentication Failed',\\n      description: 'Please check your credentials and try again.',\\n      color: 'danger'\\n    })\\n  }\\n  loading.value = false\\n}\\n\u003C\u002Fscript>\\n\\n\u003Ctemplate>\\n  \u003Cdiv class=\\\"min-h-screen flex items-center justify-center bg-[#050505] relative overflow-hidden\\\">\\n    \u003Cdiv class=\\\"absolute top-[-10%] left-[-10%] w-[40%] h-[40%] bg-primary-500\u002F10 blur-[120px] rounded-full\\\" \u002F>\\n    \u003Cdiv class=\\\"absolute bottom-[-10%] right-[-10%] w-[40%] h-[40%] bg-blue-500\u002F10 blur-[120px] rounded-full\\\" \u002F>\\n\\n    \u003CUContainer class=\\\"z-10 w-full max-w-md\\\">\\n      \u003Cdiv class=\\\"mb-8 text-center\\\">\\n        \u003Cdiv class=\\\"inline-flex items-center justify-center w-16 h-16 rounded-2xl bg-gradient-to-br from-neutral-800 to-neutral-900 border border-neutral-700 shadow-2xl mb-4 group hover:border-primary-500\u002F50 transition-colors\\\">\\n          \u003Cspan class=\\\"text-2xl font-black bg-clip-text text-transparent bg-gradient-to-r from-primary-400 to-blue-400\\\">CB\u003C\u002Fspan>\\n        \u003C\u002Fdiv>\\n        \u003Ch1 class=\\\"text-2xl font-bold tracking-tight text-white uppercase italic\\\">\\n         CsByte Admin\\n        \u003C\u002Fh1>\\n        \u003Cp class=\\\"text-neutral-500 text-sm mt-1\\\">Terminal Authentication Required\u003C\u002Fp>\\n      \u003C\u002Fdiv>\\n\\n      \u003CUCard\\n          :ui=\\\"{\\n          base: 'bg-neutral-900\u002F50 backdrop-blur-xl border-neutral-800 shadow-[0_0_50px_-12px_rgba(0,0,0,0.5)]',\\n          body: 'p-8'\\n        }\\\"\\n      >\\n        \u003CUForm :state=\\\"state\\\" @submit=\\\"onSubmit\\\" class=\\\"space-y-6\\\">\\n          \u003CUFormField label=\\\"Operator Username\\\" name=\\\"username\\\" :ui=\\\"{ label: 'text-neutral-400 text-xs font-bold uppercase tracking-widest' }\\\">\\n            \u003CUInput\\n                v-model=\\\"state.username\\\"\\n                placeholder=\\\"e.g. admin\\\"\\n                icon=\\\"i-lucide-terminal\\\"\\n                color=\\\"neutral\\\"\\n                variant=\\\"subtle\\\"\\n                size=\\\"xl\\\"\\n                class=\\\"w-full\\\"\\n            \u002F>\\n          \u003C\u002FUFormField>\\n\\n          \u003CUFormField label=\\\"Security Key\\\" name=\\\"password\\\" :ui=\\\"{ label: 'text-neutral-400 text-xs font-bold uppercase tracking-widest' }\\\">\\n            \u003CUInput\\n                v-model=\\\"state.password\\\"\\n                type=\\\"password\\\"\\n                icon=\\\"i-lucide-shield-check\\\"\\n                color=\\\"neutral\\\"\\n                variant=\\\"subtle\\\"\\n                size=\\\"xl\\\"\\n                class=\\\"w-full\\\"\\n            \u002F>\\n          \u003C\u002FUFormField>\\n\\n          \u003CUButton\\n              type=\\\"submit\\\"\\n              block\\n              size=\\\"xl\\\"\\n              color=\\\"primary\\\"\\n              :loading=\\\"loading\\\"\\n              class=\\\"font-bold uppercase tracking-widest py-4 transition-all hover:shadow-[0_0_20px_-5px_var(--color-primary-500)]\\\"\\n          >\\n            Authorize Access\\n          \u003C\u002FUButton>\\n        \u003C\u002FUForm>\\n      \u003C\u002FUCard>\\n\\n      \u003Cdiv class=\\\"mt-8 text-center\\\">\\n        \u003CNuxtLink to=\\\"\u002F\\\" class=\\\"text-neutral-600 hover:text-neutral-400 text-xs flex items-center justify-center gap-2 transition-colors\\\">\\n          \u003CUIcon name=\\\"i-lucide-arrow-left\\\" class=\\\"w-3 h-3\\\" \u002F>\\n          Back to Public Feed\\n        \u003C\u002FNuxtLink>\\n      \u003C\u002Fdiv>\\n    \u003C\u002FUContainer>\\n  \u003C\u002Fdiv>\\n\u003C\u002Ftemplate>\\n\\n\u003Cstyle scoped>\\n\u002F* Optional: Adding a metallic texture overlay *\u002F\\n.bg-neutral-900\\\\\u002F50 {\\n  background-image: url(\\\"data:image\u002Fsvg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg'%3ExternalForce%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'\u002F%3E%3C\u002Ffilter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'\u002F%3E%3C\u002Fsvg%3E\\\");\\n  background-blend-mode: overlay;\\n  opacity: 0.98;\\n}\\n\u003C\u002Fstyle>\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"This is the sample login page for authentication.\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Creating AuthStore\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Let's create a composible \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"useAuthStore.ts\"},{\"type\":\"text\",\"text\":\" \"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"ts\"},\"content\":[{\"type\":\"text\",\"text\":\"export const useAuthStore = defineStore('auth', () => {\\n    const { user, loggedIn:isAuthenticated, clear, fetch: fetchSession } = useUserSession()\\n\\n    async function login(credentials: { username: string; password: any }) {\\n        try {\\n            await $fetch('\u002Fapi\u002Fauth\u002Flogin', {\\n                method: 'POST',\\n                body: credentials\\n            })\\n            await fetchSession()\\n            return true\\n        } catch (error) {\\n            console.error('Login failed:', error)\\n            return false\\n        }\\n    }\\n\\n    async function logout() {\\n        await clear()\\n        navigateTo('\u002Flogin')\\n    }\\n\\n    return { isAuthenticated, login, logout }\\n})\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Here \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"useUserSession\"},{\"type\":\"text\",\"text\":\" is the composible from \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"nuxt-auth-utils\"},{\"type\":\"text\",\"text\":\", which gives all the session user info like user, loggedIn or not, clear for logout, fetch.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"fetch: fetchSession\"},{\"type\":\"text\",\"text\":\"  will force the client to sync the server changes after login.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"\u002Fapi\u002Fauth\u002Flogin\"},{\"type\":\"text\",\"text\":\" will hit the Nitro server endpoint for login. \"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Authentication Middleware\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"The main function of the middleware is to protect specific pages from viewing by authenticated users.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"If someone tries to access a page that uses this middleware, it checks if the user is login user or not. If they aren’t logged in, it will force them to the login page.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Create the middleware file under \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"\u002Fapp\u002Fmiddleware\u002Fadmin.ts\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"ts\"},\"content\":[{\"type\":\"text\",\"text\":\"export default defineNuxtRouteMiddleware(() => {\\n\\n    const auth = useAuthStore()\\n    if (!auth.isAuthenticated) {\\n        return navigateTo('\u002Flogin')\\n    }\\n\\n})\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Use this middleware for auth pages.\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"ts\"},\"content\":[{\"type\":\"text\",\"text\":\"definePageMeta({\\n  layout: 'admin',\\n  middleware: 'admin'\\n})\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":2},\"content\":[{\"type\":\"text\",\"text\":\"Nitro Authentication Handler \"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Centralized Backend API Utility\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Let's first create the centralized utility class \"},{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"\u002Fserver\u002Futils\u002Fapi.ts\"},{\"type\":\"text\",\"text\":\" where we are going to inject the login auth-token and other security headers. Creating a centralized backend utitly have benifits that if some changes are required, we don't have to make changes in all the nitro api endpoint. \"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"ts\"},\"content\":[{\"type\":\"text\",\"text\":\"import type { H3Event } from 'h3'\\nimport type { NitroFetchOptions, NitroFetchRequest } from 'nitropack'\\n\\nexport const api = async \u003CT = any>(\\n    event: H3Event,\\n    path: NitroFetchRequest,\\n    options: NitroFetchOptions\u003CNitroFetchRequest> = {}\\n): Promise\u003CT> => {\\n    const config = useRuntimeConfig()\\n    const session = await getUserSession(event)\\n\\n    \u002F\u002F Inject headers directly into the incoming options object before running $fetch\\n    const headers = Array.isArray(options.headers)\\n        ? Object.fromEntries(options.headers)\\n        : { ...options.headers }\\n\\n    headers['X-Forwarded-For-Nitro'] = 'true'\\n\\n    if (session.secure?.token) {\\n        headers['Authorization'] = `Bearer ${session.secure.token}`\\n    }\\n\\n    \u002F\u002F Execute using the global single-instance $fetch\\n    return $fetch\u003CT>(path, {\\n        baseURL: config.baseUrl,\\n        ...options,\\n        headers\\n    })\\n}\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"X-Forwarded-For-Nitro\"},{\"type\":\"text\",\"text\":\" is a Nitro security header server-to-server validation fingerprint that is sent to the backend server to verify the request is from the Nitro server.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"Bearer ${session.secure.token}\"},{\"type\":\"text\",\"text\":\"  this is where we are injecting our login token to send to the backend server.\"}]},{\"type\":\"heading\",\"attrs\":{\"textAlign\":null,\"level\":3},\"content\":[{\"type\":\"text\",\"text\":\"Nitro login endpoint\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"Let's create our  api endpoint for login in the Nitro server. \"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"ts\"},\"content\":[{\"type\":\"text\",\"text\":\"export default defineEventHandler(async (event) => {\\n    const body = await readBody(event)\\n    const config = useRuntimeConfig()\\n\\n    try {\\n        const accessToken = await api(event,'\u002Fapi\u002Fauth\u002Flogin', {\\n            baseURL: config.baseUrl,\\n            method: 'POST',\\n            body\\n        })\\n\\n        await setUserSession(event, {\\n            secure: {\\n                token: accessToken \u002F\u002F This stays server-side and will NEVER be sent to the browser\\n            },\\n            user: {\\n                authenticatedAt: new Date().toISOString()\\n            }\\n        })\\n\\n        return { success: true }\\n    } catch (error: any) {\\n        throw createError({\\n            status: error.response?.status || 401,\\n            statusText: 'Invalid credentials'\\n        })\\n    }\\n})\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"marks\":[{\"type\":\"code\"}],\"text\":\"setUserSession\"},{\"type\":\"text\",\"text\":\"  we are injecting the user session using setUserSession. \"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"We are calling the centralized fetch client utility class:\"}]},{\"type\":\"codeBlock\",\"attrs\":{\"language\":\"ts\"},\"content\":[{\"type\":\"text\",\"text\":\"const accessToken = await api(event,'\u002Fapi\u002Fauth\u002Flogin', {\\n            baseURL: config.baseUrl,\\n            method: 'POST',\\n            body\\n        })\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"This will hit the request to the backend, get the JWT token, and set to the user session.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"For your endpoint that required login or Nitro Server security header, you need to call the centralized api utility class as above.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null},\"content\":[{\"type\":\"text\",\"text\":\"This is how we can set up the secure system for the Nuxt Application. Here, we didn't expose our token to the browser to make it more secure. If you want to add a different Oauth Provider, reference this \"},{\"type\":\"text\",\"marks\":[{\"type\":\"link\",\"attrs\":{\"href\":\"https:\u002F\u002Fnuxt.com\u002Fmodules\u002Fauth-utils\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer nofollow\",\"class\":null,\"title\":null}}],\"text\":\"nuxt-auth-utils.\"}]},{\"type\":\"paragraph\",\"attrs\":{\"textAlign\":null}}]}","\u002Fuploads\u002Fthumbnails\u002F6088642b-8dcb-4d13-bb68-f90084ddbe04_nuxt_ssr_logi.jpeg",[11,12,13,14,15,16,17],"nuxt","nuxt 4","auth","ssr","nitro-server","vuejs","authentication",[19],"NuxtJS",[11],"2026-05-18T14:36:54.441Z",[23,30,36,42,48],{"alias":24,"title":25,"description":26,"thumbnail":27,"createdAt":28,"tutorialAlias":29,"lessonAlias":29},"static-assets-vs-dynamic-routing-collision","Static Assets vs. Dynamic Routing Collision","Resolving the Static Assets vs. Dynamic Routing Collision","\u002Fuploads\u002Fthumbnails\u002F0f4d63d1-8ca4-472f-8f6d-9bd6919a88b9_nuxt_collisio.jpeg","2026-05-16T08:36:46.316Z",null,{"alias":31,"title":32,"description":33,"thumbnail":34,"createdAt":35,"tutorialAlias":29,"lessonAlias":29},"environment-variables-in-nuxt","The Definitive Guide to Environment Variables in Nuxt 4","How to create Environment Variables in Nuxt 4","https:\u002F\u002Fapi.csbyte.com\u002Fuploads\u002Feditor\u002Fe8a3c4e7-98a6-4114-a8c8-49ebb4a9522f_nuxt_env_cloudflare.png","2026-05-04T12:35:52.854Z",{"alias":37,"title":38,"description":39,"thumbnail":40,"createdAt":41,"tutorialAlias":29,"lessonAlias":29},"configure-nginx-as-reverse-proxy-in-nuxt","Configure Nginx as a reverse proxy in Nuxt application","Deploy and set up the nginx in Nuxt application","\u002Fuploads\u002Fthumbnails\u002F23c9fd84-6a39-40f1-876f-ba81011ccf06_nginx_nux.jpeg","2026-05-03T10:00:48.702Z",{"alias":43,"title":44,"description":45,"thumbnail":46,"createdAt":47,"tutorialAlias":29,"lessonAlias":29},"how-to-deploy-nuxt-app-in-ubuntu-server","How to deploy Nuxt app in Ubuntu Server","Deploy Nuxt App in Linux VM","https:\u002F\u002Fapi.csbyte.com\u002Fuploads\u002Feditor\u002F808571e8-1ce9-4e1b-901f-7afd81f4c7df_pm2.png","2026-05-02T08:11:55.437Z",{"alias":49,"title":50,"description":51,"thumbnail":52,"createdAt":53,"tutorialAlias":29,"lessonAlias":29},"how-to-deploy-our-nuxt-application-to-cloudflare","How to deploy our nuxt application to cloudflare","Deploy our Nuxt application to Cloudflare using Wrangler","https:\u002F\u002Fapi.csbyte.com\u002Fuploads\u002Feditor\u002F19c8ef54-4006-4bfa-a07d-b2dd5e401c22_nuxt_deploy.png","2026-05-02T02:23:45.510Z"]