Our Writing

Build a real-time game with Supabase and Vue.


Jozef /

In this tutorial series, we'll build a real-time game using Supabase and Vue with loads of cool little details and polish using a cyberpunk style design. For the first part of the tutorial, we will set up our project and implement some of the basic styles.

Tic Tac What?

We've been following Supabase for a while and wanted to give it a try. So what better way than to build a polished, real-time game using our favourite frontend framework, Vue?

We'll be creating a new spin on the classic tic-tac-toe game. The twist is that each player has a limited time to place their O or X. Players can create a new game and invite a friend to play using a unique code. Then, they'll compete against each other in a best-of-five series in real time.

You can try it out here (if you've got no one to play it with open it in two browser tabs): https://tic-tac-go.pixelhop.io

This project provides the perfect opportunity to test out Supabase's real-time functionality. We'll be working from the Figma designs and bringing them to life with lots of cool animations to make the game juicy and fun. You'll learn a lot about SVG animation, Supabase, and Vue!

If you want an overview of what we are building, check out this video:

You can see the Figma designs here 👉: Tic Tac Go Designs

Finally, if you are the sort of person that likes to dig around themselves you can find the completed code for the project below!

Get the code

Setting up the perfect Vue 3 project

Before we can get cracking, we need to spend some time doing the boring bits by setting up a new project to work on. Luckily we've got you covered and have created a Vue starter template so you can get to the fun bits more quickly. The starter project includes the following pre-setup.

  • Vite - we will use Vite to scaffold our project and provide us with frontend tooling.
  • pnpm - pnpm has fast become our favourite package manager. It's just like NPM but faster!
  • Vue 3 - Of course, you could build this project with any frontend framework, but Vue is still our fave.
  • Tailwind CSS - The Marmitte of CSS frameworks! We love it and find it helps keep our projects consistent and allows us to be super productive.
  • Eslint + Prettier - We want to avoid silly mistakes in our code and keep it nicely formatted.
  • Vue Router - We will need a few pages in our game, so we should set up Vue router early!

Start by cloning the starter project into a folder:

git clone https://github.com/pixelhop/vue-starter.git <your-project-name>

Enter the project folder:

cd <your-project-name>

Initialise git

rm -rf .git && git init

Install dependencies. You may need to install pnpm first npm i pnpm -g pnpm i

pnpm i

At this point you should a new project, with ESlint and Prettier set up correctly, but to get the most out of them, you may need to configure VSCode.

Install the following extensions if you don't have them already:

  • Volar - Vue Language Features. Make VSCode work nicely with .vue files
  • ESLint - Make VSCode work with ESLint
  • Prettier - Make VSCode work with Prettier

After installing the above extensions, configure VSCode as follows to make all the extensions play nice.

Add this to your vscode settings json, or your workspace settings json. (cmd + shift + p type" Settings" and then select "Preferences: Open Setting JSON")

  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": false,
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": true,

Yay! The tedious part is done, and you should now have a new project setup ready to create your real-time cyberpunk supabase masterpiece! You can run your shiny new project with:

pnpm run dev

Setting up default styles

Before we get started with anything too complicated, it's an excellent time to implement some of the default styles we will need to make the project match the Figma designs. Let's start by updating our tailwindconfig.cjs with the following:

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ['./index.html', './src/**/*.{js,ts,jsx,tsx,vue}'],
  theme: {
    extend: {
      colors: {
        black: '#000201',
        orange: {
          DEFAULT: '#FF7615',
        blue: {
          DEFAULT: '#02FFFF',
      dropShadow: {
        'blue-sm': '0px 0px 5px #02FFFF',
        blue: '0px 0px 11px #02FFFF',
  plugins: [],

Here we set up our project colours so they can be used easily throughout our components. We also add two new drop shadow variations to help us apply that cyberpunk blue glow to elements.

Next, we want to add the cool cyberpunk-style font Orbitron: https://fonts.google.com/specimen/Orbitron

Rather than importing the font by referencing the Google Fonts css, we prefer to install it as a package. This is always preferable as it allows you to host the font in the same place as the rest of your site resulting in better performance.

We can install the font using pnpm:

pnpm i @fontsource/orbitron

Then we need to import it in src/main.ts

import { createApp } from 'vue';
import '@fontsource/orbitron';

Now the fonts are installed, we can start by adding some default styles into src/style.css

Before we move into style.css download this background pattern: bg-pattern.png and place it in src/assets/bg-pattern.png

Now update src/style.css to the following:

@tailwind base;
@tailwind components;
@tailwind utilities;

#app {
  height: 100%;

body {
  font-family: 'Orbitron', sans-serif;
  background-color: theme('colors.black');
  background-image: url('./assets/bg-pattern.png');
  background-position: center center;
  background-repeat: repeat;
  color: theme('colors.white');

Here we set the font family on the body to use the Orbitron font we installed earlier.

Next, we set the primary background colour using the Tailwind theme() function to pull out the black colour we put in tailwind.config.css. Using the theme() function is recommended over using @apply bg-black. See Adam Wathan's thoughts on @apply.

Then we add our background image text and set it to repeat.

Finally, we set the default text colour to white!

You should now see something like this in your browser:

All projects start with humble beginnings!

Constraining the height and width

You may have noticed that we have been very lazy and only provided mobile designs in Figma!

Of course, we still want everyone to enjoy the cyberpunk delights of tic-tac-go, even if they are stuck in 1999 and using a desktop, but we don't want the layout stretching all over the shop and looking silly.

For that reason, we will add a container to src/App.vue that will constrain everything to roughly mobile size. Take that, you desktop doofbutts!

<script setup lang="ts"></script>

  <div class="h-full w-full flex items-center justify-center">
    <div class="max-w-sm max-h-[667px] h-full w-full">

<style scoped></style>

That's a wrap!

That's all for the first part of this tutorial series. We now have a good starting point to get on with some of the more fun elements of the project. Next up, we will learn how to animate an SVG logo using anime.js.

Related posts.