DEV Community

Cover image for Integrate Strapi on Nuxt
Thomas Bnt β˜•
Thomas Bnt β˜• Subscriber

Posted on • Originally published at thomasbnt.dev

Integrate Strapi on Nuxt

What is Strapi?

Strapi is a headless CMS, which means you can create your own API and distribute it without any constraints.

Strapi - Open source Node.js Headless CMS πŸš€

Strapi is the next-gen headless CMS, open-source, javascript, enabling content-rich experiences to be created, managed and exposed to any digital device.

favicon strapi.io

Backend with Strapi

Installing Strapi

Before installing the CMS, please make sure you have Node.js v20.



npx create-strapi-app@latest my-project


Enter fullscreen mode Exit fullscreen mode

Or with yarn :



yarn create strapi-app my-project --quickstart


Enter fullscreen mode Exit fullscreen mode

With this command, you will follow a simple process to install it. It couldn't be simpler. For the rest, we're using SQLite (by default) in this example, but you're free to install whatever database you want.



thomasbnt@thomasbnt:~/lab$ yarn create strapi-app my-project --quickstart
yarn create v1.22.19
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...

success Installed "create-strapi-app@4.19.0" with binaries:
      - create-strapi-app
Creating a quickstart project.
Creating a new Strapi application at /lab/my-project.
Creating files.
Dependencies installed successfully.
Initialized a git repository.

Your application was created at /lab/my-project.

Available commands in your project:

  yarn develop
  Start Strapi in watch mode. (Changes in Strapi project files will trigger a server restart)

  yarn start
  Start Strapi without watch mode.

  yarn build
  Build Strapi admin panel.

  yarn strapi
  Display all available commands.

You can start by doing:

  cd /lab/my-project
  yarn develop

Running your Strapi application.

> my-project@0.1.0 develop
> strapi develop

β ‹ Building build context
β ™ Building build context[INFO] Including the following ENV variables as part of the JS bundle:
    - ADMIN_PATH
    - STRAPI_ADMIN_BACKEND_URL
    - STRAPI_TELEMETRY_DISABLED
βœ” Building build context (100ms)
βœ” Creating admin (10071ms)
β Έ Loading Strapi[2024-01-27 18:49:09.061] info: The Users & Permissions plugin automatically generated a jwt secret and stored it in .env under the name JWT_SECRET.
βœ” Loading Strapi (2075ms)
βœ” Generating types (320ms)

 Project information

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Time               β”‚ Sat Jan 27 2024 18:49:10 GMT+0100 (Central Euro… β”‚
β”‚ Launched in        β”‚ 2405 ms                                          β”‚
β”‚ Environment        β”‚ development                                      β”‚
β”‚ Process PID        β”‚ 19885                                            β”‚
β”‚ Version            β”‚ 4.19.0 (node v20.2.0)                            β”‚
β”‚ Edition            β”‚ Community                                        β”‚
β”‚ Database           β”‚ sqlite                                           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

 Actions available

One more thing...
Create your first administrator πŸ’» by going to the administration panel at:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ http://localhost:1337/admin β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

[2024-01-27 18:49:11.419] http: GET /admin (12 ms) 200
[2024-01-27 18:49:11.454] http: GET /admin/runtime~main.b145af60.js (6 ms) 200
[2024-01-27 18:49:11.463] http: GET /admin/main.5eaa19e8.js (2 ms) 200
[2024-01-27 18:49:11.827] http: GET /admin/project-type (2 ms) 200
[2024-01-27 18:49:11.846] http: GET /admin/6707.d7b87269.chunk.js (2 ms) 200
[2024-01-27 18:49:11.983] http: GET /admin/6538.27d4c381.chunk.js (3 ms) 200
[2024-01-27 18:49:11.984] http: GET /admin/9719.fe70b828.chunk.js (2 ms) 200
[2024-01-27 18:49:11.984] http: GET /admin/1025.2d854ef2.chunk.js (2 ms) 200
[2024-01-27 18:49:11.989] http: GET /admin/5019.0d8113a1.chunk.js (3 ms) 200
[2024-01-27 18:49:11.990] http: GET /admin/4944.c9cc5f7f.chunk.js (3 ms) 200
[2024-01-27 18:49:11.991] http: GET /admin/9170.6aa61d26.chunk.js (3 ms) 200
[2024-01-27 18:49:11.994] http: GET /admin/1727.8847f948.chunk.js (1 ms) 200
[2024-01-27 18:49:12.048] http: POST /admin/renew-token (9 ms) 400
[2024-01-27 18:49:12.051] http: GET /admin/init (16 ms) 200
[2024-01-27 18:49:12.054] http: GET /admin/users/me (18 ms) 401
[2024-01-27 18:49:12.144] http: GET /admin/3067.4f4141cb.chunk.js (1 ms) 200
[2024-01-27 18:49:12.149] http: GET /admin/telemetry-properties (2 ms) 401
[2024-01-27 18:49:12.354] http: GET /admin (2 ms) 200
[2024-01-27 18:49:12.588] http: GET /admin/project-type (1 ms) 200
[2024-01-27 18:49:12.686] http: GET /admin/init (2 ms) 200
[2024-01-27 18:49:12.811] http: GET /favicon.ico (0 ms) 200


Enter fullscreen mode Exit fullscreen mode

You have all the documentation available.

After installing everything and the dependencies, the server starts automatically as you can see above. However, if this has not been done, do yarn develop.

Create your account on the dashboard

When you go to http://localhost:1337 for the first time, you will be asked to create a Super Admin account.

Strapi registration page for the first Super Admin account with text fields such as first name, last name, email address and password

Youhou! You've got access to Strapi! βœ¨πŸš€

Strapi Dashboard with menu on the left and content in the centre

Creating the Collection

In this example, we're going to create a collection to display the latest updates from a Discord robot, so that we can display it wherever we want, in this case, on the website under Nuxt but also with a Slash command on the Discord platform through the robot!

Go to Content-Type Builder β†’ Collections Types β†’ Create new collection type.

Creation of a type collection in Strapi

We're going to give it a proper name "ChangelogMrRobotApp" (here Mr. Robot refers to the name of the robot). Then create fields by clicking on the Add new field. button.
In my case, I simply want to display :

  • The title
  • The version
  • The release date
  • The content of the version
  • The slug
  • And a banner, which is optional

Caution
The date of creation and publication is ALREADY taken into account in Strapi, so there's no need to add this date field to your Collections!

Then we fill in all these fields in the Content Manager tab. Then we can move on to the front!

Creating a sample collection in Strapi

Integration on the front end with Nuxt

I'm using Nuxt for the front end, because the robot's website uses this framework. But you're free to arrange it as you see fit. It's just a fetch request and some JavaScript.

Creating the API token

Before continuing with the code, we're going to create an API Token, Settings β†’ API Tokens β†’ Add new API Token. What we want is simply to GET the Collection, without having any other permissions. It will allow us to retrieve information from the API. This token should be private.

  • Token type as "Read-only
  • Token duration as "Unlimited
  • And permissions only on "find" and "findOne" on the Collection

Strapi page for creating a new API token, including name, description, token duration, type (read-only in this case) and permissions (here only the ChangelogMrRobotApp Collection)

Retrieving data with the call API

Now we can retrieve the data from the Collection from the Strapi API. Since the content is in Markdown, we need to perform an additional step, that of transforming the Markdown text into HTML. To do this, I'm using the markdown-it package.

First function: Fetch data from the API

Simply use useFetch from Nuxt. We get our data, and we can put it in a ref.



const config = useRuntimeConfig();
let changelogs = ref([]);

await useFetch(`${config.public.backendStrapiUrl}changelogs-mr-robot-app?populate=*&sort[0]=version:desc`, {
  headers: {
    Authorization: `Bearer ${config.public.backendStrapiPublicAPIToken}`
  }
}).then((response) => {
  changelogs = response.data._value;
});


Enter fullscreen mode Exit fullscreen mode
  • Here, config.public.backendStrapiUrl contains the URL of Strapi with the endpoint API to retrieve the Collection of changelogs, populated (see what the populate is) and sorted by version on the way down.
  • And config.public.backendStrapiPublicAPIToken, as its name suggests, is your Token!

You get an array with everything you want. Magic!

Transforming Markdown content β†’ HTML

With markdown-it, we'll be able to work even more magic. Install the package, and add it to the component/page.



import MarkdownIt from "markdown-it";
const md = new MarkdownIt();

changelogs.data.forEach((changelog) => {
  changelog.attributes.content = md.render(changelog.attributes.content);
});

function formatDate(date) {
  const options = { year: "numeric", month: "long", day: "numeric" };
  return new Date(date).toLocaleDateString("fr", options);
}


Enter fullscreen mode Exit fullscreen mode

I've added a function called formatDate, which simply sets the date to the correct format.

Result on one page

And now... (drum roll πŸ₯)... you need to integrate this part into your HTML body!



<article v-for="l in changelogs.data" :key="l.id" v-show="changelogs">
  <NuxtLink :to="'#' + l.attributes.slug">
    <h3 class="changelog_title" v-if="l.attributes.title" :id="l.attributes.slug">{{ l.attributes.title }}</h3>
  </NuxtLink>
  <div class="changelog_infos">
    <div
      v-if="l.attributes.releasedAt">
      <Icon name="lucide:calendar" />
      Sorti le {{ formatDate(l.attributes.releasedAt) }}
    </div>
    β€”
    <div v-if="l.attributes.version">v.{{ l.attributes.version }}</div>
  </div>
  <div v-html="l.attributes.content" v-if="l.attributes.content"></div>
</article>


Enter fullscreen mode Exit fullscreen mode

With a little CSS, we render it with style, and here's the result!

Result of the code with the changelogs, integrating the Strapi API call, and using the markdown-it package to transform markdown into HTML

This web page is available on mrrobot.app/changelog if you're curious. πŸš€

Conclusion

I discovered Strapi quite a while ago. And I hadn't created anything with it, until I had a project, where I suggested it. I've loved it ever since. For its ease of use, its documentation, its API management, and above all, its ease of integration with any framework.

This post is available in French language β†’

Top comments (2)

Collapse
 
hendisantika profile image
Hendi Santika

Nice article

Collapse
 
thomasbnt profile image
Thomas Bnt β˜•

Thank you! πŸ™Œ