In this article, I'll walk you through creating a fun and engaging Meme Battle Royale system using SurrealDB and the Gofr framework. This project demonstrates how to integrate SurrealDB, a powerful multi-model database, with Gofr, an open-source Go web framework, to build a system where users can vote on their favorite memes in head-to-head battles.
What is SurrealDB?
SurrealDB is a scalable, distributed database that combines the flexibility of document databases with the power of graph databases and the reliability of traditional relational databases. It's designed for modern applications that require complex data relationships while maintaining high performance and ease of use.
Project Overview
The Meme Battle Royale is a voting system that allows users to:
- Upload memes with titles and URLs
- Participate in head-to-head battles between two random memes
- Vote for their favorite memes
- View a leaderboard of the most popular memes
The system tracks wins and losses for each meme, creating an engaging competition platform.
Setting Up SurrealDB with Docker
Getting started with SurrealDB is straightforward using Docker:
- First, install Docker if you haven't already.
- Pull and run the SurrealDB container:
docker run --name surrealdb -p 8000:8000 surrealdb/surrealdb:latest start --log debug
Database Schema
Our system uses two main tables: memes and votes. Here's how we define them in SurrealDB:
DEFINE TABLE memes SCHEMALESS;
DEFINE FIELD title ON TABLE memes TYPE string;
DEFINE FIELD url ON TABLE memes TYPE string;
DEFINE FIELD wins ON TABLE memes TYPE int DEFAULT 0;
DEFINE FIELD losses ON TABLE memes TYPE int DEFAULT 0;
DEFINE TABLE votes SCHEMALESS;
DEFINE FIELD meme1_id ON TABLE votes TYPE string;
DEFINE FIELD meme2_id ON TABLE votes TYPE string;
DEFINE FIELD winner_id ON TABLE votes TYPE string;
Integrating SurrealDB with Gofr
The integration between SurrealDB and Gofr is handled through a configuration setup:
client := surrealdb.New(&surrealdb.Config{
Host: "localhost",
Port: 9000,
Username: "root",
Password: "root",
Namespace: "app",
Database: "meme_battle",
TLSEnabled: false,
})
Core Data Models
Our application uses two main data structures:
type Meme struct {
ID string `json:"id,omitempty"`
Title string `json:"title"`
URL string `json:"url"`
Wins int `json:"wins"`
Losses int `json:"losses"`
}
type Vote struct {
Meme1ID string `json:"meme1_id"`
Meme2ID string `json:"meme2_id"`
WinnerID string `json:"winner_id"`
}
API Endpoints
1. Create Meme (POST /memes)
This endpoint allows users to add new memes to the battle system:
POST http://localhost:9000/memes
Content-Type: application/json
{
"title": "Monday Motivation",
"url": "https://example.com/meme1.jpg",
"wins": 0,
"losses": 0
}
2. Get All Memes (GET /memes)
Retrieves all memes in the system:
GET http://localhost:9000/memes
3. Submit Vote (POST /vote)
Records a vote in a head-to-head battle:
POST http://localhost:9000/vote
Content-Type: application/json
{
"meme1_id": "memes:75ut1jzxj04agbv944yi",
"meme2_id": "memes:cgbrmfm7x66g56nhxkgg",
"winner_id": "memes:75ut1jzxj04agbv944yi"
}
4. View Leaderboard (GET /leaderboard)
Shows the top-performing memes:
GET http://localhost:9000/leaderboard
Implementation Details
The core of our implementation lies in the main.go file, where we set up our routes and handlers:
func main() {
app := gofr.New()
// Set up SurrealDB client
client := surrealdb.New(&surrealdb.Config{...})
app.AddSurrealDB(client)
// Register routes
app.POST("/memes", addMeme)
app.GET("/memes", getMemes)
app.POST("/vote", voteMeme)
app.GET("/leaderboard", getLeaderboard)
app.Run()
}
Each endpoint handler is implemented with proper error handling and database operations. For example, here's how we handle adding a new meme:
func addMeme(ctx *gofr.Context) (interface{}, error) {
var meme Meme
if err := ctx.Bind(&meme); err != nil {
return ErrorResponse{Message: "Invalid request body"}, nil
}
result, err := ctx.SurrealDB.Create(ctx, "memes", map[string]interface{}{
"title": meme.Title,
"url": meme.URL,
"wins": meme.Wins,
"losses": meme.Losses,
})
if err != nil {
return nil, err
}
return result, nil
}
Testing the System
Using Postman or curl, you can test each endpoint. For example, to add a new meme:
curl -X POST http://localhost:9000/memes \
-H "Content-Type: application/json" \
-d '{"title":"Work From Home","url":"https://example.com/wfh.jpg"}'
Conclusion
This project demonstrates the power and flexibility of using SurrealDB with the Gofr framework. The combination provides a solid foundation for building scalable, real-time voting systems. The schema-less nature of SurrealDB makes it easy to evolve the data model as requirements change, while Gofr's simplicity allows for rapid development of REST APIs.
Whether you're building a meme battle system or any other type of voting application, this stack provides the tools needed for success. The complete code for this project is available on GitHub, and I encourage you to explore, fork, and contribute to its development.
If you found this article helpful, please consider starring the Gofr repository and contributing to the community!
⭐ Star https://github.com/gofr-dev/gofr on GitHub
Top comments (0)