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
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;
});
}
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 })
};
};
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>
);
}
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!
Also, I will plan to continue work on this project and someday finish it. I want to connect it with another my game about motivation. If you want to follow, I created a new channel in Telegram. Thank you for your patience and attention!
Top comments (0)