Strapi blog logo
  • Product

      Why Strapi?Content ArchitectureRoadmapIntegrationsTry live demo
      OverviewContent Types BuilderCustomizable APIMedia LibraryRoles & Permissions
      Discover Strapi Enterprise EditionDiscover our partners
  • Pricing

  • Solutions

      Static WebsitesMobile ApplicationsCorporate websitesEditorial SitesEcommerce
      Delivery HeroL'EquipeSociete GeneralePixelDustBanco International
      Discover all our user stories
  • Community

      CommunityWrite for the communityWall of LoveStrapi Conf 2021
      SlackGitHubYoutubeCommunity Forum
      Meet the Strapi Community StarsDiscover the Strapi Showcase
  • Resources

      BlogStartersNewsroomSupport
      Strapi AcademyTutorialsVideos GuidesWebinars
      The Guide to Headless CMS Strapi Community Forum
  • Docs

      Getting StartedInstallationConfigurationsDeploymentUpdate versionContent API
      Getting StartedContent ManagerContent-Types BuilderUsers, Roles & PermissionsPlugins
      Developer DocumentationStrapi User Guide

Looking for our logo ?

Logo Brand download
Download Logo Pack
See more Strapi assets
Strapi blog logo
  • Product

    Product

    • Why Strapi?
    • Content Architecture
    • Roadmap
    • Integrations
    • Try live demo

    Features

    • Overview
    • Content Types Builder
    • Customizable API
    • Media Library
    • Roles & Permissions
    • Discover Strapi Enterprise Edition
    • Discover our partners
    Features cover

    Unlock the full potential of content management

    See all features
    Strapi Enterprise Edition

    Discover the advanced features included in Strapi Enterprise Edition.

    Get Started
  • Pricing
  • Solutions

    Solutions

    • Static Websites
    • Mobile Applications
    • Corporate websites
    • Editorial Sites
    • Ecommerce

    Stories

    • Delivery Hero
    • L'Equipe
    • Societe Generale
    • PixelDust
    • Banco International
    • Discover all our user stories
    Delivery Hero team

    Delivery Hero manages their partner portal with Strapi.

    Read their story
    turn 10 studios website

    How 1minus1 delivered a creative website for Turn10 Studios 25% faster with Strapi

    Discover their story
  • Community

    Community

    • Community
    • Write for the community
    • Wall of Love
    • Strapi Conf 2021

    Resources

    • Slack
    • GitHub
    • Youtube
    • Community Forum
    • Meet the Strapi Community Stars
    • Discover the Strapi Showcase
    Strapi Conf

    The first Strapi Global User Conference.

    Register now
    Write for the community

    Contribute on educational content for the community

    Discover the program
  • Resources

    Resources

    • Blog
    • Starters
    • Newsroom
    • Support

    Learning

    • Strapi Academy
    • Tutorials
    • Videos Guides
    • Webinars
    • The Guide to Headless CMS
    • Strapi Community Forum
    Introducing Strapi Academy

    Everything you need to know to master Strapi.

    Go to the academy
    Strapi Repository on GitHub

    Get started with the Strapi repository

    Go to repository
  • Docs

    Developers

    • Getting Started
    • Installation
    • Configurations
    • Deployment
    • Update version
    • Content API

    User Guide

    • Getting Started
    • Content Manager
    • Content-Types Builder
    • Users, Roles & Permissions
    • Plugins
    • Developer Documentation
    • Strapi User Guide
    Install Strapi

    Install Strapi locally or wherever you need.

    Get Started
    Migration Guides Strapi

    Using a previous version of Strapi? Migrate to the latest.

    Read Guides
Get Started
Back to articles

How to use the @nuxtjs/strapi Module to add Authentication to a Nuxt Application

nuxt/strapi Module to add Authentication to a Nuxt Application
  • Share on facebook
  • Share on linkedin
  • Share on twitter
  • Share by email
Alex Godwin

Alex Godwin

February 8, 2021

In this tutorial, we’ll be learning about authentication (local authentication) in Strapi. We’ll be creating a simple blog app where authenticated users can create, read and delete posts, whereas unauthenticated users can only view a list of posts but cannot read, create, or delete posts. We’ll have a login route, signup route, and a create post route where users can create posts from. We’ll also be working with Image uploads to see how users can upload images from Nuxt.js frontend to our Strapi backend.

What you’ll need for this tutorial

  • Basic Knowledge of Vue.js
  • Knowledge of JavaScript
  • Node.js (v14 recommended for strapi)
  • MongoDB

Table of Content

  • Installing Strapi
  • Building API with Strapi
  • Installing Nuxt.js
  • Installing @nuxtjs/strapi
  • Building the frontend with Nuxt.js

Let’s get started!

Installing Strapi

As mentioned in Strapi's documentation, Strapi is a flexible, open-source Headless CMS that gives developers the freedom to choose their favorite tools and frameworks while also allowing editors to easily manage and distribute their content. By making the admin panel and API extensible through a plugin system, Strapi enables the world's largest companies to accelerate content delivery while building beautiful digital experiences.

Basically, Strapi helps us build an API in no time. I mean no hassle of creating a server from scratch. With Strapi, we can do everything literally, and it’s easily customizable. We can add our code and edit functionalities easily. Strapi is simply amazing, and I’m modest about it. I’m still stunned by what Strapi can do.

Strapi provides an admin panel to edit and create APIs and also includes code that can be edited. It’s very easy to edit the code, and it makes use of JavaScript.

Strapi Admin panel

Strapi code

To install Strapi, head over to the Strapi docs at Strapi, but we want to use MongoDB as our database, so we are going to do things a little differently here, head over to Strapi docs. That section of the Strapi docs shows how to use MongoDB as our default database, follow the instructions there. Make sure to have the MongoDB server running before you start the process, and leave the username and password options as blank by pressing enter when prompted.

  • To install Strapi:
yarn create strapi-app my-project //using yarn
npx create-strapi-app my-project //using npx

Replace my-project with the name you wish to call your application directory, your package manager will create a directory with the name and will install Strapi.

If you have followed the instructions correctly, you should have strapi installed in your machine.

  • Run:
yarn develop //using yarn
npm run develop //using npm

To start our development server, Strapi starts our app on http://localhost:1337/admin.

Building The API with Strapi

We have Strapi up and running, the next step is to create our products content-type.

  1. Creating Article content-type
  • Click on content-types in the side menu
  • Add new content-type named article.
  • Create fields under article content-type
  • Name as short text
  • Description as short text
  • content as Rich text
  • Image as a single type.
  1. Adding User relationship
  • Create a relation field under article
  • Select User(from users-permissions-user) click on user has many articles relation
  • Save the article content type
  1. Creating User and Enabling User permission and Roles
  • Strapi provides a Users collection type by default
  • Head to settings
  • Under Users and Permissions Plugin select Roles
  • Click on Authenticated and check all Permissions.
  • Save changes then go back and click on public then check only the find and findOne permissions
  • Click save to save changes.
  • Create a user called author with whatever credentials you’d like, but select the authenticated role, and also enable email confirmation.
  • Create an Article, then select Users_permissions_user as author. This means that the user ‘author’ created the article.
  • Save the article, and proceed.

Save content-types, and now we can view our API in JSON format when we visit http://localhost:1337/articles. Now that we’ve created our Strapi API, what we have to do is build our front end with Nuxt.js. Let’s do that.

Installing Nuxt.js

To install Nuxt.js visit the Nuxt docs.

We want to use Nuxt in SSR mode, server hosting and also Tailwind CSS as our preferred CSS framework, so go ahead and select those, then select whatever options for the rest. Preferably leave out C.I, commit-linting, style-linting and the rest but do whatever you like. All we’ll be needing in this tutorial is what I’ve mentioned above.

  • To install Nuxt.js:
yarn create nuxt-app <project-name> //using yarn
npx create-nuxt-app <project-name> //using npx
npm init nuxt-app <project-name> //using npm

Which will ask you some questions (name, Nuxt options, UI framework, TypeScript, linter, testing framework, etc).

Once all questions are answered, all the dependencies will be installed. The next step is to navigate to the project folder and launch it.

  • Run:
yarn dev //using yarn
npm run dev //using npm

We should have Nuxt running on http://localhost:3000.

Installing @nuxtjs/strapi

We need a way to query our Strapi backend API, and Strapi provides a very nice package for that. We could use Nuxt’s native @nuxtjs/http module or axios to query our API but @nuxtjs/strapi makes our life easier. To install @nuxtjs/strapi.

  • Run:
yarn add @nuxtjs/strapi //using yarn
npm install @nuxtjs/strapi //using npm
  • Open the nuxt.config.js file and add the following code to the file
modules: [
  // ...other modules
  '@nuxtjs/strapi',
]

strapi: {
  entities: ['articles'],
}

Now we can use @nuxtjs/strapi to make API calls, we can now continue with building our pages and components.

The @nuxtjs/strapi documentation can be found here.

  • We’ll be using @nuxtjs/strapi in two ways
this.$strapi() //from properties such as methods, data, computed

$strapi() //from nuxtjs lifecycle methods

Installing @nuxtjs/markdownit

Strapi Rich text gives us the privilege of writing markdown in our content, to parse the markdown content from the backend we need to install the @nuxtjs/markdownit package.

  • Run
yarn add @nuxtjs/markdownit //using yarn
npm install @nuxtjs/markdownit //using npm
  • Then add the following lines of code to your nuxt.config.js file.
modules: [
 //...other modules
'@nuxtjs/markdownit'
],

 markdownit: {
    preset: 'default',
    linkify: true,
    breaks: true,
    injected: true,
    // use: ['markdown-it-div', 'markdown-it-attrs'],
  },

Now we can use @nuxtjs/markdownit to parse our markdown content. The @nuxtjs/markdownit documentation can be found here.

Building the frontend with NuxtJs

We can proceed with building the user-interface of our blog app.

Building the Signup page

  • Execute the following lines of code to create a signup.vue file in the pages directory.
cd pages
touch signup.vue
  • Fill signup.vue with the following lines of code.

 <template>
  <div class="w-4/5 mx-auto md:w-1/2 text-center my-12">
    <div v-show="error !== ''" class="p-3 border">
      <p>{{ error }}</p>
    </div>
    <h1 class="font-bold text-2xl md:text-4xl mt-5">Signup</h1>
    <form @submit="createUser">
      <div>
        <input
          v-model="email"
          class="p-3 my-5 border w-full"
          type="email"
          placeholder="email"
        />
      </div>
      <div>
        <input
          v-model="username"
          class="p-3 my-5 border w-full"
          type="text"
          placeholder="username"
        />
      </div>
      <div>
        <input
          v-model="password"
          class="p-3 my-5 border w-full"
          type="password"
          placeholder="password"
        />
      </div>
      <div>
        <button
          class="button--green"
          :disabled="email === '' || password === '' || username === ''"
          type="submit"
        >
          Signup
        </button>
      </div>
    </form>
  </div>
</template>
<script>
export default {
  data() {
    return {
      email: '',
      username: '',
      password: '',
      error: '',
    }
  },
  methods: {
    async createUser(e) {
      e.preventDefault()
      try {
        const newUser = await this.$strapi.register({
          email: this.email,
          username: this.username,
          password: this.password,
        })
        console.log(newUser)
        if (newUser !== null) {
          this.error = ''
          this.$nuxt.$router.push('/articles')
        }
      } catch (error) {
        this.error = error.message
      }
    },
  },
  middleware: 'authenticated',
}
</script>
<style></style>

We just built our signup logic. When users provide their email, username and password, then click the signup button, we invoke the createUser method. All we’re doing in this method is registering a new user using the @nuxtjs/strapi module i.e this.$strapi.register() method, then we redirect the user to the ‘/articles’ route, if the email belongs to an existing user an error message is displayed at the top of the page. Finally, we’re using nuxtjs middleware feature to invoke a custom made middleware that we’re going to create.

Building the Login page

  • Execute the following lines of code to create a login.vue file in the pages directory.
touch login.vue
  • Fill up login.vue with the following lines of code.
<template>
  <div class="w-4/5 mx-auto md:w-1/2 text-center my-12">
    <div v-show="error !== ''" class="p-3 border">
      <p>{{ error }}</p>
    </div>
    <h1 class="font-bold text-2xl md:text-4xl mt-5">Login</h1>
    <form @submit="loginUser">
      <div>
        <input
          v-model="identifier"
          class="p-3 my-5 border w-full"
          type="email"
          placeholder="email"
        />
      </div>
      <div>
        <input
          v-model="password"
          class="p-3 my-5 border w-full"
          type="password"
          placeholder="password"
        />
      </div>
      <div>
        <button
          :disabled="identifier === '' || password === ''"
          class="button--green"
          type="submit"
        >
          Login
        </button>
      </div>
    </form>
  </div>
</template>
<script>
export default {
  data() {
    return {
      identifier: '',
      password: '',
      error: '',
    }
  },
  methods: {
    async loginUser(e) {
      e.preventDefault()
      try {
        const user = await this.$strapi.login({
          identifier: this.identifier,
          password: this.password,
        })
        console.log(user)
        if (user !== null) {
          this.error = ''
          this.$nuxt.$router.push('/articles')
        }
      } catch (error) {
        this.error = 'Error in login credentials'
      }
    },
  },
  middleware: 'authenticated',
}
</script>
<style></style>

We’ve just built our login logic, users provide a unique identifier(email) and password then click on the login button which calls the loginUser method. This method attempts to log the user in using the @nuxtjs/strapi module i.e this.$strapi.login() method and returns a user object if a user is found, or an error if the credentials are invalid. The user is redirected to the ‘/article’ route if the process was successful or an error message is displayed if an error occurred.

Creating our authenticated middleware

Let’s create our middleware function:

  • Execute the following lines of code to create an authenticated.js file in the middleware directory.
cd middleware
touch authenticated.js
  • Fill up authenticated.js with the following code.
export default function ({ $strapi, redirect }) {
  if ($strapi.user) {
    redirect('/articles')
  }
}

We have set up a middleware that checks if a user is logged in or not. If a user is logged in we redirect them to the ‘/articles’ page, this middleware is useful for preventing a logged in user from accessing the Login, Signup and ‘/’ route. We don’t want to have a Logged in user signing up on our app for whatsoever reason.

Building the Nav component

  • Execute the following lines of code to create a Nav.vue file in the components directory.
cd components
touch Nav.vue
  • Fill up the file with the following code
<template>
  <div
    class="flex space-x-5 items-center justify-center bg-black text-white py-3 sm:py-5"
  >
    <NuxtLink to="/articles">Articles</NuxtLink>
    <div v-if="$strapi.user === null">
      <NuxtLink class="border-r px-3" to="/login">Login</NuxtLink>
      <NuxtLink class="border-r px-3" to="/signup">Signup</NuxtLink>
    </div>
    <div v-if="$strapi.user !== null">
      <span class="border-r px-3">{{ $strapi.user.username }}</span>
      <NuxtLink class="border-r px-3" to="/new">Create Post</NuxtLink>
      <button class="pl-3" @click="logout">Logout</button>
    </div>
  </div>
</template>
<script>
export default {
  name: 'Nav',
  methods: {
    async logout() {
      await this.$strapi.logout()
      this.$nuxt.$router.push('/')
    },
  },
}
</script>
<style></style>

In the Nav component, all we’re doing is building a navigation bar for our application. using the @nuxt/strapi module, we’re checking if there is no logged in user, then we display a sign up and login option in the nav bar, but if a user is logged in, we display their username, logout option and a create post link.

  • Note:
$strapi.user //returns the loggedin user or null

When a User clicks the logout button, we invoke a logout function which in turn invokes the $strapi.logout() function that logs the user out, the we redirect the user to the ‘/’ route using the $nuxt.$router.push() method.

Building the Homepage

  • Execute the following lines of code to create an index.vue file in the pages directory.
cd pages
code index.vue
  • Fill up the index.vue file with the following code.
<template>
  <div class="container">
    <div>
      <h1 class="title">Welcome To The BlogApp</h1>
      <div class="links">
        <NuxtLink to="/login" class="button--green"> Login </NuxtLink>
        <NuxtLink to="/articles" class="button--grey"> Continue Free </NuxtLink>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  middleware: 'authenticated',
}
</script>
<style>
/* Sample `apply` at-rules with Tailwind CSS
.container {
@apply min-h-screen flex justify-center items-center text-center mx-auto;
}
*/
.container {
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}
.title {
  font-family: 'Quicksand', 'Source Sans Pro', -apple-system, BlinkMacSystemFont,
    'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  display: block;
  font-weight: 300;
  font-size: 80px;
  color: #35495e;
  letter-spacing: 1px;
}
.subtitle {
  font-weight: 300;
  font-size: 42px;
  color: #526488;
  word-spacing: 5px;
  padding-bottom: 15px;
}
.links {
  padding-top: 15px;
}
</style>

What we have here is our homepage. We’re using Nuxt.js middleware feature to invoke a custom made middleware that we created.

Building the articles page

  • Execute the following lines of code to create a articles.vue file in the pages directory.
cd pages
touch articles.vue
  • Fill it up with the following code.
<template>
  <div>
    <Nav class="mx-auto sticky top-0" />
    <h1 class="text-center my-5">All our articles</h1>
    <div
      v-show="error !== ''"
      class="sticky z-100 border p-5 m-3 top-0 bg-black text-white text-center mx-auto w-4/5 sm:w-4/5 md:w-4/5 lg:w-1/2"
    >
      <p class="m-1 sm:m-3">{{ error }}</p>
      <button class="button--grey" @click="resetError()">Ok</button>
    </div>
    <div
      v-for="(article, i) in data"
      :key="i"
      class="sm:flex sm:space-x-5 my-5 shadow-lg mx-auto w-4/5 sm:w-4/5 md:w-4/5 lg:w-1/2"
    >
      <img
        :src="`http://localhost:1337${article.image.url}`"
        class="max-h-screen sm:h-48"
      />
      <div class="px-2 sm:pr-2 sm:text-left text-center">
        <h3 class="font-bold my-3">{{ article.Title }}</h3>
        <p class="my-3">{{ article.description }}</p>
        <button class="button--green mb-4 sm:mb-0" @click="readPost(article)">
          Read more
        </button>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  async asyncData({ $strapi, $md }) {
    const data = await $strapi.$articles.find()
    return { data }
  },
  data() {
    return {
      error: '',
    }
  },
  methods: {
    readPost(article) {
      if (this.$strapi.user) {
        this.error = ''
        this.$nuxt.$router.push(`/article/${article.id}`)
      } else {
        this.error = 'Please Login to read articles'
      }
    },
    resetError() {
      this.error = ''
    },
  },
}
</script>
<style></style>

On this page, we’re doing a couple of things. First, we’re using the @nuxtjs/strapi module to find all our articles then we display the articles on our page, then in the readPost method, we’re checking if a user is logged in before allowing the user to read a post, if the user is not logged in we display an error message saying ‘please login to read articles’.

Building the article content page

  • Execute the following lines of code to create a _id.vue file in the pages directory.
mkdir article
touch _id.vue
  • Fill the _id.vue file with the following code.
<template>
  <div>
    <Nav class="mx-auto sticky top-0" />
    <div class="w-4/5 sm:w-1/2 mx-auto my-5">
      <h3 class="my-5 font-bold text-4xl">{{ article.Title }}</h3>
      <img
        :src="`http://localhost:1337${article.image.url}`"
        class="max-h-screen"
      />
      <p class="mt-5 font-bold">
        written by {{ article.users_permissions_user.username }}
      </p>
      <div class="my-5" v-html="$md.render(article.Content)"></div>
      <button
        v-if="
          $strapi.user && article.users_permissions_user.id === $strapi.user.id
        "
        class="button--grey"
        @click="deletePost(article.id)"
      >
        Delete
      </button>
    </div>
  </div>
</template>
<script>
export default {
  async asyncData({ $strapi, route }) {
    const id = route.params.id
    const article = await $strapi.$articles.findOne(id)
    return { article }
  },
  methods: {
    async deletePost(id) {
      await this.$strapi.$articles.delete(id)
      this.$nuxt.$router.push('/articles')
    },
  },
  middleware({ $strapi, redirect }) {
    if ($strapi.user === null) {
      redirect('/articles')
    }
  },
}
</script>
<style scoped>
h1 {
  font-weight: 700;
  font-size: 2rem;
  margin: 0.5em 0;
}
</style>

On this page, We’re displaying individual articles with it’s complete content using markdownit i.e $md.render(article.content) , author name and more. We also display a delete button if the current user is the author of the post, we’re checking for that by using the @nuxtjs/strapi module. We don’t want an unauthorized user to delete a post they didn’t create. Finally, in the middleware, we’re checking for a logged in user. If there’s none we redirect back to the ‘/articles’ route, making sure the article content page is totally inaccessible to unauthenticated users.

Building the create article page

  • Execute the following lines of code to create a New.vue file in the pages directory.
touch New.vue
  • Fill up the New.vue file with the following lines of code
<template>
  <div class="w-4/5 mx-auto md:w-1/2 text-center my-12 overflow-hidden">
    <form ref="form" @submit="createPost">
      <h2 class="font-bold text-2xl md:text-4xl mt-5">Create a new post</h2>
      <div>
        <input
          v-model="form.Title"
          name="Title"
          type="text"
          placeholder="title"
          class="p-3 my-3 border w-full"
        />
      </div>
      <div>
        <input
          v-model="form.description"
          name="description"
          type="text"
          placeholder="description"
          class="p-3 my-3 border w-full"
        />
      </div>
      <div>
        <textarea
          v-model="form.Content"
          name="Content"
          cols="30"
          rows="10"
          class="p-3 my-3 border w-full"
        ></textarea>
      </div>
      <div>
        <input
          type="file"
          name="Image"
          class="p-3 my-3 border w-full"
          @change="assignFileInput()"
        />
      </div>
      <div>
        <button
          class="button--green"
          :disabled="
            form.Title === '' ||
            form.description === '' ||
            form.Content === '' ||
            fileInput === ''
          "
          type="submit"
        >
          Create
        </button>
      </div>
    </form>
  </div>
</template>
<script>
export default {
  data() {
    return {
      form: {
        Title: '',
        description: '',
        Content: '',
        users_permissions_user: this.$strapi.user,
      },
      fileInput: '',
    }
  },
  methods: {
    async createPost(e) {
      const formData = new FormData()
      let file
      const formElements = this.$refs.form.elements
      formElements.forEach((el, i) => {
        if (el.type === 'file') {
          file = el.files[0]
        }
      })
      formData.append(`files.image`, file, file.name)
      formData.append('data', JSON.stringify(this.form))
      e.preventDefault()
      await this.$strapi.$articles.create(formData)
      this.$nuxt.$router.push('/articles')
    },
    assignFileInput() {
      const formElements = this.$refs.form.elements
      formElements.forEach((el, i) => {
        if (el.type === 'file') {
          this.fileInput = el.files[0] !== undefined ? el.files[0].name : ''
        }
      })
    },
  },
  middleware({ $strapi, redirect }) {
    if (!$strapi.user) {
      redirect('/articles')
    }
  },
}
</script>
<style></style>

We just created the logic to enable authenticated users to create new articles. The logic is complicated especially the file upload logic so let’s work through it step by step. We built the content creation form as usual, with fields for title, description, image upload and content and the create button. using the v-model directive we link up the fields with their respective data property, file input do not support the v-model directive so we’ve built a workaround. What we’ve done is create an assignInput() method that is invoked when the field input with file type changes, when a change occurs we check if the type of the form element that changed is a file, if it is, we assign the name of the selected file as the value of fileInput. Next, the createPost() method allows users to create articles. Using FormData we append the form object from the page’s data property in string form to FormData with a data property. We do the same thing for file input but we append it to FormData with a files.image property. This is because for multipart data Strapi requires that the property be preceded by files i.e files.${fieldname} and our fieldname from the article content-type is image. With all that done, we should have our create article logic working fine.

The frontend repo for this tutorial can be found here

The backend repo for this tutorial can be found here

So devs, we’ve come to the end of this tutorial. I hope you now have what it takes to tackle Strapi authentication with NuxtJs in your arsenal. Stay tuned until the next tutorial.

Please note: Since we initially published this blog post, we released new versions of Strapi and tutorials may be outdated. Sorry for the inconvenience if it's the case. Please help us by reporting it here.

  • Try live demo
  • Starters
  • Become a Strapi expert
  • Find help in our Forum
  • Strapi on Youtube
  • Try Enterprise Edition
  • Share on facebook
  • Share on linkedin
  • Share on twitter
  • Share by email

You might also be interested in...

Strapi Starter Nuxt.js e-commerce

    Strapi Starter Nuxt.js e-commerce

    Bootstrap a simple e-commerce website using Strapi, Nuxt.js and Snipcart. In this starter, you'll be able to use all the latest features available in Strapi.

    Maxime Castres

    August 20, 2020

    Strapi Authentication in Nuxt.js
    • Guides & Tutorials

    Strapi Authentication in Nuxt.js

    This is a step-by-step guide on how to implement Strapi-based authentication in a Nuxt.js app.

    Rami Shashati

    Rami Shashati

    August 25, 2020

    User Authentication in Next.js with Strapi
    • Guides & Tutorials
    • Web Development

    User Authentication in Next.js with Strapi

    In this article, we get into Next.js and look to solve the problem of user Authentication with Strapi and it's built in user management functionality.

    Nirmalya Ghosh

    Nirmalya Ghosh

    January 25, 2021

    Newsletter

    Sign up for the Strapi newsletter to keep up with the latest news from the Strapi community!

    Unleash content.

    Starters
    Get Started

    Strapi is the leading open-source Headless CMS. Strapi gives developers the freedom to use their favorite tools and frameworks while allowing editors to easily manage their content and distribute it anywhere.

    Product

    • Why Strapi?
    • Content Architecture
    • Features
    • Enterprise Edition
    • Partner Program
    • Roadmap
    • Support
    • Integrations
    • Try live demo
    • Changelog

    Resources

    • How to get started
    • Meet the community
    • Tutorials
    • API documentation
    • GitHub repository
    • Starters
    • Strapi vs Wordpress
    • The Guide to headless CMS

    Integrations

    • Gatsby CMS
    • React CMS
    • Vue.js CMS
    • Nuxt.js CMS
    • Next.js CMS
    • Angular CMS
    • Gridsome CMS
    • Jekyll CMS
    • 11ty CMS
    • Svelte CMS
    • Sapper CMS
    • Ruby CMS
    • Python CMS

    Company

    • About us
    • Blog
    • Careers
    • Contact
    • Newsroom
    • © 2021, Strapi
    • LicenseTermsPrivacy