A musical memory game inspired by Simon and Bop It, Echoes of the Crystal Cave gives the classic format a unique twist. Set in a mysterious cave filled with glowing crystals, the game uses a five-note musical scale and atmospheric audio to create an immersive experience. Players interact with animated, glowing crystals that light up and play tones. Designed with accessibility, responsiveness, and pixel-art charm in mind, the game is easy to play yet increasingly challenging.
View Live Site on GitHub Pages.
Key features that make Echoes of the Crystal Cave unique and engaging:
- Musical memory gameplay based on a five-note scale
- Pixel-art cave environment with atmospheric sound effects
- Glowing, animated pixel-art crystals
- Animated bat character (Brucey) guiding the player
- Responsive controls for keyboard, mouse, and touch devices
- Personalised greetings and returning player recognition
- Accessibility features including visual cues for colour vision differences
- Increasing difficulty with each level
- Freestyle mode for creative exploration of the crystal sounds
- Progress and stats saved in local storage, including best level and highest memory streak
- Game Dashboard modal for easy access to player stats and customisation settings
- Objectives
- User Stories
- Design & Planning
- Game Mechanics
- Wireframes
- Pseudocode
- Function Structure and Game Pseudocode Refined
- Project Kanban Board
- Typography
- Colour Palette
- Technologies Used
- Features
- Deployment
- JavaScript JSDoc Documentation
- Testing
- Future Enhancements
- Credits
- Acknowledgements
Target Audience:
- Casual gamers who enjoy quick, skill-based challenges.
- All age groups, from children to adults, due to simple controls and gameplay.
- Fans of retro and pixel art games looking for a nostalgic yet fresh experience.
- Fans of music based games.
- Fans of memory games and memory training games (music memory included).
- As a player, I want to start a new game easily, so I can quickly begin playing.
- As a player, I want to see my progress and highest level, so I can track and improve my performance.
- As a player, I want visual and audio feedback for correct and incorrect actions, so I understand my progress and mistakes.
- As a player, I want the crystals to light up and play sound when I interact with them, so I know my input was registered.
- As a new player, I want clear, simple instructions, so I can understand the game quickly.
- As a player, I want accessible controls (mouse, keyboard, touch), so I can play on any device.
- As a player, I want clear icons or tooltips for each button, so I understand their purpose even without text.
- As a player, I want clear, accessible buttons to restart, return home, view instructions, and access settings, so I can easily control my experience.
- As a player, I want to toggle full-screen mode and sound, so I can play comfortably in different environments.
- As a player, I want to delete my saved progress, so I can start fresh whenever I choose.
- As a user, if I land on a broken or missing page, I want to see a friendly 404 message and a clear way to return to the homepage.
- As a player, I want to enter a username and receive personalised messages, so the game feels more engaging.
- As a returning player, I want my progress (like highest level) to be saved locally, so I can aim to improve over time.
- As a player, I want to hear ambient cave sounds and background music, so the game feels immersive.
- As a player, I want to adjust or mute the game’s audio, so I can customise the experience to suit my environment.
- As a player, I want to play the crystal notes freely, so I can experiment with the sounds and enjoy them outside of the main game.
Echoes of the Crystal Cave is a memory-based puzzle game where players help Brucey the bat navigate a mysterious cave filled with glowing, musical crystals. Players must watch and listen to and repeat sequences of notes to progress, while enjoying a dynamic audio-visual experience.
Help Brucey the bat remember the sequence of crystals.
- Mouse Click – Click on the crystals to play their notes.
- Touch Screen Tap – Tap crystals on mobile for touch interaction.
- Keyboard Keys (A, W, S, E, D) – Alternative input for accessibility.
- Crystals glow in different colours when activated.
- Each crystal plays a distinct note in a five-note scale.
- Correct sequence all crystals glow and a rewarding sound plays before the next level sequence starts.
- Incorrect sequence results in modal pop up with encouraging 'try again' messages (could have random inspiring messages) and option to play again yes/no buttons.
- Successfully repeat the full sequence to advance to the next round.
- In Hard/Default Mode, a single mistake results in a game over.
- (could have feature) Easy Mode, players have three chances before restarting.
- Easter egg - Player name input. If name is equal to Brucey, Brucey the bat changes colour or wears a hat.
- Level 1 = sequence of 3
- Level 2 = sequence of 4
- Level 3 = sequence of 5 ... and so on.
- Music notes/scale and crystal colour correspondence layout:
Brucey the plush bat - inspired the game’s theme.
Before creating digital wireframes, I began with rough hand-drawn notes and layout sketches to quickly capture my ideas for gameplay, UI, and features. At this stage, I also started thinking about the basic pseudocode — such as how many containers would be needed for the game layout and how the game would flow. This helped me visualise the game structure and user experience before moving on to more refined wireframes.
Below are some of my initial hand-drawn notes and layout sketches. While extremely rough, they show my early ideas and the creative planning process before moving to digital wireframes.
These early sketches helped me clarify the game’s structure and user flow before moving on to more polished wireframes.
Basic pseudocode was used during the early planning and development stage. It was helpful to write out the basic logic in order to visualise the game layout and html div containers needed in order to make dynamic changes to each componant.
- Start the game when the player clicks "Start".
- Set the initial level to 1.
- Determine sequence length based on the level (Level 1 = 3, Level 2 = 4, Level 3 = 5 etc.).
- Generate a random sequence of numbers (1 to 5), each representing a crystal.
- Store the sequence.
- Display (play) the sequence by making the corresponding crystals glow and play their notes.
- Wait for the player to start inputting their sequence by clicking on crystals.
- Store each clicked crystal in an array in the order they are clicked.
- After the player has entered the full sequence, compare it to the generated sequence.
-
If the player's input matches the generated sequence:
- Play a success animation (all crystals glow, twinkly music plays).
- Increase the level.
- Generate a new sequence with an increased length.
- Display the new sequence.
-
If the player's input does not match:
- Display "Game Over" modal with retry option.
- Option to restart from Level 1.
- Implement difficulty modes (e.g., limited attempts in hard mode/lives in easy mode/faster sequence speed).
- Add settings like brightness and sound control.
- Store player progress (e.g., name and highest level reached) in local storage.
- Easter egg for special player name (e.g., "Brucey" replace bat pixel sprite).
-
startGame()- Resets level to 1
- Generates an initial sequence of 3 crystals
- Displays the sequence to the player
-
storeSequence()- Generates a random sequence of crystal notes for each level
- Ensures each level has a completely new sequence (level + 2)
-
playSequence()- Loops through the stored sequence
- Makes each crystal glow and plays the corresponding note
-
waitForPlayerInput()- Captures player clicks, keyboard keys / A,W,S,E,D / touch, on crystals
- Stores their input sequence
-
checkPlayerInput()- Compares player’s input with the stored sequence
- If correct: calls
nextLevel() - If incorrect: calls
showPlayAgainModal()
-
nextLevel()- Increments level by 1
- Calls
storeSequence()to generate a new, longer sequence (by 1) - Calls
playSequence()to show the new sequence
-
showPlayAgainModal()- Displays a modal asking if the player wants to retry
- If "Yes": Calls
startGame()to reset - If "No": Ends the game - return to home page
To help plan and understand the logic for my project, I wrote out basic pseudocode and used Python Tutor to visualise how my functions and arrays would work. This approach, learned during my course, made it much easier to break down the game’s mechanics and debug early logic before building the full game.
Below are some screenshots of my early function experiments in Python Tutor:
This early visualisation and step-by-step debugging helped me confidently move from pseudocode to working JavaScript code.
The project was managed using a Kanban board to track tasks and features. This helped me stay organised and focused on the development process. The board was regularly updated to reflect progress and priorities.
View Echoes of the Crystal Cave Project Kanban Board
Google Fonts Selection:
For the game's typography, I aimed to capture a retro, pixel-inspired aesthetic without sacrificing readability, especially for longer text.
Jersey 20 was selected as the primary font for its pixelated, slightly retro style, which fits the game's theme perfectly. Unlike many pixel fonts that can seem hard to read, Jersey 20 maintains excellent legibility, making it ideal for headings, speech bubble text, and body text across the game site.
Handjet was chosen as a complementary font for more selective use, such as level numbers, tooltips, and modals. Its stronger pixelated look adds character where appropriate, without overwhelming the overall readability of the UI.
This combination balances a nostalgic pixel-game feel with a user-friendly reading experience, ensuring the game remains visually thematic and accessible.
The game's colour palette was refined using Coolors to achieve the right balance of aesthetic feel and accessibility. I chose a combination of dark and muted light blues for the backgrounds, headings, and button icons.
Accessibility was a priority: contrast ratios were carefully checked during development to ensure good readability for all text and UI elements.
Speech bubbles use classic black and white for maximum clarity against the dark backdrop, maintaining a clean and focused dialogue progression.
The crystals are designed with bright, saturated colours so they stand out vibrantly against the dark background cave design.
Accessibility & Visual Cues:
To ensure the game is playable for players with colour vision differences, the crystal glow effect was designed to provide a strong visual cue that does not rely solely on colour. During development, I tested the crystal animations using the Colorblindly Chrome extension (Monochromacy/Achromatopsia mode) and recorded a GIF to demonstrate that the glow and brightness changes remain visible even in monochrome. This means that while the crystal colours are a big feature, they are not essential for gameplay — players can rely on the glow effect as a clear indicator.
Future plans include extending the settings modal with a filter/slider to allow players to increase the glow, contrast, or brightness of the crystals, making the game even more accessible for a wider range of visual needs.
- GitHub — Version control and project hosting
- VSCode — Code editing
- GitHub Pages — Hosting the live site
- HTML — Semantic structure and content
- CSS3 — Styling, responsive layouts
- JavaScript (ES6+) — Interactivity, game logic, DOM manipulation
- JavaScript Modules (ES6+) — Organising code into separate, reusable files using
importandexport
- Web Audio API — Sound generation and crystal interaction audio
- Ableton Live — Creating and mastering sound effects and musical notes
- Google Fonts — Jersey 20 and Handjet for retro pixel-style typography
- Adobe Photoshop — Editing assets, creating pixel backgrounds, modals, and sprites
- Tiled Map Editor — Building the cave background and level layout
- Favicon Generator — Creating a custom favicon
- Video to GIF Converter - for creating GIFs for documentation
- Coolors — Generating and refining the colour palette
- Eye Dropper — Extracting colours from images for palette consistency
- colorblindly — Testing for colour accessibility and ensuring the game is playable for players with colour vision differences
- WebAIM Contrast Checker — Checking colour contrast ratios
- Lighthouse — Performance and accessibility audits
- ESLint — Used both as a VSCode extension and via the terminal for JavaScript code quality and error checking
- JSHint — Used alongside ESLint to provide extra meticulous, stricter checks and helpful metrics feedback
- JSDoc — Generating documentation from annotated JavaScript comments
- HTML Validator — HTML syntax and structure checking
- CSS Validator — CSS syntax and structure checking
- Prettier — Code formatting and style consistency
- Am I Responsive? — Testing responsive design across devices
- Chrome DevTools — Debugging and testing
- Gyazo Video and GIF — Recording and sharing gameplay videos and GIFs
- BrowserStack — Cross-browser and cross-device compatibility testing
- ChatGPT — Writing aid for documentation and clarity
- Python Tutor — Visualising game logic and code flow
- Balsamiq Wireframes — For creating wireframes
- Todoist – For managing tasks and tracking project progress.
- Microsoft OneNote & Word – Used to organise content, draft text, and structure ideas.
The Home Page welcomes players with a retro pixel-art design. The page features a large title, a description of the game, and a Start Game button. The design is responsive, ensuring a consistent experience across devices.
Below is a GIF of the game page in action, showing the crystals glowing and the player playing back the correct sequence. All crystals glow when the player enters the correct sequence, before the next level starts.
Key Features of the Game Page:
- Five interactive, glowing crystals, each with a unique sound and colour.
- Level indicator and animated bat character for guidance.
- Responsive design for desktop, tablet, and mobile.
- Accessible controls: mouse, keyboard (A, W, S, E, D), and touch.
The user interface is designed for clarity and accessibility, with intuitive buttons and helpful tooltips. While all buttons are important for navigation and gameplay, three key controls—Mute/Unmute Audio, Freestyle Mode, and Fullscreen—are dynamic: they visually change to reflect their current state and update their tooltips accordingly. This provides immediate feedback and ensures players always know the current mode or setting.
Other interface buttons, such as How to Play, Restart, Dashboard/Settings and Home remain visually consistent, intuitive and are also clearly labeled with tooltips for ease of use.
When the game page loads, the player first sees the game container, allowing them to take in the environment. After a brief pause, Brucey the bat appears with a speech bubble, introducing himself and the game. This short delay helps set the scene and gives Brucey’s introduction more impact.
In the dialogue bubble, the player is asked for their name and a name input modal opens.
Personalised Greeting:
If the player enters a name, Brucey responds with a custom message, making the game feel more personal and engaging. The name is stored in local storage for future visits.
Alternative Response:
If the player skips the name input, Brucey playfully acknowledges their choice, keeping the tone light and fun.
Returning Players:
Players who return to the site and have previously entered a name are greeted with a “Welcome back” message, reinforcing a sense of continuity.
Responsive Design:
The speech bubble and name input modal are designed to be responsive, ensuring they look good on all devices. The instructions to 'Click or press spacebar to continue' are on desktop. On mobile, the instructions are to tap the screen to continue. This ensures that players know how to proceed regardless of their device.
Mobile 'Tap to continue' Instructions:

The How to Play modal provides players with clear instructions on how to play the game. It includes a brief overview of the game mechanics and controls. The modal is designed to be visually appealing and easy to read.
The game dashboard modal provides players with a summary of their progress, including the highest level reached and best memory streak. It also offers quick access to key settings for a more personalised and accessible experience.
-
Delete Progress:
Players can reset their saved progress—including their name and highest level—by clicking the "Delete Progress" button. This action reloads the page and clears all saved data. A tooltip warns players before proceeding, ensuring they are aware of the consequences. -
Audio Settings:
Players can independently adjust the volume of ambient background music, cave sound effects, and crystal notes using intuitive sliders and mute buttons. There’s also a global mute button for convenience on the main game page. -
Brightness Control:
In addition to device brightness settings, the dashboard includes a site-specific brightness slider. This allows players to increase or decrease the brightness of the game page itself, making it easier to see the crystals against the dark cave background—especially in bright environments or for those with visual needs. The effect is achieved using CSS filters and JavaScript to dynamically update the brightness level in real time.
Audio is a core part of the Echoes of the Crystal Cave experience. The game features a layered soundscape with ambient cave music, interactive crystal tones, and celebratory effects.
As someone passionate about game audio, I designed Echoes of the Crystal Cave with a focus on interactive sound. The audio system is fully modular, allowing for dynamic mixing, real-time effects, and future expansion with custom music and sound design.
-
Dynamic Audio Ducking:
When the crystal sequence plays or the player interacts with crystals, the ambient track automatically fades (ducks) to ensure the crystal sounds are clear and prominent. The ambient volume smoothly returns when the sequence ends, creating a polished, immersive feel. -
Individual Track Controls:
The Game Dashboard/Settings modal provides volume sliders and mute buttons for each audio channel:- Ambient background music
- Cave sound effects
- Crystal notes and celebration effects
There’s also a global mute button for quick access on the main game page.
-
Responsive Audio Logic:
All audio controls update in real time, ensuring that changes are immediately reflected in the game. This includes volume adjustments and mute/unmute actions.
Note: The current build uses placeholder audio, but the system is ready for original, chiptune-inspired sounds and ambient music, which I plan to compose and integrate before the final release.
Audio User Event Permission Overlay:
When the game page loads, first, an overlay appears stating the site is best experienced with audio, requesting the user to click or tap to continue. A user event is a requirement for the Web Audio API to work properly. This is an effective way to ensure the user is aware of the audio and can choose to continue to enable it or not.
When the player makes a mistake, a Game Over modal appears, displaying an encouraging message and options to restart or return to the home page. The modal is designed to be consistent with the game's theme.
Freestyle Mode lets players explore and play the crystal sounds without the pressure of following a sequence. Players can click or tap on the crystals to create their own melodies, experimenting with the different notes at their own pace. This mode is ideal for those who want to enjoy the musical aspect of the game or simply relax and be creative.
Looking ahead, Freestyle Mode is designed to be expandable — with plans for more complex musical features and potential integration with the Web MIDI API, allowing for even greater interactivity and creativity.
The custom 404 page matches the game's mysterious cave theme. It features fading/flickering crystals, and the message “404: Lost in the Cave. The echoes fade... you are not where you're meant to be...” A Return Home button helps guide players back if they get lost.
Fading/Flickering Crystals:
Throughout Echoes of the Crystal Cave, a consistent fade-in animation is used for major elements:
- Home screen titles and images
- Game container and interface elements
- Modals, overlays, and dialogue bubbles
- Crystal buttons and level indicators
Inspiration:
The design choice was inspired by video games, where fade-ins create a smooth, cinematic transition between scenes.
Rather than having elements appear suddenly, the fade-in makes the game feel more cohesive and polished.
Implementation:
Fade-ins were applied using simple CSS transitions for broad browser compatibility and performance.
The effect maintains consistency across devices without adding unnecessary complexity or heavy scripting.
- Sign in to GitHub.
- Go to the Code Institute template (if used) or your own repository.
- Click Use this template and select Create a new repository.
- Enter a name for your repository and click Create repository from template.
- Open VS Code and connect your GitHub account:
- Click on the Accounts icon (bottom-left).
- Sign in and authorize VS Code.
- Open the repository in VS Code using Remote Repositories:
- Click the Source Control tab (or press
Ctrl + Shift + G). - Click Clone Repository and select GitHub.
- Find and select your repository.
- Choose a location on your machine.
- Click Open in VS Code once cloning is complete.
- Click the Source Control tab (or press
For those who prefer the terminal, use the following commands:
# Initialise a Git repository (if not already initialised)
git init
# Add all files to the staging area
git add .
# Commit the changes with a descriptive message
git commit -m "Initial commit"
# Connect the local repository to GitHub (only needed if not already linked)
git remote add origin https://github.com/YOUR-USERNAME/YOUR-REPO.git
# Push the changes to the main branch
git push -u origin mainWhenever updates are made:
git add .
git commit -m "Update features and bug fixes"
git push- Go to your GitHub repository.
- Click on the Settings tab.
- Scroll down to the Pages section in the left sidebar.
- Under Branch, select
main(or the branch you want to deploy). - Click Save.
- After a few moments, GitHub Pages will generate a link to your live site.
To maintain a clean and organised codebase, this project adopts a branching workflow. For this project, I created a dedicated feature branch for a major refactor, which I merged into the main branch before deployment. In future development, I plan to use this workflow for all significant changes.
- Creating a New Branch:
To create a new branch for a specific feature or module refactor:
git checkout -b feature/branch-name- Making and Committing Changes:
Make your changes, then stage and commit:
git add .
git commit -m "Implement new feature or refactor module"- Pushing the Branch to GitHub:
Push the branch to GitHub:
git push -u origin feature/branch-name- Merging the Branch into Main:
Once the feature/refactor is complete and tested, merge it into the main branch:
- Switch to the main branch:
git checkout main
- Pull the latest changes to ensure it’s up to date:
git pull origin main
- Merge the feature branch:
git merge feature/branch-name
- Resolve any merge conflicts, then commit the changes:
git add . git commit -m "Merge feature/branch-name into main"
- Pushing the Merged Changes:
Push the updated main branch to GitHub:
git push- Alternatively, you can open a Pull Request on GitHub to merge your feature branch into main. This is recommended for collaboration and for keeping a clear history of code reviews and merges.
Full reference documentation for all JavaScript classes and functions in this project is auto-generated using JSDoc and the docdash template.
View the full JavaScript JSDoc Documentation
Any changes to the JavaScript code or JSDoc comments can be regenerated to the documentation using the following command in the terminal:
npx jsdoc assets/js -r -d docs -t ./node_modules/docdashassets/js— your JavaScript source folder-r— recursive (includes subfolders)-d docs— output folder for documentation-t ./node_modules/docdash— use the docdash template
After running this command, commit and push the updated docs/ folder to keep the online documentation up to date.
References:
The website has been thoroughly tested to ensure functionality, accessibility, and responsiveness across devices and browsers. All HTML, CSS, and JavaScript have passed validation checks without errors, and Lighthouse scores are excellent for performance, accessibility, best practices, and SEO.
During development, I documented key troubleshooting steps, challenging issues, and their solutions to provide transparency and aid future maintenance. Manual testing was performed for all major features, and automated JavaScript testing with Jest is planned to further ensure code reliability.
For a detailed breakdown of the testing process—including validation results, Lighthouse scores, bug fixes, troubleshooting notes — please refer to TESTING.md.
During development, I researched the Canvas API to explore more advanced bat animations and dynamic backgrounds. Due to project scope and deadlines, full Canvas integration was deferred. However, I plan to continue studying the Canvas API to enhance future versions of the game with layered animations, scaling effects, and smoother sprite control.
To expand the interactivity of Echoes of the Crystal Cave, I plan to implement Web MIDI API functionality. This would allow players to connect a MIDI controller (such as a Novation Launchpad) to the game.
How it would work:
Crystal Layout Mirroring: The crystals' colours and glow states will be reflected on the physical controller's pads.
Example Images:
Hardware Input:
- Players could tap their Launchpad buttons instead of clicking or tapping on screen or the keyboard A, W, S, E, D keys.
- The game will listen for MIDI input events and trigger the corresponding crystal animations and sounds.
Real-Time Feedback: Correct inputs would trigger light animations and sounds on the hardware in sync with the game.
Alongside traditional memory gameplay, I aim to introduce an optional Rhythm Memory Mode:
- Players must match the crystal sequence and the beat of a background track.
- Audio cues and visual feedback will be precisely timed using the Web Audio API.
- Light effects (on-screen and on hardware) would pulse rhythmically to guide the player.
This would combine memory skills with timing accuracy, offering a fresh twist for players who enjoy rhythm games.
🎯 Target Audience The expanded features are designed to appeal to a broad audience:
- Casual gamers who enjoy accessible memory games with a musical twist.
- Music enthusiasts, DJs, and producers who appreciate MIDI technology and rhythm challenges.
- Parents who want to introduce their children to music creation in a fun way.
- Players of all ages who enjoy games that blend creativity, sound, and visual charm.
The goal is to create an experience that is easy to pick up but rewarding to master, and that bridges the gap between gameplay and musical creativity.
I plan to implement an achievements system to reward players for reaching milestones, such as completing levels, achieving high scores, or discovering hidden features. This will encourage replayability and provide a sense of accomplishment. The achievements could be displayed in a dedicated modal with mystery badges that unlock as players progress.
- Example Achievements:
- First Echo - Complete your first level.
- Crystal Apprentice - Reach level 5.
- Brucey's Blessing - Play the game with the name 'Brucey' for a special Easter egg.
- Following the successful refactor of the audio logic into a dedicated
AudioManagermodule, I plan to continue modularising the codebase. This will improve maintainability, scalability, and readability as the project grows.
- Based on feedback from JSHint metrics, I have identified that some functions — such as the main initialisation function that sets up event listeners and UI after the DOM loads — have a cyclomatic complexity value of 10, which is at the upper limit of recommended maintainability.
- I understand that this function’s complexity is due to handling many responsibilities (UI setup, event binding, game logic) in one place.
- In future development, I plan to refactor this and other complex functions (as part of ongoing modularisation) to reduce their complexity, improve readability, and make the codebase easier to understand and maintain for both myself and other developers.
- This will involve breaking down large functions into smaller, single-purpose functions and ensuring each module has a clear responsibility.
- I intend to improve JSDoc comments throughout the codebase to provide clearer documentation and enhance the quality of the generated output using Docdash.
-
I recognise the value of setting up automated unit tests, especially with future refactors and new features in mind. As the codebase becomes more modular, testing will help make sure that existing functionality stays intact.
-
I plan to use Jest for this, taking advantage of its built-in jsdom environment to test both core logic and DOM-related code.
-
These tests will help catch bugs earlier, support future development, and act as regression tests to prevent issues when making bigger changes — like modularisation or integrating the Web MIDI API.
- Pixel Art Bat Sprite by Caz Creates Games - Brucey the bat sprite used in the game.
- UI Asset Pack by Samuel Tome - UI icons used in the game.
- UI Buttons by Totus Lotus - UI buttons used in the game.
- Pixel Art Cave Background by MugenenCount - Background cave design used in the game (modified).
- Pixel Art Crystals - Crystals used in the game.
- Pixel Cave Wall Tileset by Ansimuz- Environment tileset used in the game.
- Speech Bubble by Just a Joke - Speech bubble used in the game.
- Jersey 20 by Sarah Cadigan-Fried - Primary font used in the game.
- Handjet by Rosetta, David Březina - Secondary font used in the game.
Throughout development, I consulted a wide range of online resources, tutorials, and community posts. Key references are grouped below by topic.
- Should I break up a large JavaScript file? (Quora)
- JavaScript Module Pattern In-Depth
- How to use ES6 Modules to separate your JavaScript
- MDN: ES6 Modules
- Best practices for using and linking multiple JS files (Reddit)
- Exploring globalThis in JavaScript
- MDN: Property Accessors
- Singleton Pattern in JavaScript (freeCodeCamp)
- What is globalThis? (LogRocket)
- JavaScript ES6 Modules - The Odin Project
- Web Audio API: Changing the Volume of a Sound (web.dev)
- Web Audio API Intro (web.dev)
- Standardized Audio Context (GitHub)
- Web Audio API Best Practices (MDN)
- Web Audio API Book (free) This is a fantastic free resource!
- Dealing with Latency (Jamie On Keys)
- Unlock Web Audio in Safari for iOS and macOS
- Web Audio on iOS Issues (HTML5 Game Devs)
- Webkit AudioContext Code
- CSS Glow Effect for Images (Stack Overflow)
- CSS Fade-In Animation (HubSpot)
- Flickering Neon Sign Effect (CodePen)
- Flickering Lamp Effect (CodePen)
- Vanilla Modal Example (CodePen)
- Modal Popup Example (CodexWorld)
- CSS Tricks: Styling Modals
- FreeCodeCamp: How to Build a Modal with JavaScript
- JSDoc Official Site
- JSDoc: The Ultimate Guide
- Document Your JavaScript Code with JSDoc (dev.to)
- Write Better, Faster, and Self-Documenting Tag Management (JSDoc)
- Creating Better JSDoc Documentation
- docdash Template
- Code Institute — For providing a supportive course and community that enabled me to build this project.
- Code Institute course content — The course materials, especially the Python Tutor lessons and the "Love Maths" project, were invaluable for understanding core programming concepts and structuring my own project.
- Code Institute Slack Community — An invaluable resource for advice, encouragement, and troubleshooting throughout the project.
- Marko Tot — Code Institute facilitator, for hosting weekly stand-up calls and sharing practical resources and guidance — especially around focusing on MVP features, meeting project deadlines, and giving constructive feedback.
- Wallace Green — Fellow student, for generous feedback, sharing helpful books and websites, and supporting my project’s development.
- Dan Hamilton — My mentor, for his encouragement and expert advice on coding best practices and audio implementation (particularly on iOS), and for sharing insights into industry standards.
- My brother — For insightful discussions on JavaScript architecture and file organisation, and for sharing his professional experience as a software developer.
Thank you all for your support, expertise, and encouragement!












































