buzzphonics: a learning app
A sounds app for parents and kids to learn phonics in the UK.
๐ About the project
In this Netlify x Hashnode hackathon post I want to share with you how I built my buzzphonics app.
I wanted to create a phonics app that I can save on my phone and have to hand when reading with my daughter who's just started learning to read. I often need to find out what a certain sound is and end up googling it every time. I need something quick and easy to click on specifically for using on my phone.
I found lots of YouTube videos doing the sounds, but then I'd have to listen to every sound, rather than just the one I wanted. For me, I wanted a single page with buttons for each sound in Phase 2 and Phase 3 phonics, here in the UK. My plan:
Simple idea - a list of sounds to listen to โ๏ธ
Small stretch goal - flip the whole page and it has images (e.g fox for f) instead of the letter โ๏ธ
Stretch goal - games โ๏ธ
Try out buzzphonics.
๐ ๏ธ How I built it
Requirements
The requirements for the basic design was to have a Phase 2 and Phase 3 page with all the sounds. Then my daughter got involved and wanted some icons and games. She wanted to be able to use the app for learning and how could I say no to that?!
Designing the layout
Inspired by Nature Sounds App by Lay on Dribbble I created this design in Figma.
I wanted it to be bright and fun for me to be able to use with my kids.
Tech stack
- React
- React Router v6
- React icons
- Deployed with Netlify
Implementation
I started with a basic 3-page layout using React and React Router. Initially, it was just going to be the home page with links to Phase 2 and Phase 3 sounds. The design changed slightly when I added the games.
Adding sounds to the letters was simple with JavaScript. I recorded all the sounds myself (under a duvet cover) as I couldn't find a royalty-free version.
The first game I added was to pick the beginning sound of the image out of three choices. I set a lot of states to track the questions, the current question, the answer and whether the user is ready to move on to the next question. I wanted different questions to appear each time they took the quiz.
function shuffleSounds() {
return [
{
id: 0,
image: "duck",
alt: "duck",
answerOptions: [
{answerText: "d", isCorrect: true},
{answerText: "f", isCorrect: false},
{answerText: "ck", isCorrect: false},
]
}, // lots of questions
].sort(() => Math.random() - 0.5).slice(0,5)
}
The matching game took a little longer to figure out as I wasn't matching 2 identical images. I wanted to match the letter to an image, for example, "f" and a picture of a fox. When it came to shuffling the questions, or cards in this example, I needed to shuffle the desk first and then map the array.
function shuffleCards() {
const shuffledDeck = sounds.sort(() => Math.random() - 0.5).slice(0,6);
return [...shuffledDeck.map((sound) => {
return {id: sound.id, letter: sound.letter}
}), ...shuffledDeck.map((sound) => {
return {id: sound.id, icon: sound.icon}
})].sort(() => Math.random() - 0.5)
}
The final feature I added was a points system. For each game that is completed, the user gets a point. These are displayed on the home page and the Games page. I used useContext to track the points through the app and saved the points to local storage. I made the points display in a hexagon, like a beehive.
const incrementalPoints = useContext(pointsContext)[1]
if (matched.length === 5) {
setFinished(wellDone)
incrementalPoints()
}
I decided last minute to add one more game, as my daughter kept asking me for one. This is a spelling game and more complex than the other two games. I started by writing pseudo code to see how the game would be laid out and how I would store the data. I created a cardDeck array that held the words, sounds and images. I then setup the desk by shuffling the sounds of the word and adding 3 random sounds, that weren't in the original word.
function setupDeck(input) {
const localSounds = [...sounds]
// Shuffle sounds from sound array
localSounds.sort(() => Math.random() - 0.5)
// Pick 3 random sounds that are unique
let randomSounds = []
while(randomSounds.length < 3) {
const pickedSound = localSounds.pop()
if (!input.sounds.find(sound => sound === pickedSound.sound)) {
randomSounds.push(pickedSound.letter)
}
}
At this point I took a break and designed a name and logo for the app. I also added another game, a reading game, based on the quiz. It's good to mix things up a bit.
For the final part of the game, I asked for help. I knew what I wanted the game to do but I couldn't figure out how it should happen. The letters needed to be clicked in the correct order and displayed. It was interesting to learn how the game worked and when we merged in the branch, it had conflicts I needed to resolve. I've not seen that before so it was a good thing to learn!
const handleCardClick = (sound) => {
const current = deck[currentCard]
const nextSound = current.sounds[currentPosition]
if (nextSound.sound === sound) {
deck[currentCard].sounds[currentPosition].found = true;
setCurrentPosition(currentPosition + 1)
}
// check if we have completed current word
if (currentPosition >= deck[currentCard].sounds.length - 1) {
setCantContinue(false)
}
}
Now with 4 working games all there was left to do was add more content and repeat the sounds game with Phase 3 sounds.
๐ก What did I learn?
I have made a few React projects in the past but even though the site is quite simple there were a few things that got me googling.
useContext. I wanted a simple way to pass the points from the game to the main page. UseContext allowed me to manage the state globally across the app rather than drilling down props.
Building games. I'm not a gamer and I've really disliked all the games projects I've done while learning. My daughter wanted them so it was interesting to step back and draw out on paper the game play and work out what to code.
Using branches and pull requests in GitHub. It was my first experience using branches and pull requests on my own project.
๐ญ Plans for the future
To make this game much more funs for my kids, I want to add some more features.
- The ability to login and keep your points to yourself. My youngest wants to try and play too so being able to have their own accounts would be amazing.
- New games. If you have any other word game ideas please comment below or create an issue/discussion on GitHub.
๐ Links
๐ Thanks
This app is open source and I would love to have others work on it to develop it further. My daughter asks for a new game every day and I'm not a magician ๐ .
Feel free to connect with me on Twitter or LinkedIn and let me know your thoughts on this project.