Web scraper in Nuxt 3 - part III - Displaying the results on frontend
Tags: nuxt, vue, typescript, webdev
Published: 2023-11-12 14:08:52

Welcome back to my tutorial about web scraping with Nuxt 3. This is the third part of the four volume series:

1. [Introduction and setting up](https://dev.to/aloisseckar/web-scraper-in-nuxt-3-part-i-introduction-and-setting-up-4bb5)
2. [Backend scraping service in Nuxt](https://dev.to/aloisseckar/web-scraper-in-nuxt-3-part-ii-backend-scraping-service-in-nuxt-2k6c)
3. **Displaying the results on frontend**
4. [Going live on Netlify](https://dev.to/aloisseckar/web-scraper-in-nuxt-3-part-iv-going-live-on-netlify-1i8p)

In the previous article we created a working scraper, that extracts data about last available number on [JEP Index](https://openjdk.org/jeps/0). We are producing JSON data, now we will incorporate them into a webpage.

## Components in Nuxt

Hope you still rememeber the ending of first tutorial as we talked about `app.vue` file. Now it is time to get back to it.

If you used [Nuxt official starter](https://nuxt.com/docs/getting-started/installation), it displays fancy “Welcome to Nuxt!” page, I you followed my [`nuxt-starter`](https://github.com/AloisSeckar/nuxt-starter), it contains just some plain HTML text. Either way all the contents are wrapped in special `<template>` tag. This is how we tell what to render on the actual page in Vue.js.

Whenever you have `.vue` file in your Vue project, it is considered a “component”, or also **SFC** - _Sigle File Component_. The `app.vue` is traditionally the entry point into Vue application. For simple apps like ours we won’t be needing any other components. In more complex projects there can be many more of them and you can nest them inside each other to build what you need.

Since this is shouldn't a comprehensive Vue/Nuxt tutorial, I won’t be digging much deeper. Let me just say, that components have this already mentioned `<template>` section to handle what to display and often also acompanied with a `<script>` section to prepare the data to display and/or to control how the content is being displayed.

## Getting data from backend

To tell Nuxt to grab data from your backend, add following code into `app.vue`:

```vue
<script setup lang="ts">
import type { JEPData } from './server/api/peek'

const { data: jepData } = await useFetch<JEPData>('/api/peek')
</script>
```
 
_Side note: I usually put the `<template>` part first and the `<script>` section beneath that, but you may also see the other way around. The important thing is to pick one style and keep using it._

You may notice two attributes of `<script>` tag. The `setup` is a special construct introduced in Vue 3 and it is generally [recommended to use it](https://vuejs.org/api/sfc-script-setup.html). I can’t think of any use case, where I would have used `<script>` without `setup`. So basically just put it there whenever you'll be writing a `.vue` component. The `lang=”ts”` part on the other hand tells the compiler that the contents inside will be in TypeScript and not just plain old JavaScript.

The actual code only has two active lines. The `import type` is used to load the type info about the data we expect to be returned. We have defined (and exported it) in `/server/api/peek.ts` in previous tutorial. This is another TS feature and providing you have your IDE properly configured, it will help you with autocompleting attribute names and gives you warnings about incorrectly used values (like trying to assign number into a value declared as string or accessing a value that is not declared on the type).

The second line is the important one. Here we use Nuxt’s built-in [`useFetch`](https://nuxt.com/docs/api/composables/use-fetch) function that can be used for super simple data fetching on the client’s side. It is basically a wrapper around the [`$fetch`](https://nuxt.com/docs/api/utils/dollarfetch) function we already have used to fetch JEP Index data. The interesting concept is the left side of the assignment. The `useFetch` returns a more complex object, but for now we only want the `data` part of it. Applying `{}` brackets like this is called "object destructuring" in JavaScript. It allows us to grab only what we want and ignore the rest of the object. I could have been happy with the generic name `data`, but to make clearer what the data actually represent, I am also reassigning the identifier to `jepData` – from now on the contents fetched from our backend will be known as `jepData` to the rest of the component.

Let me just point out that as simply as that we managed to make our frontend cooperating with backend. Traditionally you have separate apps running on frontend and completely different programs for backend operations. But in Nuxt we can do both in one and just integrate to outside services like database or file storage.

This might or might not be a good thing depending on your goals. You are in risk of creating a large monolithic application, a thing modern developers try to avoid. But a lot of websites are relatively small in scope and having separated frontend and backend brings in unnecessary complexity and maintenance issues. And nothing really holds you back from using isolated Nuxt instances as microservices, or maybe "micromodules". Check out [this video from recent Nuxt Nation 2023 conference](https://www.youtube.com/watch?v=FiPBKZTIDEQ), where Nuxt team member Jakub Andrzejewski talks about this topic. 

## Rendering dynamic data

Back in our demo app, we now have the data and we can display them inside the template. 

Vue uses “double mustache syntax” (`{{ value }}`) to allow evaluating JavaScript expression inside its templates. So, we can write for example:

```vue
<div>Current last JEP: {{ jepData?.lastJEP }}</div>
```

This will yield the fetched number of last JEP (**463** at the time of writing this article). Variable `jepData` can be used because it was defined within `<script setup>` section and thus it is automatically available inside `<template>` as well. Notice the optional chaining though to avoid situations when `useFetch` would fail to get the data back from our backend.

Armed with this knowledge, you could continue with integrating the rest of fetched data into the page. Any HTML tags can be used inside `<template>` sectio. CSS styles can also be applied, but since it is another vast topic, let me just link a [dedicated tutorial article](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling) for those, who would like to dive in.

## Conclusion

I made a couple of updates inside my `app.vue` (with no CSS) as well. If you want to see the final outcome, check the GitHub repository - [https://github.com/AloisSeckar/JEPeek](https://github.com/AloisSeckar/JEPeek).

You can also display the live version of this micro-project at [https://jepeek.netlify.app](https://jepeek.netlify.app). With that I took a step forward to show you the outcome of the final part of this tutorial series - [Going live on Netlify](https://dev.to/aloisseckar/web-scraper-in-nuxt-3-part-iv-going-live-on-netlify-1i8p).

As always, if you had trouble understanding anything in this article or you are curious to learn more about topics we only touched briefly here, reach me out in the comments.

And if you like to learn more about Nuxt basics in general, I am working on [demos-nuxt GitHub repository](https://github.com/AloisSeckar/demos-nuxt) with growing number of demo applications.