Simply copy and paste the following command line in your terminal to create your first Strapi project.
npx create-strapi-app
my-project
This tutorial is part of the « E-commerce website with Strapi, Nuxt.js, GraphQL and Strip »
Note: The source code is available on Github.
At this point, you may have expected to get ready to order. But before that, you need to give the user the possibility to register and log in to your app. No worries, Strapi comes to the rescue with its Users & Permissions plugin already installed in your project.
In this article, you will create a new user system. With the ability to verify, create, and logout a user.
To quicken your front-end development, you are going to install an HTTP module. HTTP module for Nuxt.js provides a universal way to make HTTP requests to our Strapi API.
Let’s add @nuxt/http
dependency to our project:
1
npm install @nuxt/http
Then add it to the modules section in your nuxt.config.js
:
1
2
3
4
5
6
7
8
9
10
11
12
13
// nuxt.config.js
const strapiBaseUri = process.env.API_URL || 'http://localhost:1337'
export default {
// Modules: https://go.nuxtjs.dev/config-modules
modules: ['@nuxt/http', '@nuxtjs/apollo'],
// nuxt/http https://http.nuxtjs.org/API/options
http: {
baseURL: `${strapiBaseUri}/api`,
browserBaseURL: `${strapiBaseUri}/api`,
},
}
Create a new store named auth.js
and copy/paste the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// store/auth.js
import Cookies from 'js-cookie'
export const state = () => ({
user: {},
})
export const mutations = {
setUser(state, user) {
state.user = user
Cookies.set('user', JSON.stringify(user))
},
logout(state) {
state.user = null
Cookies.set('user', null)
},
}
export const getters = {
user: (state) => {
return state.user?.id
},
username: (state) => {
return state.user?.username
},
token: (state) => {
return state.user?.jwt
},
}
The newly created store, will store user information (id, username, and a JWT
which lets your users request your API as an authenticated one).
To make sure the user stay connected even after page reload, you will also use cookies. Create a new index.js
file inside your store
directory, and define a new nuxtServerInit
function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// store/index.js
import cookieparser from 'cookieparser'
export const actions = {
nuxtServerInit({ commit }, { req }) {
if (req && req.headers && req.headers.cookie) {
const parsed = cookieparser.parse(req.headers.cookie)
const user = (parsed.user && JSON.parse(parsed.user)) || null
const cart = (parsed.cart && JSON.parse(parsed.cart)) || []
commit('auth/setUser', user)
commit('cart/setItems', cart)
}
},
}
Since user sessions is defined and stored in the server, we can only access it through req.headers.cookie
. To add the authenticated user to our store, we parse browser cookies in page.
Now, let's create a registration page. Create a new auth
directory inside your pages
directory. Then create a new file register.vue
inside the new auth
directory.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// pages/auth/register.vue
<template>
<div class="uk-container uk-container-xsmall">
<h1 class="uk-heading-xsmall uk-margin-top">Sign up</h1>
<form @submit.stop.prevent="handleSubmit">
<div v-if="err" class="uk-alert-danger" uk-alert>
<a class="uk-alert-close" uk-close></a>
<p>{{ err.message }}</p>
</div>
<div class="uk-margin">
<label class="uk-form-label">
Username
<input v-model="username" class="uk-input" type="text" />
</label>
</div>
<div class="uk-margin">
<label class="uk-form-label">
Email
<input v-model="email" class="uk-input" type="email" />
</label>
</div>
<div class="uk-margin">
<label class="uk-form-label">
Password
<input v-model="password" class="uk-input" type="password" />
</label>
</div>
<button class="uk-button uk-button-primary uk-width-1-1" type="submit">
Register
</button>
</form>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
data() {
return {
username: '',
email: '',
password: '',
err: null,
}
},
methods: {
// Method that will register your users
async handleSubmit() {
try {
const { jwt, user } = await this.$http.$post('auth/local/register', {
username: this.username,
email: this.email,
password: this.password,
})
this.setUser({
jwt,
id: user.id,
username: user.username,
})
this.$router.push({
path: '/',
})
} catch (err) {
this.err = err.response?.data?.error
}
},
...mapMutations({
setUser: 'auth/setUser',
}),
},
}
</script>
In this page, you display a form which has three inputs: username, email and password. You also defined a method named handleSubmit
which uses the REST API to register the user before redirecting them to the home page.
Perfect! You are going to create a sign in page right now. Create a new login.vue
file inside your auth
directory.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
// pages/auth/login.vue
<template>
<div class="uk-container uk-container-xsmall">
<h1 class="uk-heading-xsmall uk-margin-top">Log In</h1>
<form @submit.stop.prevent="handleSubmit">
<div v-if="err" class="uk-alert-danger" uk-alert>
<a class="uk-alert-close" uk-close></a>
<p>{{ err.message }}</p>
</div>
<div class="uk-margin">
<label class="uk-form-label">
Email
<input v-model="email" class="uk-input" type="email" />
</label>
</div>
<div class="uk-margin">
<label class="uk-form-label">
Password
<input v-model="password" class="uk-input" type="password" />
</label>
</div>
<button class="uk-button uk-button-primary uk-width-1-1" type="submit">
Log In
</button>
</form>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
data() {
return {
email: '',
password: '',
err: null,
}
},
methods: {
async handleSubmit() {
try {
const { jwt, user } = await this.$http.$post('auth/local', {
identifier: this.email,
password: this.password,
})
this.setUser({
jwt,
id: user.id,
username: user.username,
})
this.$router.push({
path: '/',
})
} catch (err) {
this.err = err.response?.data?.error
}
},
...mapMutations({
setUser: 'auth/setUser',
}),
},
}
</script>
In this page, you display another form which has only two inputs: username and password. You also defined handleSubmit
method which uses the REST API to vertify the user before redirecting them to the home page.
Create a new Header.vue
component in components
directory.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// components/Header.vue
<template>
<nav class="uk-navbar uk-navbar-container" uk-navbar>
<div class="uk-navbar-left">
<NuxtLink class="uk-navbar-item uk-logo" to="/">Deliveroo clone</NuxtLink>
</div>
<div class="uk-navbar-right">
<ul v-if="username" class="uk-navbar-nav">
<li>
<button class="uk-button uk-button-link uk-navbar-toggle">
Shopping Cart
<span v-if="numberOfItems" class="uk-badge">{{
numberOfItems
}}</span>
</button>
<div class="uk-navbar-dropdown">
<Cart />
</div>
</li>
<li>
<button
class="uk-button uk-button-link uk-navbar-toggle"
@click="logout"
>
Log out
</button>
</li>
</ul>
<ul v-else class="uk-navbar-nav">
<li><NuxtLink to="/auth/login">Log In</NuxtLink></li>
<li><NuxtLink to="/auth/register">Register</NuxtLink></li>
</ul>
</div>
</nav>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
export default {
computed: {
...mapGetters({
username: 'auth/username',
numberOfItems: 'cart/numberOfItems',
}),
},
methods: {
...mapMutations({
logout: 'auth/logout',
}),
},
}
</script>
Using the <NuxtLink>
component, we create a new link to the home inside our Header component.
The header is a standalone component, which we will display on every page. It contains the login, logout and sign-up buttons. It also shows the shopping car, a dropdown which display a list of selected dishes, the sum and a checkout button.
Next we will extend the main layout by adding a layouts/default.vue
file. It will be used for all pages.
Create a new folder layouts
, we will use the <Nuxt>
component to include the page component, check Layouts directory for more informations.
Next, create a new file layouts``/default.vue
and then copy/paste the following code.
1
2
3
4
5
6
<template>
<div>
<Header />
<nuxt />
</div>
</template>
Reload your page and play with this new user system you just created! or try navigation to the following links:
That's it for the authentication! You will now have a Log In, Register, and Log Out links in your page header. 💵 In the next section, you will learn how to set up Stripe for checkout and create orders.
Pierre created Strapi with Aurélien and Jim back in 2015. He's a strong believer in open-source, remote and people-first organizations. You can also find him regularly windsurfing or mountain-biking!