DEV Community

Cover image for Netlify Dynamic Site Challenge: Motizen, a treasure hunt game
Sergo
Sergo

Posted on • Edited on

Netlify Dynamic Site Challenge: Motizen, a treasure hunt game

This is a submission for the Netlify Dynamic Site Challenge: Build with Blobs.

First of all, I want to apologize. Both to myself and to the community. Unfortunately, I couldn't and didn't have time to implement everything I wanted. I didn't estimate my strength and time. And this is a very big mistake. But I always remember that many smart people said that it's better late than never. Or it's better to participate than not to participate.

What I Built

I wanted to surprise you with a game where each user would uncover pieces of a picture and find various treasures. Every day, piece by piece. But since I don't have enough experience, and I didn't work closely with Netlify, it turned out the way it did.

First of all, when you go to the site, don't be scared. Yes, there is a registration. 😅 I implemented it with Netlify Integrity. The game was supposed to show players who found treasures. But I didn't have time to implement this.

Demo

Mista

You can try the game here.
Attention! Please do not click too quickly and too much! I didn't implement serverless functions very well.😭😥

Platform Primitives

I implemented two functions, loadGameState, saveGameState, with which you can save the game state using Netlify Blobs as storage. And I did it through Netlify Function Serverless.

async function loadGameState(gameStateBlobId) { return fetch(`/.netlify/functions/load-game-state?blobID=${gameStateBlobId}`, { method: 'GET', headers: { 'Content-Type': 'application/json', } }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return response.json(); }) .then(result => { const gameState = JSON.parse(result.gameState); console.log('Game state loaded successfully: ', gameState); return gameState; }) .catch(error => { console.log('Error in loading game state: ', error); throw error; }); } async function saveGameState(gameState) { const json = JSON.stringify(gameState); return fetch('/.netlify/functions/save-game-state', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: json }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } return response.json(); }) .then(result => { console.log('Game state saved successfully: ', result) return result; }) .then(result => { localStorage.setItem('gameStateBlobId', result.blobID); }) .catch(error => { console.log('Error in saving game state: ', error); throw error; }); } 
Enter fullscreen mode Exit fullscreen mode

This is a serverless function for load-game-state.mjs:

import { getStore } from '@netlify/blobs'; exports.handler = async function(event, context) { const siteID = process.env.NETLIFY_SITE_ID; const token = process.env.NETLIFY_TOKEN; const store = getStore({ siteID, token, name: 'my-store' }); if (event.httpMethod !== 'GET') { return { statusCode: 405, body: 'Method Not Allowed' }; } const blobID = event.queryStringParameters.blobID; if (!blobID) { return { statusCode: 400, body: JSON.stringify({ message: "BlobID is required" }) }; } let buffer; try { buffer = await store.get(blobID); } catch (error) { console.error("Error fetching blob:", error); return { statusCode: 500, body: JSON.stringify({ message: "Error fetching game state" }) }; } if (!buffer) { return { statusCode: 404, body: JSON.stringify({ message: "Game state not found" }) }; } const gameState = buffer.toString(); return { statusCode: 200, headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ gameState }) }; }; 
Enter fullscreen mode Exit fullscreen mode

And this is how I implemented Netlify Integrity (maybe, someone it will helpful):

'use client' import netlifyIdentity from 'netlify-identity-widget'; export default function Home() { ... useEffect(() => { netlifyIdentity.init(); const handleLogin = (currentUser) => { netlifyIdentity.open(); setIsLoggedIn(true); setPlayerName(currentUser.user_metadata.full_name || currentUser.email); }; const handleLogout = () => { setIsLoggedIn(false); setPlayerName(''); netlifyIdentity.logout(); // выход из системы }; netlifyIdentity.on('login', handleLogin); netlifyIdentity.on('logout', handleLogout); if (netlifyIdentity.currentUser()){ handleLogin(netlifyIdentity.currentUser()); } return () => { netlifyIdentity.off('login', handleLogin); netlifyIdentity.off('logout', handleLogout); }; }, []); return ( <main className={styles.main}> <ImageUploader onFileSelect={(selectedFile) => setFile(selectedFile)} setName={(name) => {setUserName(name); setPlayerName(name);}} />  <CanvasComponent processImage={processImage} />  <div ref={nameRef}>{playerName}</div>{/* Div для отображения имен */}  {isLoggedIn ? ( <div className={styles.userIdentity}> {playerName} <button onClick={() => netlifyIdentity.logout()}>Logout</button>  </div>  ) : ( <button onClick={() => netlifyIdentity.open()}>Login / Sign Up</button>  )} </main>  ); } 
Enter fullscreen mode Exit fullscreen mode

This is not the End

In this project I used Next.js, Netlify Blobs Store, Netlify Integrity, Canvas API, Netlify Serverless and deployed on Netlify.
It was hard, but very interesting. Thank you for this challenge!

Griffith

Top comments (0)