<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Elif Nur Turk</title>
    <description>The latest articles on DEV Community by Elif Nur Turk (@elifnurturk).</description>
    <link>https://dev.to/elifnurturk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1917690%2F3fa34dd6-ff78-4e97-8b0d-dc572a75488e.JPG</url>
      <title>DEV Community: Elif Nur Turk</title>
      <link>https://dev.to/elifnurturk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/elifnurturk"/>
    <language>en</language>
    <item>
      <title>Custom Toasters in Nuxt with Vue Toastification</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Mon, 04 Nov 2024 09:44:35 +0000</pubDate>
      <link>https://dev.to/elifnurturk/custom-toasters-in-nuxt-with-vue-toastification-10ai</link>
      <guid>https://dev.to/elifnurturk/custom-toasters-in-nuxt-with-vue-toastification-10ai</guid>
      <description>&lt;h2&gt;
  
  
  Custom Toasters in Nuxt with Vue Toastification
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Customizing Vue Toastification in Nuxt 3
&lt;/h2&gt;

&lt;p&gt;In this article, we’ll explore how to integrate and customize Vue Toastification in a Nuxt 3 application. We’ll create a reusable toaster plugin and demonstrate how to trigger different types of toast notifications from your components.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcfjgracq8k7r6fcre9c1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcfjgracq8k7r6fcre9c1.png" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Setting Up Vue Toastification
&lt;/h3&gt;

&lt;p&gt;First, ensure you have installed the Vue Toastification library in your Nuxt 3 project. You can do this using npm or yarn:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install @meforma/vue-toaster&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add @meforma/vue-toaster&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Creating the Toaster Plugin
&lt;/h3&gt;

&lt;p&gt;Next, we’ll create a plugin that initializes the toaster with custom settings. Create a new file in the plugins directory (e.g., toast.client.ts):&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/plugins/toast.client.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createToaster } from '@meforma/vue-toaster'
    import { defineNuxtPlugin } from '#app'

    export default defineNuxtPlugin((nuxtApp) =&amp;gt; {
      const toaster = createToaster({
        position: 'bottom-left',
        maxToasts: 5, // Display at most 5 toasts at a time
      })
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! You’ve set up the basic integration for &lt;strong&gt;Vue Toastification&lt;/strong&gt; in your Nuxt 3 project. Now, let’s dive into how you can &lt;strong&gt;customize&lt;/strong&gt; the toaster to fit your specific needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Areas of Customization
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Positioning&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Types and Styles&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Duration&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  1. Positioning
&lt;/h3&gt;

&lt;p&gt;You’ve already set the default position to bottom-left. However, Vue Toastification offers multiple predefined positions. You can easily change this by passing a different value to the position option.&lt;/p&gt;

&lt;p&gt;Available positions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;top-right&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;top-left&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bottom-right&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;bottom-left&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;const toaster = createToaster({&lt;br&gt;
      position: 'bottom-left', // Change the position here&lt;br&gt;
    });&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Types, Styles, Durations
&lt;/h3&gt;

&lt;p&gt;You can customize the appearance of the toasts based on the type of message (e.g., success, error, warning). You can pass custom classes to modify the toast’s look:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/plugins/toast.client.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   import { createToaster } from '@meforma/vue-toaster'
    import { defineNuxtPlugin } from '#app'

    export default defineNuxtPlugin((nuxtApp) =&amp;gt; {
      const toaster = createToaster({
        position: 'bottom-left',
      })

      // Define custom toast functions
      const successToast = (message: string) =&amp;gt; {
        toaster.show(message, {
          type: 'success',
          duration: 3000, 
          className: 'bg-green-500 text-white p-4 rounded shadow-md w-[300px] my-2',
        })
      }

      const failToast = (message: string) =&amp;gt; {
        toaster.show(message, {
          type: 'error',
          duration: 3000,
          className: 'bg-red-500 text-white p-4 rounded shadow-md w-[300px] my-2',
        })
      }

      const warnToast = (message: string) =&amp;gt; {
        toaster.show(message, {
          type: 'warning',
          duration: 3000,
          className: 'bg-yellow-500 text-white p-4 rounded shadow-md w-[300px] my-2',
        })
      }

      // Provide the toasts globally with types
      nuxtApp.provide('successToast', successToast)
      nuxtApp.provide('failToast', failToast)
      nuxtApp.provide('warnToast', warnToast)
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage in a Page
&lt;/h2&gt;

&lt;p&gt;To display toast notifications with button actions, you can set up buttons to trigger success, error, and warning toasts. Here’s the code:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/pages/toast.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   &amp;lt;template&amp;gt;
      &amp;lt;div class="flex justify-center space-x-4 h-10"&amp;gt;
        &amp;lt;button @click="$successToast('Operation was successful!')" class="bg-primary text-white px-4"&amp;gt;Success&amp;lt;/button&amp;gt;
        &amp;lt;button @click="$failToast('Something went wrong!')" class="bg-red-800 text-white px-4"&amp;gt;Fail&amp;lt;/button&amp;gt;
        &amp;lt;button @click="$warnToast('This is a warning!')" class="bg-orange-400 text-white px-4"&amp;gt;Warn&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;

    &amp;lt;script setup&amp;gt;
    const { $successToast, $failToast, $warnToast } = useNuxtApp();
    &amp;lt;/script&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pkbj6fe2bh26vnhi7z9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5pkbj6fe2bh26vnhi7z9.png" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For more customization,&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/pages/toast.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import { createToaster } from '@meforma/vue-toaster'
    import { defineNuxtPlugin } from '#app'
    import successImg from '@/assets/images/success.svg'

    export default defineNuxtPlugin((nuxtApp) =&amp;gt; {
      const toaster = createToaster({
        position: 'bottom-left',
        maxToasts: 5, 
      })

      // toast with icon
      const successToast = (message: string) =&amp;gt; {
        toaster.show(`
          &amp;lt;div class="flex items-center"&amp;gt;
            &amp;lt;img src="${successImg}" alt="success" class="w-5 h-5 mr-2" /&amp;gt;
            ${message}
          &amp;lt;/div&amp;gt;
        `, {
          type: 'success',
          pauseOnHover: true, 
          duration: 3000, 
          className: 'bg-white text-xs text-gray-800 p-4 rounded shadow-md w-[300px] my-2 rounded-lg shadow-white shadow-lg',
        })
      }

      nuxtApp.provide('successToast', successToast)

    })

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsac3dn25opisr7yenw3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsac3dn25opisr7yenw3v.png" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Toast notifications in Nuxt 3 provide quick, effective feedback for users. With minimal setup, you can customize and trigger success, error, or warning messages across your app. This simple integration enhances user experience and keeps interactions smooth and informative.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;See you in next article!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@meforma/vue-toaster" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@meforma/vue-toaster&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vue</category>
      <category>nuxt</category>
      <category>toast</category>
    </item>
    <item>
      <title>Google reCAPTCHA for Vue.js/Nuxt.js : App &amp; Form Spam Shield</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Thu, 17 Oct 2024 09:37:26 +0000</pubDate>
      <link>https://dev.to/elifnurturk/google-recaptcha-for-vuejsnuxtjs-app-form-spam-shield-1nkd</link>
      <guid>https://dev.to/elifnurturk/google-recaptcha-for-vuejsnuxtjs-app-form-spam-shield-1nkd</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;The Importance of reCAPTCHA in Modern Applications&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the digital age, safeguarding applications from bots and automated attacks is more critical than ever. &lt;strong&gt;Google’s reCAPTCHA&lt;/strong&gt; provides a robust solution by verifying user authenticity, effectively preventing spam and protecting against brute force login attempts.&lt;/p&gt;

&lt;p&gt;Modern reCAPTCHA versions are also much more user-friendly. Unlike older captchas that made users decipher distorted text, newer versions work silently in the background, allowing smoother user interactions while still providing strong protection.&lt;/p&gt;

&lt;p&gt;To integrate reCAPTCHA, you need two keys: a &lt;strong&gt;site key&lt;/strong&gt; and a &lt;strong&gt;secret key&lt;/strong&gt;. The site key is used on the front end to display the reCAPTCHA widget, while the secret key is required on the backend to validate the token generated on frontend after user interaction.&lt;/p&gt;

&lt;p&gt;When a user submits a form, a token will be created and sent to your backend endpoint, which communicates with Google’s API to verify the token. If the token is valid, the backend returns a confirmation (e.g., “OK”). We’ll handle only the frontend operations using the existing backend API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;vue-recaptcha-v3&lt;/em&gt;&lt;/strong&gt; is a Vue library that facilitates the integration of Google’s reCAPTCHA v3 into Vue.js applications. It enhances security by running in the background to score user interactions, effectively distinguishing between humans and bots without disrupting the user experience.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe807jogta89vsr2kmghz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe807jogta89vsr2kmghz.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing vue-recaptcha-v3 in Your Vue.js Application
&lt;/h2&gt;

&lt;p&gt;Integrating &lt;strong&gt;vue-recaptcha-v3&lt;/strong&gt; into your Vue.js application involves a few straightforward steps. Here’s a guide to help you set it up, with a special focus on &lt;strong&gt;Nuxt.js&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install the Library
&lt;/h3&gt;

&lt;p&gt;First, you need to install the &lt;strong&gt;vue-recaptcha-v3&lt;/strong&gt; package. Run one of the following commands in your project directory:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install vue-recaptcha-v3&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;yarn add vue-recaptcha-v3&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Obtain reCAPTCHA API Keys
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.google.com/recaptcha/admin/create" rel="noopener noreferrer"&gt;Click&lt;/a&gt; and visit the &lt;a href="https://www.google.com/recaptcha/admin/create" rel="noopener noreferrer"&gt;Google reCAPTCHA admin console&lt;/a&gt; to register your site. You’ll receive two keys: &lt;strong&gt;Site Key&lt;/strong&gt; &amp;amp; &lt;strong&gt;Secret Key&lt;/strong&gt;. Make sure to choose reCAPTCHA v3 during registration. We will be using Site Key in the front-end.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Create a Plugin
&lt;/h3&gt;

&lt;p&gt;Next, create a new plugin file for reCAPTCHA. You can do this by creating a vue-recaptcha-v3.js file in the plugins directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*plugins/vue-recaptcha-v3.js*

    import { defineNuxtPlugin } from '#app'; 
    import { VueReCaptcha } from 'vue-recaptcha-v3';

    export default defineNuxtPlugin((nuxtApp) =&amp;gt; {
      nuxtApp.vueApp.use(VueReCaptcha, {
        siteKey: 'YOUR_SITE_KEY', // Replace with your site key
        loaderOptions: {
          autoHideBadge: true, // Optional: Automatically hides the badge
          explicitRenderParameters: {
              //badge: 'bottomleft', //incase you don't want to hide it
          }
        }
    });
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Badge Appearance&lt;/strong&gt;&lt;br&gt;
 &lt;em&gt;The reCAPTCHA badge is visible by default on all pages, but you can customize its behavior. For instance, you can choose to hide it by enabling the autoHideBadge option.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Customizing Badge Location&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can specify the position of the reCAPTCHA badge by using the loaderOptions when configuring &lt;strong&gt;vue-recaptcha-v3&lt;/strong&gt;. Here are the available badge positions:&lt;br&gt;
 &lt;strong&gt;inline&lt;/strong&gt;: The badge is shown inline (no fixed position).&lt;br&gt;
 &lt;strong&gt;bottomright&lt;/strong&gt;: The badge appears in the bottom-right corner of the page.&lt;br&gt;
 &lt;strong&gt;bottomleft&lt;/strong&gt;: The badge appears in the bottom-left corner of the page.&lt;br&gt;
 &lt;strong&gt;topright&lt;/strong&gt;: The badge appears in the top-right corner of the page.&lt;br&gt;
 &lt;strong&gt;topleft&lt;/strong&gt;: The badge appears in the top-left corner of the page.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 4: Register the Plugin
&lt;/h3&gt;

&lt;p&gt;Add the plugin to the plugins array in your nuxt.config.js. Here’s an example configuration,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    export default defineNuxtConfig({
      devtools: { enabled: true },
       //..

        plugins:[
            {src: '~/plugins/vue-recaptcha-v3.js', mode: 'client' },
        ],

      ..//

    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can apply it in form…&lt;/p&gt;

&lt;p&gt;Let’s break down the implementation of reCAPTCHA in your &lt;strong&gt;ContactForm&lt;/strong&gt; component step by step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Setup and Import
&lt;/h3&gt;

&lt;p&gt;First, we import the necessary modules from &lt;strong&gt;vue-recaptcha-v3&lt;/strong&gt; and define our component:&lt;/p&gt;

&lt;p&gt;/ContactForm.vue&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;script&amp;gt;
    import { VueReCaptcha, useReCaptcha } from "vue-recaptcha-v3";

    export default {
      name: "ContactForm",
      data() {
        return {
          form: {
            name: "",
          },
          submissionMessage: null,
          errorMessage: null,
        };
      },
      setup() {
        const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();

        const recaptcha = async () =&amp;gt; {
          await recaptchaLoaded(); // Wait for reCAPTCHA to load
          return await executeRecaptcha("contact"); // Create a reCAPTCHA token
        };
        return {
          recaptcha,
        };
      },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The component imports VueReCaptcha and the useReCaptcha hook to manage reCAPTCHA.&lt;br&gt;
 The form object contains the user's input fields, while submissionMessage and errorMessage are used to display feedback.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 2: Token Creation
&lt;/h3&gt;

&lt;p&gt;Next, we define the submitForm method to handle form submissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   methods: {
        async submitForm() {
          const token = await this.recaptcha(); // Call the recaptcha method to get the token
          console.log(token);

          // Check if the token is valid
          if (!token) {
            this.errorMessage = "Invalid reCAPTCHA. Please try again.";
            this.submissionMessage = null; // Clear previous messages
            alert(this.errorMessage);
            return; // Exit if the token is invalid
          }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The recaptcha method is called to generate a token, which is logged to the console.&lt;br&gt;
 If the token is not generated (invalid), an error message is displayed, and the function exits early.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 3: CAPTCHA Validation
&lt;/h3&gt;

&lt;p&gt;Once a valid token is created, the next step is to validate it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    try {
            // Send the token to the CAPTCHA validation API first
            const captchaResponse = await fetch(
              "https://api.x.com/api/captcha",
              {
                method: "POST",
                headers: {
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({ recaptcha_token: token }),
              }
            );

            // If the CAPTCHA validation is successful (status 200), submit the form
            if (captchaResponse.ok) {
              console.log("response is ok");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The token is sent to your backend CAPTCHA validation endpoint using a POST request.&lt;br&gt;
 If the response is OK (status 200), it proceeds to prepare the form submission.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 4: Form Submission
&lt;/h3&gt;

&lt;p&gt;If the CAPTCHA validation passes, the form data is sent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      const formData = new FormData();
              formData.append("name", this.form.name);
              formData.append("recaptchaToken", token);

              const formSubmitResponse = await fetch(
                "https://api.x.com/api/contact",
                {
                  method: "POST",
                  body: formData,
                }
              );

              // Check if the form submission response is okay (status 200-299)
              if (formSubmitResponse.ok) {
                const result = await formSubmitResponse.json();
                this.submissionMessage = "Contact form submitted successfully!";
                alert(this.submissionMessage); // Show success alert
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A FormData object is created to hold the form inputs, including the reCAPTCHA token. The form data is sent to your form submission endpoint. If the submission is successful, a success message is displayed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 5: Error Handling
&lt;/h3&gt;

&lt;p&gt;If either the CAPTCHA validation or form submission fails, appropriate error messages are shown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    } else {
                const error = await formSubmitResponse.json();
                this.errorMessage = error.message || "Error submitting form.";
                alert(this.errorMessage);
                this.submissionMessage = null; // Clear previous messages
              }
            } else {
              this.errorMessage = "CAPTCHA validation failed. Please try again.";
              alert(this.errorMessage);
              this.submissionMessage = null;
            }
          } catch (error) {
            console.error("Submission error:", error);
            this.errorMessage = "An error occurred while submitting the form.";
            this.submissionMessage = null; // Clear previous messages
            alert(this.errorMessage); // Show error alert
          }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;: If there are issues with the CAPTCHA validation or form submission, the error messages are displayed, allowing users to understand what went wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 6: Resetting the Form
&lt;/h3&gt;

&lt;p&gt;Finally, the form can be reset after submission:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;resetForm() {&lt;br&gt;
          this.form.name = "";&lt;br&gt;
        },&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Here’s the complete code for the &lt;strong&gt;ContactForm&lt;/strong&gt; component, integrating reCAPTCHA for secure form submissions:&lt;/p&gt;

&lt;p&gt;/ContactForm.vue&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;script&amp;gt;
    import { VueReCaptcha, useReCaptcha } from "vue-recaptcha-v3";

    export default {
      name: "ContactForm",
      data() {
        return {
          form: {
            name: "",
          },
          submissionMessage: null,
          errorMessage: null,
        };
      },
      setup() {
        const { executeRecaptcha, recaptchaLoaded } = useReCaptcha();

        const recaptcha = async () =&amp;gt; {
          await recaptchaLoaded(); // Wait for reCAPTCHA to load
          return await executeRecaptcha("contact"); // Create a reCAPTCHA token
        };
        return {
          recaptcha,
        };
      },

      methods: {
        async submitForm() {
          const token = await this.recaptcha(); // Call the recaptcha method to get the token
          console.log(token);

          // Check if the token is valid
          if (!token) {
            this.errorMessage = "Invalid reCAPTCHA. Please try again.";
            this.submissionMessage = null; // Clear previous messages
            alert(this.errorMessage);
            return;
          }

          try {
            // Send the token to the CAPTCHA validation API first
            const captchaResponse = await fetch(
              "https://api.x.com/api/captcha",
              {
                method: "POST",
                headers: {
                  "Content-Type": "application/json",
                },
                body: JSON.stringify({ recaptcha_token: token }),
              }
            );

            // If the CAPTCHA validation is successful (status 200), submit the form
            if (captchaResponse.ok) {
              console.log("response is ok");

              // Prepare form data for submission
              const formData = new FormData();
              formData.append("name", this.form.name);
              formData.append("recaptchaToken", token); // Append the reCAPTCHA token

              // Submit the form data
              const formSubmitResponse = await fetch(
                "https://api.x./api/contact",
                {
                  method: "POST",
                  body: formData,
                }
              );

              // Check if the form submission response is okay (status 200-299)
              if (formSubmitResponse.ok) {
                const result = await formSubmitResponse.json();
                this.submissionMessage = "Contact form submitted successfully!";
                this.errorMessage = null; // Clear previous error messages
                alert(this.submissionMessage); // Show success alert
              } else {
                // Handle errors from the form submission server
                const error = await formSubmitResponse.json();
                this.errorMessage = error.message || "Error submitting form.";
                alert(this.errorMessage);
                this.submissionMessage = null; // Clear previous messages
              }
            } else {
              // Handle CAPTCHA validation error
              this.errorMessage = "CAPTCHA validation failed. Please try again.";
              alert(this.errorMessage);
              this.submissionMessage = null;
            }
          } catch (error) {
            console.error("Submission error:", error);
            this.errorMessage = "An error occurred while submitting the form.";
            this.submissionMessage = null; // Clear previous messages
            alert(this.errorMessage); // Show error alert
          }
        },
        resetForm() {
          this.form.name = "";
        },
      },

     beforeUnmount() {
      this.$recaptcha.destroy();
      },
    };

    &amp;lt;/script&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;" Please note that reCAPTCHA may not function correctly on localhost. It's recommended to test it in a deployed environment. "&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By implementing this step-by-step guide, you’ve successfully integrated reCAPTCHA into your form component. This not only enhances the security of your form submissions but also ensures a smooth and transparent user experience.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;em&gt;“Let’s hope the bots can’t outsmart this reCAPTCHA — if they do, I’ll need to write a new article to fool them! Until then, stay secure.”&lt;/em&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;See you in next article!&lt;/p&gt;

&lt;p&gt;Elif Nur Türk&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://developers.google.com/recaptcha/intro" rel="noopener noreferrer"&gt;https://developers.google.com/recaptcha/intro&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://dev.to/elquimeras/integrate-recaptcha-v3-on-nuxt3-app-1gma"&gt;https://dev.to/elquimeras/integrate-recaptcha-v3-on-nuxt3-app-1gma&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nuxt.com/docs/migration/plugins-and-middleware" rel="noopener noreferrer"&gt;https://nuxt.com/docs/migration/plugins-and-middleware&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>recaptcha</category>
      <category>webdev</category>
      <category>vue</category>
      <category>security</category>
    </item>
    <item>
      <title>Simple Authentication for Nuxt.js (JSON Web Token + Local Storage)</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Mon, 30 Sep 2024 09:26:15 +0000</pubDate>
      <link>https://dev.to/elifnurturk/basic-authentication-for-nuxtjs-json-web-token-local-storage-899</link>
      <guid>https://dev.to/elifnurturk/basic-authentication-for-nuxtjs-json-web-token-local-storage-899</guid>
      <description>&lt;h2&gt;
  
  
  Basic Authentication for Nuxt.js (JSON Web Token + Local Storage)
&lt;/h2&gt;

&lt;p&gt;When developing a web application, ensuring security is essential. In this guide, we’ll explore how to set up a secure authentication flow using Prisma ORM and JSON Web Tokens (JWT) in NUXT 3 projects...&lt;/p&gt;

&lt;p&gt;We'll implement a login mechanism that verifies user credentials and generates a JWT token. This token will be saved in localStorage, allowing the user to stay logged in across sessions. There will be two layouts in our application: a login layout for users who are not authenticated and a default layout for authenticated users.&lt;/p&gt;

&lt;p&gt;Middleware will check for the presence of a valid token in localStorage on each request, ensuring users without a token are redirected to the login page. Logging out will be straightforward simply clearing the token from localStorage will log the user out and redirect them to the login page.&lt;/p&gt;

&lt;p&gt;By following this approach, you’ll implement a basic bearer authentication system in your web application with server &amp;amp; client side guide. If you already have an API endpoint that provides a token upon successful login, you can skip the server-side setup and focus directly on the front-end operations.&lt;/p&gt;

&lt;p&gt;Let’s start!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvbu3u3e6z81ch3dazga3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvbu3u3e6z81ch3dazga3.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Server-Side setups&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Assuming you’ve already set up Prisma and connected your database (or with any ORM tool), it’s time to refine your user model,&lt;/p&gt;

&lt;p&gt;&lt;code&gt;model Users {&lt;br&gt;
      Id        Int      @id @default(autoincrement())&lt;br&gt;
      Username  String   @unique&lt;br&gt;
      Password  String&lt;br&gt;
      CreatedAt DateTime @default(now())&lt;br&gt;
    }&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
run the necessary migrations, create an user. The folder architecture will be like;&lt;br&gt;
&lt;code&gt;&lt;br&gt;
    | components/&lt;br&gt;
    | layouts/&lt;br&gt;
    | middleware/&lt;br&gt;
    | pages/&lt;br&gt;
    | prisma/&lt;br&gt;
    | |- schema.prisma/&lt;br&gt;
    | server/&lt;br&gt;
    | |- api/&lt;br&gt;
    | | |- auth/ &lt;br&gt;
    | | | |- login.post.js&lt;br&gt;
    |- app.vue&lt;br&gt;
    |- nuxt.config.ts&lt;br&gt;
    |- package.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let’s install required packages that “bcrypt” “jsonwebtoken” “jwt-decode”&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install bcrypt jsonwebtoken jwt-decode

or

yarn add bcrypt jsonwebtoken jwt-decode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;You can create your own JWT token with a help of JWT token generator. The content of token is totally up to you.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/server/api/auth/login.post.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    import { PrismaClient } from '@prisma/client';
    import bcrypt from 'bcrypt';
    import jwt from 'jsonwebtoken';

    const prisma = new PrismaClient();
    const JWT_SECRET = 'your_token'; // Replace with your secret key

    export default defineEventHandler(async (event) =&amp;gt; {
      const { username, password } = await readBody(event);

      // Find the user in the database
      const user = await prisma.users.findUnique({
        where: { Username: username }
      });

      if (!user) {
        return { statusCode: 401, body: { success: false, message: 'Invalid username or password' } };
      }

      // Check if the password is correct
      const validPassword = await bcrypt.compare(password, user.Password);

      if (!validPassword) {
        return { statusCode: 401, body: { success: false, message: 'Invalid username or password' } };
      }

      // Create a JWT token
      const token = jwt.sign(
        { id: user.Id, username: user.Username }, 
        JWT_SECRET, 
        { expiresIn: '12h' } // Token expires in 12 hour
      );


      // Return the token to the frontend
      return { 
        statusCode: 200, 
        body: { 
          success: true, 
          message: 'Login successful', 
          token 
        } 
      };
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This handler performs several key tasks: it first extracts the username and password from the request body, then queries the database to locate the user with the specified username. It verifies the provided password against the hashed password stored in the database. Upon successful validation, it generates a JSON Web Token (JWT) with a 48-hour expiration and returns this token to the frontend for subsequent authentication. If the credentials are invalid, it responds with a 401 status code and an appropriate error message.&lt;/p&gt;

&lt;p&gt;Let’s fix &lt;em&gt;nuxt.config.ts&lt;/em&gt; and check the API if it works.&lt;br&gt;
&lt;code&gt;&lt;br&gt;
    export default defineNuxtConfig({&lt;br&gt;
    ...&lt;br&gt;
      server: {&lt;br&gt;
        proxy: {&lt;br&gt;
          '/api': 'http://localhost:3000' // Adjust the port if your backend server is running on a different port&lt;br&gt;
        },&lt;br&gt;
        router: {&lt;br&gt;
          base: '/api' &lt;br&gt;
        },&lt;br&gt;
      },&lt;br&gt;
      router: {&lt;br&gt;
        middleware: ['auth']&lt;br&gt;
      },&lt;br&gt;
    ...&lt;br&gt;
    });&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And the Postman response be like,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2597uzny3zsy5x2z17am.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2597uzny3zsy5x2z17am.png" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It works well!&lt;/p&gt;
&lt;h2&gt;
  
  
  Client-Side Setups:
&lt;/h2&gt;

&lt;p&gt;We can start by revisiting the file structure. With Prisma and server files already set up, the next steps involve defining layouts, forms, pages, and middleware. Let’s begin with setting up the two layout files.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;| components/&lt;br&gt;
    | |- LoginForm.vue&lt;br&gt;
    | layouts/&lt;br&gt;
    | |- default.vue&lt;br&gt;
    | |- login.vue&lt;br&gt;
    | middleware/&lt;br&gt;
    | |- auth.js&lt;br&gt;
    | pages/&lt;br&gt;
    | |- index.vue&lt;br&gt;
    | |- login.vue&lt;br&gt;
    | prisma/&lt;br&gt;
    | server/&lt;br&gt;
    |- app.vue&lt;br&gt;
    |- nuxt.config.ts&lt;br&gt;
    |- package.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/layouts/default.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;template&amp;gt;
      &amp;lt;div v-if="isAuthenticated"&amp;gt;
        &amp;lt;!-- You can add header footer sidebars etc. --&amp;gt; 
        &amp;lt;NuxtPage /&amp;gt;
        &amp;lt;DialogWrapper /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div v-else&amp;gt;
        &amp;lt;p&amp;gt;Loading...&amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;

    &amp;lt;script setup&amp;gt;
    import { ref, onMounted } from "vue";
    import { useRouter } from "vue-router";
    import { DialogWrapper } from "vue3-promise-dialog";

    const router = useRouter();
    const isAuthenticated = ref(null); // Use null to distinguish between loading and not authenticated

    onMounted(() =&amp;gt; {
      const token = localStorage.getItem("authToken");
      if (token) {
        isAuthenticated.value = true;
      } else {
        isAuthenticated.value = false;
        router.push("/login");
      }
    });
    &amp;lt;/script&amp;gt;

*/layouts/login.vue*

You can hide all the side bars, panels, pages, header and footer if user is not authenticated.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;div&amp;gt;
    &amp;lt;NuxtPage /&amp;gt;
    &amp;lt;DialogWrapper /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script setup&amp;gt;
import { useRouter } from "vue-router";
import { DialogWrapper } from "vue3-promise-dialog";
const router = useRouter();
const navigateToRoute = (route) =&amp;gt; {
  router.push(route);
};
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*/app.vue*



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script setup&amp;gt;
import { useRouter } from "vue-router";
import { DialogWrapper } from "vue3-promise-dialog";
const router = useRouter();
const navigateToRoute = (route) =&amp;gt; {
  router.push(route);
};
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*/pages/index.vue*

    &amp;lt;template&amp;gt;
      &amp;lt;section&amp;gt;
        &amp;lt;div class="block"&amp;gt;
          &amp;lt;h1&amp;gt;
            Welcome to your Web App!
          &amp;lt;/h1&amp;gt;
          &amp;lt;button 
             @click="logout"&amp;gt;Logout
          &amp;lt;/button&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/section&amp;gt;
    &amp;lt;/template&amp;gt;
    &amp;lt;script&amp;gt;
    export default {
      methods: {
        logout() {
          // Remove the auth token from localStorage
          localStorage.removeItem("authToken");
          // Redirect the user to the login page
          this.$router.push("/login");
        },
      },
    &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;em&gt;/pages/login.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    &amp;lt;template&amp;gt;
      &amp;lt;section&amp;gt;
        &amp;lt;div &amp;gt;
          &amp;lt;LoginForm /&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/section&amp;gt;
    &amp;lt;/template&amp;gt;
    &amp;lt;script&amp;gt;
    definePageMeta({
      layout: "login",
    });
    export default {};
    &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Page setups are completed! We can now proceed with implementing the login functionality. A crucial step is to extract the token from the login response and store it in local storage. This ensures that the token is available for authenticating future requests.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/components/LoginForm.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    &amp;lt;template&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;form @submit.prevent="signIn"&amp;gt;
            &amp;lt;div&amp;gt;
              &amp;lt;label for="username"&amp;gt;Username&amp;lt;/label
              &amp;gt;
              &amp;lt;input
                type="text"
                id="username"
                v-model="Username"
                required
                class="w-full"
              /&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;div&amp;gt;
              &amp;lt;label for="password"&amp;gt;Password&amp;lt;/label
              &amp;gt;
              &amp;lt;input
                type="password"
                id="password"
                v-model="Password"
                required
                class="w-full"
              /&amp;gt;
            &amp;lt;/div&amp;gt;
            &amp;lt;button
              type="submit"
              class="w-full"
            &amp;gt;
              Sign in
            &amp;lt;/button&amp;gt;
          &amp;lt;/form&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;

    &amp;lt;script&amp;gt;
    export default {
      data() {
        return {
          Username: "",
          Password: "",
        };
      },

      methods: {
        async signIn() {
          try {
            const response = await fetch("/api/auth/login", {
              method: "POST",
              headers: {
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                username: this.Username,
                password: this.Password,
              }),
            });

            const data = await response.json();
            if (data.statusCode === 200) {
              // Set the token in local storage
              localStorage.setItem("authToken", data.token);
              alert("Login is successful");
              this.$router.push("/");
            } else {
              console.log("Login failed:", data.message);
              alert("Username or password is invalid");
            }
          } catch (error) {
            console.error("Error during login:", error);
            alert("Error during login. Please try again.");
          }
        },
      },
    };
    &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time for middleware/auth.js file. Essentially, it ensures that only users with a valid token can access to some pages of the application.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/middleware/auth.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    //middleware/auth.js

    import * as jwtDecode from 'jwt-decode';

    export default defineNuxtRouteMiddleware((to, from) =&amp;gt; {
      const token = localStorage.getItem('authToken');

      if (token) {
        try {
          const decodedToken = jwtDecode(token);
          const currentTime = Date.now() / 1000;

          if (decodedToken.exp &amp;lt; currentTime) {
            localStorage.removeItem('authToken');
            return navigateTo('/login');
          }
        } catch (error) {
          // Handle token decoding error
          localStorage.removeItem('authToken');
          return navigateTo('/login');
        }
      } else if (to.name !== 'login') {
        return navigateTo('/login');
      }
    });

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This middleware function handles JWT authentication by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Retrieving the JWT token from localStorage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decoding and verifying the token’s expiration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If expired, it removes the token and redirects to the login page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If decoding fails, it also removes the token and redirects to the login page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Redirecting unauthenticated users to the login page if no valid token is found.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In essence, it ensures only users with a valid, non-expired token can access protected routes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, it’s important to note that this setup only addresses front-end authentication. If your application has server-side endpoints for managing user sessions or access control, you’ll need to implement additional server-side middleware to handle API safety.&lt;/p&gt;

&lt;p&gt;See you in next article!&lt;/p&gt;

</description>
      <category>authjs</category>
      <category>jwt</category>
      <category>webdev</category>
      <category>nuxt</category>
    </item>
    <item>
      <title>Configuring .env file remotely on your VPS</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Mon, 30 Sep 2024 09:18:29 +0000</pubDate>
      <link>https://dev.to/elifnurturk/configuring-env-file-remotely-on-your-vps-56o1</link>
      <guid>https://dev.to/elifnurturk/configuring-env-file-remotely-on-your-vps-56o1</guid>
      <description>&lt;h2&gt;
  
  
  Configuring .env file remotely on your VPS
&lt;/h2&gt;

&lt;p&gt;The .env file typically holds sensitive information such as API keys, database credentials, and configuration settings. This file should be created and managed securely to ensure your application's proper operation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsm4rbnhndl43omr3x4ay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsm4rbnhndl43omr3x4ay.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Access your VPS and navigate to the directory&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`cd /path/to/your/directory`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s create an .env file in directory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vi .env&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command will generate a .env file in your specified directory.&lt;br&gt;
To edit the file, simply execute the command "i".&lt;/p&gt;

&lt;p&gt;&lt;code&gt;i&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Afterward, you can paste your environment variables directly into the file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qvnkn91lwaetdeq6aq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qvnkn91lwaetdeq6aq1.png" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To save and exit, press Esc and then run the appropriate command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;:wq&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now its saved. You can then rebuild your application and restart the VPS server to apply the changes.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>devops</category>
      <category>webdev</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>How to Connect GitHub Repo to VPS Server</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Mon, 30 Sep 2024 09:17:41 +0000</pubDate>
      <link>https://dev.to/elifnurturk/how-to-connect-github-repo-to-vps-server-4jph</link>
      <guid>https://dev.to/elifnurturk/how-to-connect-github-repo-to-vps-server-4jph</guid>
      <description>&lt;h2&gt;
  
  
  How to Connect GitHub Repo to VPS Server
&lt;/h2&gt;

&lt;p&gt;Connecting your GitHub repository to a Virtual Private Server (VPS) allows you to deploy code, automate deployments, and maintain seamless updates. This article will guide you through the process, assuming you have basic knowledge of Linux, SSH, and Git.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we begin, ensure you have the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Access to your VPS&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A GitHub repository&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Git Installing and configuration&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqxi4miun7l6erz7t6s8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuqxi4miun7l6erz7t6s8.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Access To Your Virtual private server (VPS)
&lt;/h2&gt;

&lt;p&gt;To connect to your VPS, you’ll need to use an SSH (Secure Shell) client. One of the most popular SSH clients for Windows is &lt;strong&gt;PuTTY&lt;/strong&gt;. This tool allows you to securely connect to your server and execute commands remotely. You can use any SSH/Telnet software.&lt;/p&gt;

&lt;p&gt;Open the terminal and enter the domain URL.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9f1kygix0btrnm6yi6p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj9f1kygix0btrnm6yi6p.png" width="602" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s launch the terminal to handle authentication.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvpba9eku0a6uq4a04xr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvpba9eku0a6uq4a04xr.png" width="800" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After successfully verifying your username and password, navigate to the /www/var directory or the designated directory where the code will be installed. Use the appropriate command to access this directory.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd /path/to/your/directory&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, you can proceed to install Git within that directory.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s verify that Git has been installed correctly without any issues.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git --version&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Congratulations, your VPS server is now fully set up!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Get and Install the githup repository
&lt;/h2&gt;

&lt;p&gt;Obtain the repository URL from GitHub to clone it onto your server machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzj063ba59ob7r1bm512.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzj063ba59ob7r1bm512.png" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we can continue the cloning process from where we left off.&lt;br&gt;
&lt;code&gt;&lt;br&gt;
    git clone git@github.com/username/repository.git&lt;br&gt;
    git init&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Do not forget to add .env key incase you use it because it will not be auto installed. &amp;lt; &lt;a href="https://elifnurturk.medium.com/configuring-env-file-remotely-on-your-vps-12b1f599a829" rel="noopener noreferrer"&gt;This article&lt;/a&gt; &amp;gt; may help you.&lt;/p&gt;

&lt;p&gt;If uyou already had a project file in directory but not installed with git you can run this command to connect project source to your github repo,&lt;/p&gt;

&lt;p&gt;You can replace “main” with your own branch name&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`git remote add origin https://github.com/your-username/your-repository.git
git pull origin main `
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once the repository is cloned, navigate to the project directory and proceed with the initial build. Depending on your project’s setup, you may use one of the following commands to install dependencies, build and start the application.&lt;/p&gt;

&lt;p&gt;Once you have cloned a repository, you can use git pull to retrieve and merge any new changes from the remote repository into your local copy directory.&lt;/p&gt;

&lt;p&gt;You can replace “main” with your own branch name&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`git pull origin main`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Remember to rebuild your application and restart the VPS server every time you pull new changes from the repository. This ensures that your updates are applied correctly and your application is running the latest version.&lt;/p&gt;

&lt;p&gt;By following these practices, you’ll maintain a robust and efficient development workflow, keeping your application up-to-date and running smoothly on your VPS.&lt;/p&gt;

&lt;p&gt;Thank you for following along, and happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devops</category>
      <category>linux</category>
      <category>ubuntu</category>
    </item>
    <item>
      <title>Json Lottie Animations &amp; Custom Error Pages in Nuxt</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Sat, 28 Sep 2024 12:14:22 +0000</pubDate>
      <link>https://dev.to/elifnurturk/json-lottie-animations-custom-error-pages-in-nuxt-472n</link>
      <guid>https://dev.to/elifnurturk/json-lottie-animations-custom-error-pages-in-nuxt-472n</guid>
      <description>&lt;h2&gt;
  
  
  Json Lottie Animations &amp;amp; Custom Error Pages in Nuxt
&lt;/h2&gt;

&lt;p&gt;We’re going to take our 404 Not Found CSE error page to the next level with Lottie animations. Here’s how you can do it, step by step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47v18fehlqazfvdmlv2f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47v18fehlqazfvdmlv2f.gif" width="600" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Lottie?
&lt;/h3&gt;

&lt;p&gt;Lottie animations are lightweight and scalable, making them ideal for web use. These animations can include complex vector graphics and are highly efficient in terms of performance compared to traditional image or GIF animations. Lottie files are also interactive and customizable, making them a powerful tool for web designers and developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Lottie Animations in Vue Nuxt Projects with vue3-lottie
&lt;/h3&gt;

&lt;p&gt;Integrating Lottie animations into Vue and Nuxt projects is straightforward with the help of the vue3-lottie library. This library provides a simple and efficient way to render Lottie animations in Vue 3 applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Guide to Using Lottie Animations in Vue/Nuxt Projects
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installing vue3-lottie
&lt;/h3&gt;

&lt;p&gt;Let’s install the vue3-lottie package to our exist project.&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install vue3-lottie@latest
yarn add vue3-lottie@latest
pnpm add vue3-lottie@latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;`&lt;/p&gt;
&lt;h3&gt;
  
  
  Importing vue3-lottie
&lt;/h3&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create a folder called plugins at the root of your project and rifght after create a file named Vue3Lottie.client.ts inside the plugins directory.&lt;/p&gt;

&lt;p&gt;Also let’s add our &lt;em&gt;error.json&lt;/em&gt; animated lottie to our assetsfolder under the animations folder.&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| assets/
| |- animations/
| | |- error.json
| pages/
| |- index.js
| plugins/
| |- Vue3Lottie.client.ts
|- app.vue
|- error.vue
|- nuxt.config.ts
|- package.json
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Add the following code to the file.&lt;/p&gt;

&lt;p&gt;./plugins/Vue3Lottie.client.ts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    import { Vue3Lottie } from 'vue3-lottie'
    export default defineNuxtPlugin((nuxtApp) =&amp;gt; {  
    nuxtApp.vueApp.component('Vue3Lottie', Vue3Lottie)})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s use the our animation in our error.vue page!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;error.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;template&amp;gt;
      &amp;lt;div class="text-center"&amp;gt;
        &amp;lt;h1 class="text-6xl"&amp;gt;404&amp;lt;/h1&amp;gt;
        &amp;lt;h2 &amp;gt;Page Not Found&amp;lt;/h2&amp;gt;
        &amp;lt;ClientOnly&amp;gt;
          &amp;lt;Vue3Lottie :animation-data="animation" :height="height" :width="width" /&amp;gt;
        &amp;lt;/ClientOnly&amp;gt;
        &amp;lt;button @click="redirect" class="text-3xl"&amp;gt;Back to menu&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;

    &amp;lt;script &amp;gt;
    import { Vue3Lottie } from "vue3-lottie";
    import NotFound from "/assets/animations/error.json";

    export default {
      components: { Vue3Lottie },
      data() {
        return {
          animation: NotFound,
          height: 500,
          width: 1300,
        };
      },
      methods: {
        redirect() {
          window.location.href = "/";
        },
        error() {
          return useError();
        },
      },
    };
    &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the output be like,&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47v18fehlqazfvdmlv2f.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47v18fehlqazfvdmlv2f.gif" width="600" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Let your creative mind to explore new possibilities!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;See you in the next article!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vue3-lottie.vercel.app/introduction/nuxt-3" rel="noopener noreferrer"&gt;https://vue3-lottie.vercel.app/introduction/nuxt-3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>404</category>
      <category>nuxt</category>
      <category>vue</category>
      <category>lottie</category>
    </item>
    <item>
      <title>Exploring Server-Side Rendering and Database Operations in Nuxt.js with Prisma ORM</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Fri, 27 Sep 2024 11:45:57 +0000</pubDate>
      <link>https://dev.to/elifnurturk/exploring-server-side-rendering-and-database-operations-in-nuxtjs-with-prisma-orm-4021</link>
      <guid>https://dev.to/elifnurturk/exploring-server-side-rendering-and-database-operations-in-nuxtjs-with-prisma-orm-4021</guid>
      <description>&lt;h2&gt;
  
  
  Exploring Server-Side Rendering and Database Operations in Nuxt.js with Prisma ORM
&lt;/h2&gt;

&lt;p&gt;Nuxt.js, a powerful Vue.js framework and with the release of Nuxt 3, the framework has doubled down on its commitment to server-side rendering (SSR).&lt;/p&gt;

&lt;p&gt;In this article, we’ll delve into the world of server-side coding with Nuxt 3. We’ll explore what server-side rendering means in the context of Nuxt 3, how to leverage it effectively in your projects. If you are looking for an upgrade in Nuxt 3, this guide will equip you with the knowledge and tools you need to harness the full potential of server-side coding in your Vue applications.&lt;/p&gt;

&lt;p&gt;Assuming you already have a database connection established through Prisma ORM, we’ll dive into leveraging the power of Nuxt 3’s server-side rendering capabilities alongside Prisma’s robust data modeling features. Underlined sentences will take you to the relevant article. If you haven’t set up Prisma ORM yet, don’t worry; &lt;a href="https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql" rel="noopener noreferrer"&gt;integrate Prisma ORM into your existing project&lt;/a&gt; simply follow the instructions in the Prisma documentation to get started with setting up your database connection and generating your Prisma client.&lt;/p&gt;

&lt;p&gt;No matter which database you use, the process will remain the same unless you have the DATABASE_URL in your .env file. Once you have your Prisma folder and schema.prisma file configured, we’ll proceed with defining our models to facilitate smooth data management within our Nuxt 3 application. We will read the outputs via Postman.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgstp21r6gqixdg30c2b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwgstp21r6gqixdg30c2b.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The folder architecture will primarily resemble;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    | assets/
    | components/
    | pages/
    | prisma/
    | |- schema.prisma/
    | public/
    | server/
    | |- api/
    |- app.vue
    |- nuxt.config.ts
    |- package.json
    |- yarn.lock
    |- README.md
    |- tsconfig.json

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the Prisma model creation process. We’ll employ this model to define all CRUD operations.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/prisma/schema.prisma&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;`   generator client {&lt;br&gt;
      provider = "prisma-client-js"&lt;br&gt;
    }&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Users {
  Id       Int      @id @default(autoincrement()) // Primary key
  Name     String
  Surname  String
  Email    String   @unique
  CreateAt DateTime @default(now())          
}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Now you can &lt;a href="https://www.prisma.io/docs/orm/prisma-migrate/getting-started" rel="noopener noreferrer"&gt;migrate your model into your database&lt;/a&gt; on terminal.&lt;/p&gt;

&lt;p&gt;We’re transitioning to Nuxt 3 server-side rendering. Let’s begin by setting up the following folder structure. We’ll implement functionalities to create, update, and delete users, as well as display them individually by their IDs. We’ll utilize HTTP methods to perform these CRUD operations directly through API endpoint URLs.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;| server/&lt;br&gt;
    | |- api/&lt;br&gt;
    | | |- users/&lt;br&gt;
    | | | |- [id].get.js&lt;br&gt;
    | | | |- [id].delete.js&lt;br&gt;
    | | | |- [id].put.js&lt;br&gt;
    | | |- users.get.js&lt;br&gt;
    | | |- users.post.js&lt;br&gt;
    | |- utils/&lt;br&gt;
    | | |- prisma.js&lt;br&gt;
    |- app.vue&lt;br&gt;
    |- nuxt.config.ts&lt;br&gt;
    |- package.json&lt;br&gt;
    |- yarn.lock&lt;br&gt;
    |- README.md&lt;br&gt;
    |- tsconfig.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To prevent repetition of the Prisma import in every server file, we’ve created a prisma.js file in the util directory. Within it, we place the following code. This way, there's no need to repeatedly import Prisma in each server file.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/server/utils/prisma.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   import { PrismaClient } from '@prisma/client';

    const prisma = new PrismaClient();

    export default prisma;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve streamlined the process by directly importing utils in Nuxt. You won’t find the need to configure routes in any config file.&lt;/p&gt;

&lt;p&gt;We’ll provide detailed documentation for each file, including its code and the corresponding output we’ve verified using Postman. Lets start!&lt;/p&gt;

&lt;p&gt;/server/api/users.get.js&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  // Event handler for DELETE request to delete a user
    export default defineEventHandler(async () =&amp;gt; {
        try {
        const users = await prisma.users.findMany();
        return users;   
        } catch (error) {
          // Return error if fetching users fails
          return {
            status: 500,
            body: { message: 'Failed to fetch users' }
          };
        }
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15girclen8pfzxowowzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F15girclen8pfzxowowzv.png" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is all users over there&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/server/api/users.post.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    export default defineEventHandler(async (event) =&amp;gt; {
      const { Name, Surname, Email } = await readBody(event)

      const user = await prisma.users.create({
        data: {
          Name, Surname, Email
        },
      })
      return user
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yt3knizqji3ir5i1sjx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5yt3knizqji3ir5i1sjx.png" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In Postman, ensure to include the necessary body information for posting data, then select the POST method from the dropdown menu located at the top left corner. After the Post method, it will return the new created user.&lt;/p&gt;

&lt;p&gt;Now, we can initiate the usage of CRUD operations targeting specific user IDs. Make the postman method get again and see the user with id “1”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/server/api/users/[id].get.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    export default defineEventHandler(async (event) =&amp;gt; {
      const user = await prisma.users.findUnique(({
        where: {
          Id: parseInt(event.context.params.id)
        },
        //include: { author: true }
      }))
      return user;
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqf4cq7es1rh28nf0fys6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqf4cq7es1rh28nf0fys6.png" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets delete the test user back now. We choose the method “DELETE” and add user id the URL&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/server/api/users/[id].delete.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    export default defineEventHandler(async (event) =&amp;gt; {
        const user = await prisma.users.delete(({
          where: {
            Id: parseInt(event.context.params.id)
          },
          //include: { author: true }
        }))
        return user;
      });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6otgzd3ibsdbq4izp0na.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6otgzd3ibsdbq4izp0na.png" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s see how the change the user data via “PUT” method.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/server/api/users/[id].put.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

    export default defineEventHandler(async (event) =&amp;gt; {
        const body = await readBody(event)
        const name = body.Name
        const surname = body.Surname
        const email = body.Email

        const updateUser = await prisma.users.update({
          where: {
            Id: parseInt(event.context.params.id)},
            data: {
                Name: name,
                Surname: surname,
                Email: email,
              },
        });
        return updateUser;
    });

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re injecting the “fresh data” into the body tag, just like we do when drafting models. Before and after send operation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2FNaN%2F1%2ARoo_GjyUDl_LCj_t3gg6fg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2FNaN%2F1%2ARoo_GjyUDl_LCj_t3gg6fg.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmnlz6qjf13i5qgybrik7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmnlz6qjf13i5qgybrik7.png" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can either update all variables with new data or choose to update only the name. Any changes made in the body tag content will affect the existing data.&lt;/p&gt;

&lt;p&gt;In this article, I outlined the foundational structure and shared some essential insights into crafting a server using Nuxt. My aim is to provide valuable assistance to developers keen on advancing in this field.&lt;/p&gt;

&lt;p&gt;And if you’re ready to dive into the code, I’ve got the full repo waiting for you right &lt;a href="https://github.com/elifnurturk/nuxt-server/" rel="noopener noreferrer"&gt;**here&lt;/a&gt;**. Explore and experiment!”&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“In the grand canvas of the big picture, embark on a journey of painting each detail.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;See you in next article, happy coding!&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql" rel="noopener noreferrer"&gt;https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.prisma.io/docs/orm/prisma-migrate/getting-started" rel="noopener noreferrer"&gt;https://www.prisma.io/docs/orm/prisma-migrate/getting-started&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nuxt.com/docs/guide/directory-structure/server" rel="noopener noreferrer"&gt;https://nuxt.com/docs/guide/directory-structure/server&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nuxt.com/docs/guide/directory-structure/utils" rel="noopener noreferrer"&gt;https://nuxt.com/docs/guide/directory-structure/utils&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;*&lt;a href="https://github.com/elifnurturk/nuxt-server" rel="noopener noreferrer"&gt;https://github.com/elifnurturk/nuxt-server&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nuxt</category>
      <category>prisma</category>
      <category>typescript</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Custom Text Font Usage in Nuxt.js with Tailwind CSS</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Wed, 25 Sep 2024 13:39:36 +0000</pubDate>
      <link>https://dev.to/elifnurturk/custom-text-font-usage-in-nuxtjs-with-tailwind-css-j49</link>
      <guid>https://dev.to/elifnurturk/custom-text-font-usage-in-nuxtjs-with-tailwind-css-j49</guid>
      <description>&lt;h2&gt;
  
  
  Custom Text Font Usage in Nuxt.js with Tailwind CSS
&lt;/h2&gt;

&lt;p&gt;By integrating custom fonts into your Nuxt.js project, you can make your web application truly stand out. Tailwind CSS, known for its utility-first framework, simplifies this process, making it both efficient and effective. This article will take you through the steps to effortlessly incorporate custom fonts into your Nuxt.js project using Tailwind CSS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cstbmhotm85ucs563o5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1cstbmhotm85ucs563o5.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assuming you’ve already set up Tailwind CSS in your project, the next step is integrating custom fonts to elevate your design. Custom fonts can transform the look and feel of your Nuxt.js application, adding a unique touch that sets it apart.&lt;/p&gt;

&lt;p&gt;For this article, we'll be using the eye-catching Dirty Headline 2 font. To get started, you'll need to download the font from your browser in ZIP format. Once downloaded, extract the "Dirty Headline.ttf" file from the ZIP archive. This font will add a unique flair to our project, ensuring our typography stands out with a bold and distinctive style.&lt;/p&gt;

&lt;p&gt;Let’s create the following folders into the assets folder;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;-assets/css/font.css&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;-assets/fonts/&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;| assets/&lt;br&gt;
    | |- css/&lt;br&gt;
    | | |- font.css&lt;br&gt;
    | |- fonts/&lt;br&gt;
    | | |- DirtyHeadline.ttf&lt;br&gt;
    | pages/&lt;br&gt;
    | |- index.js&lt;br&gt;
    |- app.vue&lt;br&gt;
    |- nuxt.config.ts&lt;br&gt;
    |- package.json&lt;br&gt;
    |- tailwind.config.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To incorporate the DirtyHeadline.ttf font file into project pull it to assets/font folder and create a font.css file to define the @font-face rule for this font.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/assets/css/font.css&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    @font-face {
        font-family: 'Dirty Headline 2';
        src: url('~/assets/fonts/DirtyHeadline.ttf') format('truetype');
        font-weight: normal;
        font-style: normal;
      }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s integrate this font into your nuxt.config.ts and tailwind.config.js files.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;nuxt.config.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    export default defineNuxtConfig({
      css: ['@/assets/css/fonts.css'],
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;tailwind.config.ts&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    /** @type {import('tailwindcss').Config} */

    export default {
      theme: {
        extend: {
          fontFamily: {
            'dirty-headline': ['"Dirty Headline 2"', 'sans-serif']
          }
        }, 
      },
     }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we can try the new font in our vue pages!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;pages/index.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;template&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h1&amp;gt; class="font-dirty-headline"&amp;gt;The Dirty Font!&amp;lt;/h1&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we go&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fliwgm20ey5gqmtxhtzu4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fliwgm20ey5gqmtxhtzu4.png" width="387" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See you in next article!&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>webdev</category>
      <category>css</category>
      <category>nuxt</category>
    </item>
    <item>
      <title>I18n Localization for Nuxt.js ! Implement multi-language support to website.</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Wed, 25 Sep 2024 06:36:41 +0000</pubDate>
      <link>https://dev.to/elifnurturk/i18n-localization-for-nuxtjs-implement-multi-language-support-to-website-50n3</link>
      <guid>https://dev.to/elifnurturk/i18n-localization-for-nuxtjs-implement-multi-language-support-to-website-50n3</guid>
      <description>&lt;h2&gt;
  
  
  I18n Localization for Nuxt.js ! Implement multi-language support to website.
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Understanding I18n Localization in Nuxt 3
&lt;/h2&gt;

&lt;p&gt;In today’s interconnected world, creating web applications that cater to users from diverse linguistic backgrounds is paramount. Whether you’re building a personal blog or a large-scale enterprise platform, ensuring your content is accessible and understandable to users worldwide is crucial. This is where Internationalization (I18n) and Localization come into play. With the release of Nuxt 3, the process of implementing I18n localization has been streamlined, making it easier than ever to reach a global audience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is I18n Localization?
&lt;/h2&gt;

&lt;p&gt;I18n, short for “Internationalization,” is the process of designing and developing software applications that can adapt to various languages and cultural contexts without engineering changes. Localization, on the other hand, refers to the adaptation of a product, application, or content to meet the language, cultural, and other requirements of a specific target market or locale. Together, I18n and localization ensure that your web application is not only available in different languages but also culturally relevant and sensitive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F02u9b83legqhjnsf9le4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F02u9b83legqhjnsf9le4.png" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Nuxt 3: Simplifying Localization
&lt;/h2&gt;

&lt;p&gt;Nuxt 3, the latest iteration of the popular Vue.js framework, comes with built-in support for I18n localization, making it easier for developers to create multilingual applications. Let’s delve into how Nuxt 3 simplifies the process:&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration-driven Approach
&lt;/h2&gt;

&lt;p&gt;Nuxt 3 adopts a configuration-driven approach for I18n localization. Developers can define locales, language-specific content, and other localization-related settings directly in the Nuxt configuration file (nuxt.config.js), eliminating the need for additional plugins or complex setups.&lt;/p&gt;

&lt;h2&gt;
  
  
  Locale-based Routing
&lt;/h2&gt;

&lt;p&gt;With Nuxt 3, creating locale-based routes is seamless. Developers can define routes specific to each language/locale, allowing users to navigate the application in their preferred language effortlessly. Nuxt automatically handles route generation and navigation based on the user’s selected locale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component-level Localization
&lt;/h2&gt;

&lt;p&gt;Nuxt 3 enables component-level localization, empowering developers to create reusable UI components that adapt to different languages and locales seamlessly. This granular approach to localization enhances code reusability and maintainability while ensuring a consistent user interface across language variations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Nuxt 3 Localization
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Here’s a simplified guide to getting started:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install I18n in Nuxt 3: Begin with installing I18n in your exist project by using npm, yarn or pnpm&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @nuxtjs/i18n --save-dev
yarn add --dev @nuxtjs/i18n
pnpm add -D @nuxtjs/i18n
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Upon completion of the installation process, it is recommended to remove the package-lock.json and yarn.lock files. Subsequently, reinstallation of dependencies should be carried out to ensure a clean and consistent environment. And Let’s check the package.json to see.&lt;/p&gt;

&lt;blockquote&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "devDependencies": {
      "@nuxtjs/i18n": "^8.0.0"
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Following the dependency setup, the creation of the “locale” folder and language-specific JSON files can commence, facilitating the localization process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3sc5a5ru1fj97xcwe4t.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3sc5a5ru1fj97xcwe4t.jpeg" width="137" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Configure Localization: Define locales, language-specific content, and other localization settings in the nuxt.config.ts file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    export default defineNuxtConfig({
      modules: ['@nuxtjs/i18n'],
      i18n: {
        // Module Options
        lazy: true,
        langDir: "locales", 
        strategy: "prefix_except_default",
        defaultLocale: "en", // Default Language
        locales: [
            { code: "tr", iso: "tr-TR", file: "tr.json"},
            { code: "en", iso: "en-US", file: "en.json" },
        ],
      }
    })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create Language-specific Content: Organize language-specific content in separate JSON files under the locales directory:&lt;/p&gt;

&lt;p&gt;./locales/en.json&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  {
        "helloWorld" : "Hello World"
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;./locales/tr.json
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; {
        "helloWorld" : "Merhaba Dünya"
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, now we can use only 1 variable name for 2 language support.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    &amp;lt;div&amp;gt;
      {{ $t("helloWorld") }}
    &amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Output be like, for &lt;a href="http://www...com/" rel="noopener noreferrer"&gt;www...com/&lt;/a&gt; and &lt;a href="http://www...com/tr/" rel="noopener noreferrer"&gt;www...com/tr/&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ficmymf40gqbz051pgt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ficmymf40gqbz051pgt.png" width="186" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlpfp7lanyfsbd4ylscz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdlpfp7lanyfsbd4ylscz.png" width="240" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I18n localization is no longer a daunting task, thanks to the advancements in frameworks. By embracing a configuration-driven approach, dynamic content translation, and integrated tooling, Nuxt 3 simplifies the process of creating multilingual applications.&lt;/p&gt;

&lt;p&gt;By following these steps, you can leverage the power of Nuxt 3 to create fully localized web applications that resonate with users worldwide.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;See you in next article!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://i18n.nuxtjs.org/docs/getting-started" rel="noopener noreferrer"&gt;https://i18n.nuxtjs.org/docs/getting-started&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>i18n</category>
      <category>localization</category>
      <category>webdev</category>
      <category>nuxt</category>
    </item>
    <item>
      <title>Building Scalable Web Designs with Nuxt Layouts</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Tue, 24 Sep 2024 06:32:44 +0000</pubDate>
      <link>https://dev.to/elifnurturk/building-scalable-web-designs-with-nuxt-layouts-1b7p</link>
      <guid>https://dev.to/elifnurturk/building-scalable-web-designs-with-nuxt-layouts-1b7p</guid>
      <description>&lt;h2&gt;
  
  
  Building Scalable Web Designs with Nuxt Layouts
&lt;/h2&gt;

&lt;p&gt;Layouts play a crucial role in creating scalable web designs by providing reusable, consistent structures across pages, which helps in maintaining and scaling your application as it grows. Layouts in Nuxt provide a reusable structure for your pages, allowing you to define headers, footers, sidebars, or any other common components in one place. This article will walk you through how to use layouts in Nuxt and how they can streamline your development process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Use Layouts?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In large applications, certain elements such as navigation bars, footers, or sidebars tend to appear on multiple pages. Instead of repeating these components in each page file, Nuxt layouts allow you to centralize them, reducing redundancy and improving maintainability. With layouts, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduce Code Duplication&lt;/strong&gt;: Common structures like headers and footers can be defined once and used throughout multiple pages.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improve Readability&lt;/strong&gt;: By separating page content from the layout structure, your code becomes more modular and readable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increase Flexibility&lt;/strong&gt;: You can define multiple layouts and assign them to different pages or sections of your app, giving you the flexibility to create unique designs while maintaining consistency.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Creating Layouts in Nuxt&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By default, Nuxt provides a &lt;strong&gt;default layout&lt;/strong&gt; that wraps around your pages, but you can easily create custom layouts to suit your needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Define a Layout&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To create a new layout, you need to add a layout file to the layouts/ directory in your Nuxt project. If the layouts/ folder doesn’t exist yet, create one.&lt;/p&gt;

&lt;p&gt;For example, let’s create a layout called default.vue:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;| assets/
| layouts/
|- default.vue
|- admin.vue
| components/
|- Header.vue
|- Footer.vue
|- Sidebar.vue
| pages/
|- index.js
| public/
|- app.vue
|- nuxt.config.ts
|- package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;/layouts/default.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;template&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;Header /&amp;gt;
        &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
        &amp;lt;Footer /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;/layouts/admin.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;template&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;Sidebar /&amp;gt;
        &amp;lt;slot&amp;gt;&amp;lt;/slot&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now efficiently apply layouts to pages, ensuring a consistent and organized structure throughout the application.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;/app.vue&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;template&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;NuxtLayout&amp;gt; 
           &amp;lt;NuxtPage /&amp;gt; 
        &amp;lt;/NuxtLayout&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;/pages.index.js&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;template&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;p&amp;gt;This is the main page.&amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;
    &amp;lt;script setup&amp;gt;
    definePageMeta({
      layout: "default",
    });
    &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4k6gbk6ylv6ys9v13cbx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4k6gbk6ylv6ys9v13cbx.png" alt="Image description" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and for the admin pages,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;template&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;p&amp;gt;This is the main page.&amp;lt;/p&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/template&amp;gt;
    &amp;lt;script setup&amp;gt;
    definePageMeta({
      layout: "admin",
    });
    &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwki029454vans3sj4j4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvwki029454vans3sj4j4.png" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Layouts in Nuxt are a powerful way to create reusable, consistent structures across your application, making your code more modular and maintainable. By defining common components like headers and footers in layouts, you can streamline your page development, improve flexibility, and keep your application organized.&lt;/p&gt;

&lt;p&gt;Whether you’re working on a small personal project or a large-scale application, leveraging layouts in Nuxt will help you manage your UI and design efficiently with features like dynamic layouts, slot support, and ease of setup.&lt;/p&gt;

&lt;p&gt;See you in next article!&lt;/p&gt;

&lt;h1&gt;
  
  
  nuxtjs #vue.js #layouts #web #webdevelopment
&lt;/h1&gt;

</description>
      <category>nuxt</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>vue</category>
    </item>
    <item>
      <title>Exploring Server-Side Rendering and Database Operations in Nuxt.js with Prisma ORM</title>
      <dc:creator>Elif Nur Turk</dc:creator>
      <pubDate>Fri, 23 Aug 2024 07:30:33 +0000</pubDate>
      <link>https://dev.to/elifnurturk/exploring-server-side-rendering-and-database-operations-in-nuxtjs-with-prisma-orm-5576</link>
      <guid>https://dev.to/elifnurturk/exploring-server-side-rendering-and-database-operations-in-nuxtjs-with-prisma-orm-5576</guid>
      <description>&lt;p&gt;&lt;a href="https://elifnurturk.medium.com/exploring-server-side-rendering-and-database-operations-in-nuxt-3-with-prisma-orm-39cb51e0bb2a" rel="noopener noreferrer"&gt;Exploring Server-Side Rendering and Database Operations in Nuxt.js with Prisma ORM&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
