Skip to content

Commit 2facf9d

Browse files
Nuxt tutorial (#1841)
1 parent 429af7a commit 2facf9d

File tree

1 file changed

+52
-99
lines changed

1 file changed

+52
-99
lines changed

examples/tutorials/nuxt.md

Lines changed: 52 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ You can find the code for this project in this
2525

2626
## Scaffold a Nuxt app with Deno
2727

28-
We can create a new Nuxt project using deno like this:
28+
We can create a new Nuxt project using Deno like this:
2929

3030
```bash
3131
deno -A npm:nuxi@latest init
@@ -60,9 +60,7 @@ First, our
6060
[dinosaur data](https://github.com/denoland/examples/blob/main/with-nuxt/server/api/data.json)
6161
will live within the server directory as `server/api/data.json`:
6262

63-
```json
64-
// server/api/data.json
65-
63+
```json title="server/api/data.json"
6664
[
6765
{
6866
"name": "Aardonyx",
@@ -76,7 +74,7 @@ will live within the server directory as `server/api/data.json`:
7674
"name": "Abrictosaurus",
7775
"description": "An early relative of Heterodontosaurus."
7876
},
79-
...
77+
...etc
8078
]
8179
```
8280

@@ -87,35 +85,21 @@ would come from a database.
8785
> to [a variety of databases](https://docs.deno.com/runtime/tutorials/connecting_to_databases/) and [even use ORMs like Prisma](https://docs.deno.com/runtime/tutorials/how_to_with_npm/prisma/) with
8886
> Deno.
8987
90-
Next, let’s add type definitions for our dinosaur data. We’ll put it in a new
91-
folder, `types`:
92-
93-
```tsx
94-
// types/index.ts
95-
96-
export interface Dino {
97-
name: string;
98-
description: string;
99-
}
100-
```
101-
102-
We’ll create two API routes to serve the following:
88+
This app will have two API routes. They will serve the following:
10389

10490
- the full list of dinosaurs for an index page
10591
- individual dinosaur information for an individual dinosaur page
10692

10793
Both will be `*.get.ts` files, which Nuxt automatically converts to API
108-
endpoints to respond to GET requests.
94+
endpoints to respond to `GET` requests.
10995
[The filename convention determines both the HTTP method and the route path](https://nuxt.com/docs/guide/directory-structure/server#matching-http-method).
11096

11197
The initial `dinosaurs.get.ts` is fairly simple and uses
11298
[`defineCachedEventHandler`](https://nitro.build/guide/cache) to create a cached
11399
endpoint for better performance. This handler simply returns our full dinosaur
114100
data array without any filtering:
115101

116-
```tsx
117-
// server/api/dinosaurs.get.ts
118-
102+
```tsx title="server/api/dinosaurs.get.ts"
119103
import data from "./data.json" with { type: "json" };
120104

121105
export default defineCachedEventHandler(() => {
@@ -126,12 +110,10 @@ export default defineCachedEventHandler(() => {
126110
The `GET` route for the individual dinosaur has a little more logic. It extracts
127111
the name parameter from the event context, performs case-insensitive matching to
128112
find the requested dinosaur, and includes proper error handling for missing or
129-
invalid dinosaur names. To pass the name parameter, let’s name this route as
130-
`[name].get.ts`:
131-
132-
```tsx
133-
// server/api/dinosaurs/[name].get.ts
113+
invalid dinosaur names. We'll create a `dinosaurs` directory, then to pass the
114+
name parameter, we'll make a new file named `[name].get.ts`:
134115

116+
```tsx title="server/api/dinosaurs/[name].get.ts"
135117
import data from "../data.json";
136118

137119
export default defineCachedEventHandler((event) => {
@@ -159,37 +141,38 @@ export default defineCachedEventHandler((event) => {
159141
});
160142
```
161143

162-
Awesome. When we run the server with `deno task dev` and point our browser to
163-
`localhost:3000/api/dinosaurs`, we can see the raw JSON response showing all of
164-
the dinosaurs:
144+
Run the server with `deno task dev` and visit
145+
[http://localhost:3000/api/dinosaurs](http://localhost:3000/api/dinosaurs) in
146+
your browser, you should see the raw JSON response showing all of the dinosaurs!
165147

166148
![Setting up API](./images/how-to/nuxt/nuxt-1.webp)
167149

168-
You can also retrieve data for a single dinosaur by going to
169-
`localhost:3000/api/dinosaurs/aardonyx`.
150+
You can also retrieve data for a single dinosaur by visiting a particular
151+
dinosaur name, for example:
152+
[http://localhost:3000/api/dinosaurs/aardonyx](http://localhost:3000/api/dinosaurs/aardonyx).
170153

171154
![Setting up API](./images/how-to/nuxt/nuxt-2.webp)
172155

173-
Next, let’s setup the frontend with Vue to display the index page and each
156+
Next, we'll setup the frontend with Vue to display the index page and each
174157
individual dinosaur page.
175158

176-
## Setup Vue frontend
159+
## Setup the Vue frontend
177160

178-
We want to set up two pages within our app:
161+
We want to set up two pages within the app:
179162

180-
- An index page which will list all our dinosaurs
181-
- An individual dinosaur page showing more information about our selected
163+
- An index page which will list all of the dinosaurs
164+
- An individual dinosaur page showing more information about the selected
182165
dinosaur.
183166

184-
Let’s first create the index page. Since Nuxt uses
185-
[file-system routing](https://nuxt.com/docs/getting-started/routing), let’s
186-
create a `pages` directory and within that, our index page at `pages/index.vue`.
167+
First, create the index page. Nuxt uses
168+
[file-system routing](https://nuxt.com/docs/getting-started/routing), so we will
169+
create a `pages` directory in the root, and within that an index page called
170+
`index.vue`.
171+
187172
To get the data, we’ll use the `useFetch` composable to hit the API endpoint we
188173
created in the previous section:
189174

190-
```tsx
191-
// pages/index.vue
192-
175+
```tsx title="pages/index.vue"
193176
<script setup lang="ts">
194177
const { data: dinosaurs } = await useFetch("/api/dinosaurs");
195178
</script>
@@ -212,17 +195,15 @@ const { data: dinosaurs } = await useFetch("/api/dinosaurs");
212195
</template>
213196
```
214197

215-
For our next page that shows information for each dinosaur, let’s create a
216-
dynamic page: `pages/[name].vue`. This page uses Nuxt's
198+
For the page that shows information on each dinosaur, we'll create a new dynamic
199+
page called `[name].vue`. This page uses Nuxt's
217200
[dynamic route parameters](https://nuxt.com/docs/getting-started/routing#route-parameters),
218201
where the `[name]` in the filename can be accessed in JavaScript as
219202
`route.params.name`. We’ll use the `useRoute` composable to access the route
220203
parameters and `useFetch` to get the specific dinosaur's data based on the name
221204
parameter:
222205

223-
```tsx
224-
// pages/[name].vue
225-
206+
```tsx title="pages/[name].vue"
226207
<script setup lang="ts">
227208
const route = useRoute();
228209
const { data: dinosaur } = await useFetch(
@@ -248,9 +229,7 @@ root of the directory to serve our application’s root component. We’ll use
248229
page structure and [`NuxtPage`](https://nuxt.com/docs/api/components/nuxt-page)
249230
for dynamic page rendering:
250231

251-
```tsx
252-
// app.vue
253-
232+
```tsx title="app.vue"
254233
<template>
255234
<NuxtLayout>
256235
<div>
@@ -268,8 +247,8 @@ for dynamic page rendering:
268247
</template>;
269248
```
270249

271-
Let’s run our server with `deno task dev` and see how it looks at
272-
`localhost:3000`:
250+
Run the server with `deno task dev` and see how it looks at
251+
[http://localhost:3000](http://localhost:3000):
273252

274253
<figure>
275254

@@ -286,9 +265,7 @@ First, we'll set up a layout which will provide a consistent structure across
286265
all pages using Nuxt's layout system with
287266
[slot-based](https://vuejs.org/guide/components/slots) content injection:
288267

289-
```tsx
290-
// layouts/default.vue
291-
268+
```tsx title="layouts/default.vue"
292269
<template>
293270
<div>
294271
<slot />
@@ -303,48 +280,15 @@ for some basic design, so we need to install those dependencies:
303280
deno install -D npm:tailwindcss npm:@tailwindcss/vite
304281
```
305282

306-
Then, we're going to update our `nuxt.config.ts` file by adding the
307-
`@tailwindcss/vite` plugin to our Nuxt configuration as a Vite plugin.
308-
309-
```tsx
310-
// nuxt.config.ts
311-
312-
import tailwindcss from "@tailwindcss/vite";
313-
314-
export default defineNuxtConfig({
315-
compatbilityDate: "2025-05-15",
316-
devtools: { enabled: true },
317-
vite: {
318-
plugins: [
319-
tailwindcss(),
320-
],
321-
},
322-
});
323-
```
324-
325-
Next, let’s create a new css file, `assets/css/main.css`, and add an import
326-
`@import` that imports tailwind, as well as the tailwind utilities.
327-
328-
```tsx
329-
// assets/css/main.css
330-
@import "tailwindcss";
331-
332-
@tailwind base;
333-
@tailwind components;
334-
@tailwind utilities;
335-
```
336-
337-
The only other thing we'll need to do is update our `nuxt.config.ts` file to
338-
configure our Nuxt application for Deno compatibility, enable development tools,
339-
and set up Tailwind CSS.
340-
341-
```tsx
342-
// nuxt.config.ts
283+
Then, we're going to update the `nuxt.config.ts`. Import the Tailwind dependency
284+
and configure the Nuxt application for Deno compatibility, We'll enable
285+
development tools, and set up Tailwind CSS:
343286

287+
```tsx title="nuxt.config.ts"
344288
import tailwindcss from "@tailwindcss/vite";
345289

346290
export default defineNuxtConfig({
347-
compatbilityDate: "2025-05-15",
291+
compatibilityDate: "2025-05-15",
348292
devtools: { enabled: true },
349293
nitro: {
350294
preset: "deno",
@@ -363,9 +307,20 @@ export default defineNuxtConfig({
363307
});
364308
```
365309

366-
## Running Our Application
310+
Next, create a new css file, `assets/css/main.css`, and add an import `@import`
311+
that imports tailwind, as well as the tailwind utilities:
367312

368-
We can then run our application using:
313+
```tsx title="assets/css/main.css"
314+
@import "tailwindcss";
315+
316+
@tailwind base;
317+
@tailwind components;
318+
@tailwind utilities;
319+
```
320+
321+
## Running the application
322+
323+
We can then run the application using:
369324

370325
```bash
371326
deno task dev
@@ -381,9 +336,7 @@ This will start the app at localhost:3000:
381336

382337
And we’re done!
383338

384-
## Next steps
385-
386-
Next steps for a Nuxt app might be to add authentication using the
339+
🦕 Next steps for a Nuxt app might be to add authentication using the
387340
[Nuxt Auth](https://auth.nuxtjs.org/) module, implement state management with
388341
[Pinia](https://pinia.vuejs.org/), add server-side data persistence with
389342
[Prisma](https://docs.deno.com/examples/prisma_tutorial/) or

0 commit comments

Comments
 (0)