Win singing in the Mexican way! La Loteria is the most popular board game in Mexico created on 1887 by Clemente Jacques. Normally the game is played between 2 to 15 players of all ages, where lucky is the one who decides who wins.

Since anyone can join the game because it's easy to play, it makes it a family game besides that some people consider it a recreational type.

Why I choose this game?

I chose to develop this traditional game into a video game that anyone around the world could play and know more about the Mexican culture, however, this wasn't an easy task. It was a complex challenge, from making the designs and audios for each card to the logic to develop a multi-platform game (because I've never done one before).

The USA plays Sack Race, France plays Petánque, but in Mexico, when all the family is together, we play La Loteria.

How to play

I've talked a little bit about the background of the game but, how do you play La Loteria? Well, it's as easy as playing bingo.

Normal Loteria

There are 55 cards in the game. You will receive a board of 16 random cards. The "gritón" (shouter) is the person who will be shouting and singing the passing cards. If you hear one card that you have on your board, put a frijolito (bean) on it. Play this way until you have completed the game mode, which normally is the full game mode where you need to have all the cards marked on your board.

La Loteria Video Game

It's the same as the normal game but here you will have your board on your smartphone or computer.

You'll need a big screen where the cards will be shown and sung. A code game will be displayed on the screen where you need to write it on your cellphone to join the current game. When everybody has joined, the game starts and card by card will appear on the screen, so once again, if you hear one card that you have on your board, put a frijolito (bean) on it pressing it on your phone, if you made a mistake, press twice to remove it.

Press the LOTERIA button and let's see if you have won this game...

How I built it

Well, as I've said before, it wasn't easy to build the game.

Main Page

First I did the lobby page where the user can choose between to go the instructions tab, playing the game, or go the game history tab. This was easy because it didn't include so much code to write. I only use the Wix Window and Wix Location Velo API.

import wixWindow from 'wix-window';
import wixLocation from 'wix-location';

if (wixWindow.formFactor !== "Mobile") { //If a user doesn't enter on a phone
    $w('Button').label = ""; //Colapsar los titulos de los botones

if (wixWindow.multilingual.currentLanguage === "en") { //If the user choose English language
    $w('#button1').label = "Instructions";
} else { //If the user choose Spanish language
    $w('#button1').label = "Instrucciones";

wixWindow.openLightbox("Crear Unirse").then((resultBack) => {
    if (resultBack === "joinGame") {
    } else if (resultBack === "newGame") {

Join Game Tab

Then synchronously I build the Join Game Tab and the New Game Tab but the first one was the join game tab.

In this window, the user introduces the game code and his/her username for the game to identify him/her. In this tab, messages are sent and received with the Wix Realtime Velo API when the game starts or when someone presses the LOTERIA button. Besides this API, I include the Wix Animations to shadow the card images.

import wixRealtime from 'wix-realtime';
import wixAnimations from 'wix-animations';

wixRealtime.subscribe({ "name": idSESION, "resourceId": idSESION }, (message, channel) => {});
wixAnimations.timeline().add($item('#image3'), { "duration": 100, "opacity": 0.7 }).replay();

Since the only way to send messages on Realtime is with the Wix Realtime Backend I created a function where each time I wanted to send a message I needed to call it from the front-end, but I will talk about the code of it in the Backend section.

New Game Tab

This was the one with which I struggled the most. This tab includes all the logic of the game with what to do with the coming messages and what to show or do depending on the type of event.

First, it shows the code game for joining it. Then when all players are in, it asks the game mode you want to play. After it, it shows the instructions, and finally, it starts the game showing card by card with its audio.

The APIs I used here were the same as the Join Game Tab but as I said, here's where the game decides what to do depending on what is receiving.

if (Object(message.payload).event === "checkLoteria") { //Someone has made LOTERIA
    loteria = true;
    loteriaInfo = message.payload.info;

An external API I used was QR Code Generator to display a dynamic QR code to join the game with QueryParams included so that the player doesn't have to rewrite the code game.

const URLGame = encodeURI(`https://deapco.wixsite.com/la-loteria/join-game?gameId=${gameCreated.idSesion}`);
$w('#html1').src = `https://api.qrserver.com/v1/create-qr-code/?data=${URLGame}&size=150x150&color=ffffff&bgcolor=00C6C5`;

Backend functions

sendMessage() or sendMessageToUser()

It sends messages by Realtime to all users or specific users using Wix Realtime Backend.


import wixRealtimeBackend from 'wix-realtime-backend';

export function sendMessage(canal, message) {
    wixRealtimeBackend.publish({ "name": canal, "resourceId": canal }, message, { "includePublisher": true });

export function sendMessageToUser(channel, message, userId) {
    wixRealtimeBackend.publish({ "name": channel, "resourceId": channel }, message, { "users": [userId], "includePublisher": true });


import * as BackFunc from "backend/functions";

BackFunc.sendMessage(wixLocation.query.gameId, { "event": "checkLoteria", "info": { "tablero": $w('#repeater1').data, "userName": wixLocation.query.userName, "_id": wixLocation.query.userId } });

BackFunctions.sendMessageToUser(gameCreated.idSesion, ({ "event": "userJoined", "mainWindow": wixLocation.query.mainWindow }), message.publisher.id);


Checks if the game code that the player wrote in the Join Game Tab exists using Wix Data. It's necessary that this function was in the backend because I used the { "suppressAuth": true } in the Wix Data Options and suppressAuth can only be used here.


import wixData from 'wix-data';

export function bucarSesion(idS) {
    return wixData.query("SesionesActuales")
        .eq("idSesion", idS)
            .eq("juegoIniciado", true))
        .find({ "suppressAuth": true })
        .then((result) => {
            if (result.totalCount === 0) {
                return { "encontrado": false };
            } else {
                return { "encontrado": true, "item": result.items[0] }


import * as BackFunc from "backend/functions";

$w('#button1').onClick(() => {
    BackFunc.bucarSesion(idSESION).then((result) => {});


This function helped me to get all the cards stored in the Media Manager. Since I didn't save the cards on the Data Base, I used the Wix Media Backend to directly obtain the fileURL of each card.


import { mediaManager } from 'wix-media-backend';

export function getCartas() {
    return mediaManager.listFiles({ "parentFolderId": "0e72c4b5de254c9b93b718e4aa37b556" }, { "order": "asc", "field": "originalFileName" }, { "limit": 100 }).then((myFiles) => {
        return myFiles;


import * as BackFunc from "backend/functions";

BackFunc.getCartas().then((cartas) => {
    $w('#repeater1').data = cartas;

Velo API Integration

API Method Location in Project
Wix Animations 1. Timeline 1. Join Game 2. New Game
Wix Data 1. Query Backend
Wix Location 1. Query 2. QueryParams 3. To() All tabs
Wix Media Backend 1. Media Manager Backend
Wix Realtime 1. Suscribe() 2. Unsuscribe() 1. Join Game 2. New Game
Wix Realtime Backend 1. Publish() Backend
Wix Window 1. Form Factor 2. Lightbox 3. Multilingual 4. OpenLightbox() All tabs

Challenges I ran into

I think this list will be larger than the Declaration of Independence... just kidding, but one thing I'm sure of is that I struggled with obvious things during the development of the game.

The Realtime channel

Well, this was my first time using the Wix Realtime Velo API so I thought that you can only include the channel name but it didn't work, so I noticed that if I include both the name and resourceId of the channel it sent the message.

Design and audio content

I didn't want to include Google images for the cards, so I made each of them with graphical online software so that they would be the way and design I wanted.

I recorded each singing card audio with my phone. First I searched for phrases for each icon and then wrote them down so I can record them later.

Check if it is LOTERIA or not

The second biggest issue I had was to find a way if the player's board had made the mode game. We humans can see if on the board there's a vertical or horizontal line like in the bingo, but how can a computer check if the Loteria board has a vertical or horizontal line? Well, it took me one complete day to find out how to do that, and finally got it.

AudioPlayer element

Last but not least (literally not the least problem, instead it was the biggest problem I had) was the audioPlayer element included in the New Game Tab where I wanted to include background music while the audio phrases were played too, but I can't.

I thought I could have two audio players playing at the same time but the last one on playing is the one that reproduces and the other one stops, so first it was big trouble because I thought it would lose the essentiality of the game, but when I try it out, it didn't seem a big deal.

Another thing I had trouble with it was changing the source of it at a certain time. I thought that if you do that, the currentTime will change to 0 so that it started from the beginning, but nope, so I need to make changes before playing it but I don't know why sometimes it didn't work so it was a complete disaster to work with this element.

Accomplishments that I'm proud of

I think that the biggest accomplishment I'm proud of is that it worked, that's all, the video game I had on my mind I could make it work out and I feel astonished that within 1 week I could finish it using new resources.

The other thing I'm proud of is that the new Velo APIs I used I knew how to use them correctly. I thought that Wix Realtime was hard to use, but it's all the opposite, it's so easy to use and can help in other developments that I may do further.

What I learned

Well, as I said above, the usage of new Velo APIs I hadn't worked with before and the way web browsers interact with audio players elements. I think only those two things were new for me because I can say that I'm a WIX fan, every project, system, or online software I need to develop, I do it in WIX, and also because I'm a Velo certificated so I kind of know who to work well with WIX.

What's next for La Loteria

I would like that this game becomes an international game that everybody can play, but before getting here, I think that the card audios should be translated into other different languages since the only available one is in Spanish and made with other voices, with professional voices of dubbing world.

Share this project: