Nuxt and Tailwind CSS Tutorial: How to build a modern restaurant site

Nuxt Tailwind CSS Tutorial thumnails.jpeg
By Nyore Chadere
Read time 9 min
Posted on 14 May 2025

In today's digital age, having a compelling online presence is crucial for restaurants. This tutorial will guide you through creating a professional restaurant website using two powerful technologies: Nuxt and Tailwind CSS, integrated with BCMS for content management.

You can view the finished application here: Home - Tastyyy - Tastyyy

Why Nuxt and Tailwind CSS?

Before diving into the implementation, let's understand why this tech stack is perfect for restaurant websites

Nuxt and Tailwind CSS benefits

Here are some key Nuxt advantages:

  • Server-side rendering (SSR) for better SEO performance, which will help local customers find your restaurant in search results

  • Faster page loads, which is critical for hungry and impatient customers

  • Simple routing system that makes the creation of menu pages, food pages and contact pages easy and seamless

Also, here are some of Tailwind's advantages:

  • A utility-first approach for rapid UI development will speed up design implementation

  • Consistent styling across all pages without complex CSS management

  • Easy to customize for your restaurant's brand identity and aesthetics

  • Responsive design out of the box

  • Minimal CSS in production will reduce your application bundle and hosting costs.

The need for a content management system

For the success of a restaurant website, you need a good system where you manage your restaurant postings, and these include your food, your coupons, and other things you need your users to see, Also, you will need a system that records the orders you get from your restaurant.

BCMS is an intuitive headless CMS that empowers developers with the ability to manage and model content with modern tech stacks.

By combining Nuxt.js and BCMS, we can create a powerful and user-friendly restaurant website platform that caters to the needs of both hungry customers and food vendors.

Prerequisites

Before starting this tutorial, make sure you have:

  • Node.js installed (version 16 or higher)

  • Basic knowledge of Vue.js

  • Familiarity with CSS concepts

  • Code editor of your choice

Project Setup

I’ll be using a restaurant website starter template that's already integrated with BCMS.

To get started, create a BCMS account.

After that, create a new project folder on your computer, navigate into that folder from your terminal, and paste in the command below:

npx @thebcms/cli create nuxt starter restaurant

Paste the command and follow the prompts

Running this command will:

  • Ask you to log in to the BCMS account you created through the terminal:

login prompt
login succssesful
  • Set up a new BCMS project

  • Populate it with content for the restaurant

  • Will clone the Nuxt Restaurant starter project locally

  • Create an .env file and update your project with the required BCMS configuration

After the successful run of that command, you can then cd into the project directory from your terminal and run:

npm install && npm run dev

After running the dev command, go to localhost:3000 on your browser and voila, you should see the restaurant website come to life:

home page

Great, but this begs the question: how did we get here? What is happening behind the scenes? How can you build this from scratch yourself?

I will now explain the processes behind building a dynamic website with Nuxt, TailwindCSS, and BCMS.

Let's start with BCMS.

How does BCMS work?

To explain how BCMS works, I will use the analogy of a bread baker.

A baker who wants to bake bread will need a pan, these pans can come in different shapes or sizes. After getting the pan, the baker mixes his flour and other ingredients that will give him the bread, puts it in the pan, and then in the oven.

When it is cooked, the baker collects the bread and turns it out; the bread has taken the shape of the pan. If the pan was to be long, the bread would be long; if it was short or round, the bread would be short or round.

BCMS uses the same pattern for dynamic content. In BCMS, you have:

Templates - This is the pan; in other words, this is the model for your content. Here, you define the structure for your content. For example, you specify if you want a title, an opening paragraph, or whatever information you want that particular template to have.

Templates can be either multi-entry or single-entry. For instance, a Home page template would be single-entry, while a Blog post template would be multi-entry.

Entries - These are the ingredients or the finished bread that takes the shape of the pan or the template. Simply put, entries are your information. If in your template you specified a field for the title, your entry is where you put that title, which is the dynamic content that you update.

Let’s see these in action.

Go to your BCMS dashboard and to the NuxtRestaurant project. On the administration tab, navigate to the template.

If you created a new BCMS project from scratch without using a starter, this page will be blank, and you will need to create a new template.

BCMS templates

Click on the template “Contact page” to view its content:

Contact page template

You can see from the image above the structure for the Contact page. It contains the title and the slug (these are automatically created for you by default). and then other fields with each having different properties as they’re needed.

These fields are created based on what you need on your website. If you navigate to the contact page on the website localhost:3000/contact, you’ll see these fields on display. A title, a location, and a map, which is an image(though it should be a reactive element).

Contact page

After getting the fields you need from either your website or the website design, you go ahead to BCMS to create a template and then design the template based on how your website is going to output them.

Now, let’s look at entries.

On the administration tab, go to entries and then click on the Contact Page.

contact entry

Here, you can edit the content you want displayed on your website. For example, you could change the title to another title of your choice, modify the description, and update the phone number to something else, all within the structure that your template allows you to use.

You can demonstrate this by editing any field there and then reloading your page to see the results.

But how are Nuxt.js and BCMS connected? Let's explore that next.

Querying BCMS data from Nuxt.js

  1. How to connect BCMS to Nuxt

  2. BCMS automatic Type allocation

  3. BCMS data fetching methods

  4. Exploring fetched data

  5. Using data and TailwindCSS styling

If you want to connect a new Nuxt website to BCMS, visit the BCMS documentation, which offers a step-by-step guide to integrating with BCMS. Since this project is already integrated with BCMS, I will not go over the process again. You can read more in the documentation.

Now, let’s see how to query data from the CMS.

TypeScript In Nuxt.js

The Restaurant code starter uses TypeScript; all starters in the BCMS repo use TypeScript. To get the best out of TypeScript, you need to define TypeScript types to model the content you’re expecting to query from the CMS. BCMS automatically does this when you connect to the BCMS instance and run the development server.

In your code editor, navigate to your created project folder and then to bcms > types > ts > entry. There, you will find type definitions for all the templates in your BCMS project.

If you should create a new template in your BCMS project, BCMS automatically gets the type definitions and updates them in this folder when you restart the dev server. So you don’t have to worry about type definitions at all, BCMS automatically handles that for you.🎉

This happens because of the command in the package.json

 "dev": "bcms --pull types --lng ts && nuxt dev",
9.Contact page types.png

With these types defined for you, you can go ahead now to use them when fetching data.

Data fetching

In Nuxt, you can either fetch data in your components or you can fetch data using server routes. The code starter uses the server routes approach because it makes the component cleaner and separates UI logic and application logic.

BCMS provides helper functions to query data from BCMS. These are:

getAll: Gets all entries in a template. Useful for restaurant menu items.

getById: Gets a single entry using its ID

getBySlug : Gets a single entry using the slug field

Let’s see one of these in action.

In your code editor, navigate to server > api > contact-page.ts where you will find the code that fetches the contact page entry from BCMS. Let’s break it down bit by bit:

At the topmost, you have the BCMS core configuration objects imported:

import { ClientConfig } from '@thebcms/client';
import { bcms } from '~/bcms-client';

Followed by the type definitions for the Contact page. Since it is a typescript project, the types must be properly defined and used, and as you now know, BCMS automatically creates those types for you so all you have to do is import them like so:

import { ContactPageEntry, ContactPageEntryMetaItem } from '~/bcms/types/ts';

After the imports, the response object is defined, which contains the response of the query in the meta object and the BCMS object in its own object in case the components want to use it:

export type ContactPageResponse = {
   meta: ContactPageEntryMetaItem;
   bcms: ClientConfig;
};

After that, the handler for the server route, which simply runs the code when the api is requested,d is initialized, and there you have the code block that fetches the data from BCMS:

const contactPageEntry = (await bcms.entry.getBySlug(
   'contact',
   'contact-page',
)) as ContactPageEntry;

The contactPageEntry uses the BCMS getBySlug helper function to browse through the entries and then retrieves the first item it gets that has the slug contact or contact-page. It is defined so in case the user mistakenly changes the slug on the BCMS dashboard. After that, the response is awaited to make sure it gets fulfilled before it is assigned to the variable. The value is then mapped to the ContactPageEntry type.

The code blocks after this simply extract the data from the value and then create the final response object:

const contactPageMeta = contactPageEntry.meta.en as ContactPageEntryMetaItem;
const res: ContactPageResponse = {
   meta: contactPageMeta,
   bcms: bcms.getConfig(),
};
return res;

To see this Server route in action, navigate to the pages folder of your application in your code editor and then to the contact folder, and then index.vue. pages > contact > index.vue

In the script tag, first of all, the ContactPageResponse is imported:

import type { ContactPageResponse } from '~/server/api/contact-page';

After that, the nuxt useFetch composable is utilized to fetch data from the server route, and then the server route in turn fetches data from the BCMS.

const { data, error } = await useFetch<ContactPageResponse>('/api/contact-page');
if (!data.value || error.value) {
   throw createError({
      statusCode: 404,
      statusMessage: 'Page Not Found',
   });
}

Add a console.log(data.value) below the if block to view the data in the console.

In your console, you should see the data logged.

10.Contact page response.png

With your data now available to you, you can use it any way you want in the component. For example as it is used on the component to set the SEO details for the page.

useHead(() =>
   setOgHead({
      title: `${data.value?.meta.seo?.title || data.value?.meta.title} - Tastyyy`,
      description: data.value?.meta.seo?.description,
   }),
)

In the code above, Nuxtjs useHead composable was used to set the OG head title and description details, which are obtained from the data object.

Using Tailwind CSS Styling

When working with Nuxt, like in this case, you need packages like tailwind, and in other cases, more packages like Pinia for state management. Nuxt provides you with Nuxt Modules, which help you easily incorporate these packages into your application. Let’s see how you can install the TailwindCSS module for Nuxt.

Note: This starter Project already has Nuxt installed using the Tailwind CSS Nuxt module, so you do not need to reinstall it. But this part of the tutorial is designed to teach you how you can install Tailwind CSS from scratch in a new project.

On the homepage of the TailwindCSS Nuxt module, there is a command that adds TailwindCSS to your project within seconds. Simply copy this command and paste it into your terminal for installing TailwindCSS:

npx nuxi module add tailwindcss

After installation, you can add the module to your nuxt.config file in the modules section, like so:

modules: ['@nuxtjs/tailwindcss']

At this point, everything will be working fine, without any extra steps. But you can customize your TailwindCSS themes and styling by creating a tailwind.config.js or .ts file in your root folder, where you can set themes like it is done in the NuxtRestaurant starter.

/** @type {import('tailwindcss').Config} */
export default {
    content: [
        './layouts/**/*.vue',
        './pages/**/*.vue',
        './components/**/*.vue',
        './error.vue',
    ],
    theme: {
        extend: {
            colors: {
                appAccent: '#A48A63',
                appBody: '#F4F2E8',
                appText: '#272424',
                appGray: {
                    100: '#E0E0E0',
                    200: '#6A6A75',
                    300: '#63635F',
                    400: '#8F8E88',
                    500: '#9C9090',
                    600: '#786F6F',
                    700: '#454040',
                },
            },
            container: {
                center: true,
                padding: {
                    DEFAULT: '1.5rem',
                    lg: '2rem',
                },
                screens: {
                    sm: '640px',
                    md: '768px',
                    lg: '1024px',
                    xl: '1280px',
                    '2xl': '1440px',
                },
            },
            fontFamily: {
                Helvetica: ['Helvetica', 'sans-serif'],
                Gloock: ['Gloock', 'sans-serif'],
            },
        },
    },
    plugins: [],
};

Great, with this code above, you have successfully integrated your BCMS data into your Nuxt application and configuring Tailwind CSS to beautify it. If you navigate to localhost:3000/contact you should see your page beautifully styled.

11.Contact Page.png

Now, let’s get this project live.

Deploy your Nuxt Application

You can deploy your Nuxt application on different hosting providers, you can find a list of these hosting providers here on the official Nuxt website.

For this application, I will deploy it on Vercel using the git method. Here are the steps to deploy a Nuxt application on Vercel:

  • First, create a git repo on either Github, BitBucket, or Gitlab and then push the source code to it.

  • Create a Vercel account if you don’t have one already.

On your dashboard, click on “Add New” and select Project. You will have the option to connect to your git repository at this point. After authenticating and connecting, click on import on the project that you pushed to your git provider to import that project onto Vercel.

  • Vercel will automatically detect that you’re using Nuxt and Nitro and will automatically set the frameworks preset.

import project
  • Click on the Environment Variables tab, then copy and paste your BCMS config variables from your .env file.

.env file
  • Click on the Deploy button, and you will be greeted with a successful message.

deployment

Here is the URL for the project that was just deployed on Vercel.

TIP: If the deploy fails, check the build logs Vercel will generate for you, and you will get an error message that will help you to debug.

Conclusion

Since you have understood how to create a website with Nuxt.js, TailwindCSS, and BCMS and have seen it in action in this Restaurant starter, why not take it a step further and create a new template named FAQ, where you write and answer the frequently asked questions users of your restaurant throw at you. You will first need to think about what you need on that page(don’t forget SEO), and then you will make the template, add the necessary fields, and then create the entry.

After that, you create the faq page in the Nuxt project, and then query the data using the server route method talked about in this tutorial, get the data, and then style the page using Tailwind CSS.

Doing this should take a few minutes and will give you more confidence in building and shipping with BCMS and Nuxt.js.

It takes a minute to start using BCMS

Gradient

Join our Newsletter

Get all the latest BCMS updates, news and events.

You’re in!

The first mail will be in your inbox next Monday!
Until then, let’s connect on Discord as well:

Join BCMS community on Discord

By submitting this form you consent to us emailing you occasionally about our products and services. You can unsubscribe from emails at any time, and we will never pass your email to third parties.

Gradient