chore: README.md is same in repo as package
This commit is contained in:
parent
8774bc8092
commit
0704c1e2ec
5 changed files with 257 additions and 136 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,6 +1,9 @@
|
|||
node_modules/
|
||||
dist/
|
||||
|
||||
# generated at publish time from the root README.md (see scripts/publish-lib.js)
|
||||
lib/README.md
|
||||
|
||||
.claude
|
||||
|
||||
*.*~
|
||||
|
|
|
|||
215
lib/README.md
215
lib/README.md
|
|
@ -1,146 +1,24 @@
|
|||
# Build your own web browser game with `mnswpr`
|
||||
# Play Minesweeper Online for Free
|
||||
[](https://app.netlify.com/sites/mnswpr/deploys)
|
||||
|
||||
Have you ever wondered how games on a web browser are built? Believe it or not, anything you see on a web browser can be built by anyone. That's why the web is so great: it is free and open for everyone to enjoy!
|
||||
Play it here: [mnswpr.com](https://mnswpr.com). This is the classic game **Minesweeper** built with vanilla web technologies (i.e., no framework dependency).
|
||||
|
||||
In this guide, we will use **mnswpr** as a simple building block for you to build your own browser game. I will walk you through the steps to create your own Minesweeper browser game from scratch.
|
||||
<!-- TODO: replace with the actual screenshot/GIF once supplied (confirm final path/filename) -->
|
||||

|
||||
|
||||
If you want to skip to the ending, all the code are in this repository: [minimal-mnswpr](https://github.com/ayo-run/minimal-mnswpr)
|
||||
Technology Stack: HTML, JS, and CSS; [Google Firebase](https://firebase.google.com) for leader board store; [Netlify](https://netlify.com) for hosting
|
||||
|
||||
First, let's go through the requirements.
|
||||
## Usage
|
||||
|
||||
## Requirements
|
||||
The web is a wonderful, free, and open platform to create and distribute value. You can use **mnswpr** in different ways:
|
||||
|
||||
It is assumed that you have some knowledge in HTML and JavaScript. You can easily read about this and play around examples online. Some knowledge on using a terminal and a text editor is also required.
|
||||
- as a deployed [web app](https://mnswpr.com)
|
||||
- as a [library](https://npmx.dev/package/@ayo-run/mnswpr) with `npm i @ayo-run/mnswpr`
|
||||
- as a `web component` (coming soon).
|
||||
|
||||
You will need a computer with [node.js](https://nodejs.org/en/download).
|
||||
|
||||
If you are familiar with HTML and JavaScript, and has a computer with `node.js` installed... let's now start with the project setup!
|
||||
|
||||
## Project Setup
|
||||
|
||||
Open the terminal and confirm that you have `node.js`.
|
||||
|
||||
```bash
|
||||
# verify the node.js version
|
||||
node --version # Should print the version
|
||||
```
|
||||
Next, create a directory where we'll write some code for your game.
|
||||
|
||||
```bash
|
||||
# on mac or linux
|
||||
mkdir my-game
|
||||
|
||||
cd my-game
|
||||
```
|
||||
Once your terminal is in the new directory `my-game`, we will initialize the JavaScript project using the Node Package Manager or `npm`. Type the following on your terminal:
|
||||
|
||||
```bash
|
||||
npm init
|
||||
```
|
||||
|
||||
This will start the `npm` initialization interface, which will ask you some questions. You can think of what you want to answer, but if you want to go with the defaults, you can just press the `Enter` key repeatedly for each until the questions are done.
|
||||
|
||||
The last question will ask you if everything is OK:
|
||||
|
||||
```bash
|
||||
Is this OK? (yes)
|
||||
|
||||
# Don't be shy, you can just press ENTER again
|
||||
```
|
||||
|
||||
Next, we will add `vite` as a development tool for bundling and as a development server.
|
||||
|
||||
<details>
|
||||
<summary>Additional info on Vite...</summary>
|
||||
Making web pages work in different browsers often brings challenges brought about by differences in technological implementations and limitations. Vite helps us so that our code will work in different environments without us worrying about issues in compatibility and performance. </details><br />
|
||||
|
||||
```bash
|
||||
npm i -D vite
|
||||
```
|
||||
|
||||
Now that the JS project is initialized and we have a development environment with `vite`, we will install **mnswpr** as a dependency:
|
||||
|
||||
```bash
|
||||
npm i @ayo-run/mnswpr
|
||||
```
|
||||
|
||||
Finally, you can run the installed `vite` dev server by running the following:
|
||||
|
||||
```bash
|
||||
# `npx` here is the execute command for npm
|
||||
npx vite # will run the vite dev server
|
||||
```
|
||||
|
||||
Vite will now show the address you can type to your browser to see your project. It will show something like this:
|
||||
|
||||
```bash
|
||||
VITE v8.0.3 ready in 128 ms
|
||||
|
||||
➜ Local: http://localhost:5173/
|
||||
➜ Network: use --host to expose
|
||||
➜ press h + enter to show help
|
||||
```
|
||||
|
||||
You can then open the "Local" address (e.g., http://localhost:5173) on your browser.
|
||||
|
||||
Congratulations. You now have your project setup! It's time to write some code.
|
||||
|
||||
## Write Some Code
|
||||
|
||||
Believe it or not, you have done the hard part. Now we start the fun part: putting the parts of your game together!
|
||||
|
||||
There are mainly 3 kinds of code that work together in a web page: HTML, JavaScript or JS, and Cascading Style Sheets or CSS.
|
||||
|
||||
In this guide, we work mostly with HTML & JS to focus on the basics.
|
||||
|
||||
### The HTML
|
||||
|
||||
Using your favorite text editor, create a file named `index.html` with the following content:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>My Minesweeper Game</title>
|
||||
<style>
|
||||
html, body {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>My Minesweeper Game</h1>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Additional info on `index.html`</summary>
|
||||
The file name `index.html` is important. It is the default file that Web browsers look for in any given path/directory as the web page it will show.
|
||||
</details>
|
||||
<br />
|
||||
|
||||
If you have your browser opened to the Local address `vite` just showed earlier, you should see your very first web page with a title **My Minesweeper Game**
|
||||
|
||||
Exciting right? You can try editing the text inside `<h1>...</h1>` to see the web page change as well. :)
|
||||
|
||||
Take a second to read through the content of your `index.html`. The `<div>` element there with `id="app"` attribute will be where the game board will be rendered.
|
||||
|
||||
Now we just need JavaScript to do this. You will find the `<script>` tag that has the `src="main.js"` attribute, which means the web page is ready to load that JavaScript... but this file doesn't exist yet. So let's write the code for that.
|
||||
|
||||
### The JavaScript
|
||||
|
||||
Create a new file named `main.js` with the following content:
|
||||
Using it as a library takes only a few lines — mount it onto any element by `id`:
|
||||
|
||||
```js
|
||||
/**
|
||||
* main.js
|
||||
*/
|
||||
import '@ayo-run/mnswpr/mnswpr.css'
|
||||
import mnswpr from '@ayo-run/mnswpr'
|
||||
|
||||
|
|
@ -148,8 +26,75 @@ const game = new mnswpr('app')
|
|||
game.initialize()
|
||||
```
|
||||
|
||||
When you create this `main.js` file, the dev server will instantly update the web page for you and you should now see your minesweeper browser game!
|
||||
## How to Play
|
||||
|
||||
The goal is to reveal every safe cell without detonating a mine. Your **first click is always safe**.
|
||||
|
||||
- **Left click** — reveal a cell
|
||||
- **Right click** — flag / unflag a suspected mine
|
||||
- **Left + right click together** (chording) — reveal the neighbors of a satisfied number
|
||||
- **Touch** — tap to reveal, long-press to flag
|
||||
|
||||
## Tooling
|
||||
The project has gone through years of existence. It started from 2019 when tooling was massively different. I have [modernized it](https://elk.zone/social.ayco.io/@ayo/116333804543330938) since and have witnessed how much easier and faster it is to build now - even without web frameworks or LLMs!
|
||||
|
||||
As of now the tooling I use are:
|
||||
- [Vite](https://vite.dev/) for bundling and development server
|
||||
- [Eslint](https://eslint.org) for JS linting & [CSS linting](https://eslint.org/blog/2025/02/eslint-css-support/)
|
||||
- [ESLint Stylistic](https://eslint.style) for JS formatting
|
||||
- [Husky](https://typicode.github.io/husky/) for git hooks
|
||||
- [PNPM](https://pnpm.io/installation) for dependency & workspace management
|
||||
- and a bunch of automation using scripts and Continuous Integration actions
|
||||
|
||||
Because a big part of this project's purpose is to track how the software development industry evolves — and because it has come a long way in modernizing along the way — I now also use it as a **playground for coding agents**. It's a small, framework-free, well-scoped codebase, which makes it a great sandbox to see how AI agents read, reason about, and change real code. To help them get their bearings quickly, the repo ships an [`AGENTS.md`](./AGENTS.md) describing the architecture and conventions.
|
||||
|
||||
## Development
|
||||
To start development, you need [`node`](https://nodejs.org/en/download). I highly recommend [`pnpm`](https://pnpm.io/installation) to be used as well. Once you know you have this, you can do the following:
|
||||
1. Install dependencies: `pnpm i`
|
||||
2. Start the dev server: `pnpm run dev`
|
||||
|
||||
The rest of the everyday commands:
|
||||
|
||||
```bash
|
||||
pnpm test # run the Vitest suite
|
||||
pnpm lint # ESLint (JS + CSS)
|
||||
pnpm lint:fix # ESLint with autofix
|
||||
pnpm build # build the website
|
||||
pnpm build:lib # build the publishable library
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! See [`AGENTS.md`](./AGENTS.md) for the architecture, conventions, and release workflow before opening a pull request.
|
||||
|
||||
## You just want to play?
|
||||
|
||||
*👉 The live site is here: [mnswpr.com](https://mnswpr.com)*
|
||||
|
||||
## Background
|
||||
One day, while working in my home office, I heard loud and fast mouse clicks coming from our bedroom. It's my wife, playing her favorite game (Minesweeper) on a crappy website full of advertisements.
|
||||
|
||||
I can't allow this, it's a security issue. 🤣
|
||||
|
||||
But it is also an opportunity.
|
||||
|
||||
I wanted to give her the same game, with a similar leader board she can dominate. And this is also a chance for me to dig deeper into vanilla JS.
|
||||
|
||||
Can I make a page with complex interactions (more on this later) without any library dependency?
|
||||
|
||||
## What I have learned:
|
||||
1. JS is awesome ✨
|
||||
1. We don't always *need* JS frameworks (or TS) ✨
|
||||
1. Even subtle UI changes *can improve* user gameplay experience ✨
|
||||
1. There's more ways to break your app than you are initially aware of ✨
|
||||
1. Competition motivates users to use your app more ✨
|
||||
1. Hash in bundled filenames helps avoid issues with browser caching (when shipping versions fast) ✨
|
||||
|
||||
|
||||
|
||||
## License
|
||||
|
||||
[BSD-2-Clause](./LICENSE)
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
157
lib/TUTORIAL.md
Normal file
157
lib/TUTORIAL.md
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
# Build your own web browser game with `mnswpr`
|
||||
|
||||
Have you ever wondered how games on a web browser are built? Believe it or not, anything you see on a web browser can be built by anyone. That's why the web is so great: it is free and open for everyone to enjoy!
|
||||
|
||||
In this guide, we will use **mnswpr** as a simple building block for you to build your own browser game. I will walk you through the steps to create your own Minesweeper browser game from scratch.
|
||||
|
||||
If you want to skip to the ending, all the code are in this repository: [minimal-mnswpr](https://github.com/ayo-run/minimal-mnswpr)
|
||||
|
||||
First, let's go through the requirements.
|
||||
|
||||
## Requirements
|
||||
|
||||
It is assumed that you have some knowledge in HTML and JavaScript. You can easily read about this and play around examples online. Some knowledge on using a terminal and a text editor is also required.
|
||||
|
||||
You will need a computer with [node.js](https://nodejs.org/en/download).
|
||||
|
||||
If you are familiar with HTML and JavaScript, and has a computer with `node.js` installed... let's now start with the project setup!
|
||||
|
||||
## Project Setup
|
||||
|
||||
Open the terminal and confirm that you have `node.js`.
|
||||
|
||||
```bash
|
||||
# verify the node.js version
|
||||
node --version # Should print the version
|
||||
```
|
||||
Next, create a directory where we'll write some code for your game.
|
||||
|
||||
```bash
|
||||
# on mac or linux
|
||||
mkdir my-game
|
||||
|
||||
cd my-game
|
||||
```
|
||||
Once your terminal is in the new directory `my-game`, we will initialize the JavaScript project using the Node Package Manager or `npm`. Type the following on your terminal:
|
||||
|
||||
```bash
|
||||
npm init
|
||||
```
|
||||
|
||||
This will start the `npm` initialization interface, which will ask you some questions. You can think of what you want to answer, but if you want to go with the defaults, you can just press the `Enter` key repeatedly for each until the questions are done.
|
||||
|
||||
The last question will ask you if everything is OK:
|
||||
|
||||
```bash
|
||||
Is this OK? (yes)
|
||||
|
||||
# Don't be shy, you can just press ENTER again
|
||||
```
|
||||
|
||||
Next, we will add `vite` as a development tool for bundling and as a development server.
|
||||
|
||||
<details>
|
||||
<summary>Additional info on Vite...</summary>
|
||||
Making web pages work in different browsers often brings challenges brought about by differences in technological implementations and limitations. Vite helps us so that our code will work in different environments without us worrying about issues in compatibility and performance. </details><br />
|
||||
|
||||
```bash
|
||||
npm i -D vite
|
||||
```
|
||||
|
||||
Now that the JS project is initialized and we have a development environment with `vite`, we will install **mnswpr** as a dependency:
|
||||
|
||||
```bash
|
||||
npm i @ayo-run/mnswpr
|
||||
```
|
||||
|
||||
Finally, you can run the installed `vite` dev server by running the following:
|
||||
|
||||
```bash
|
||||
# `npx` here is the execute command for npm
|
||||
npx vite # will run the vite dev server
|
||||
```
|
||||
|
||||
Vite will now show the address you can type to your browser to see your project. It will show something like this:
|
||||
|
||||
```bash
|
||||
VITE v8.0.3 ready in 128 ms
|
||||
|
||||
➜ Local: http://localhost:5173/
|
||||
➜ Network: use --host to expose
|
||||
➜ press h + enter to show help
|
||||
```
|
||||
|
||||
You can then open the "Local" address (e.g., http://localhost:5173) on your browser.
|
||||
|
||||
Congratulations. You now have your project setup! It's time to write some code.
|
||||
|
||||
## Write Some Code
|
||||
|
||||
Believe it or not, you have done the hard part. Now we start the fun part: putting the parts of your game together!
|
||||
|
||||
There are mainly 3 kinds of code that work together in a web page: HTML, JavaScript or JS, and Cascading Style Sheets or CSS.
|
||||
|
||||
In this guide, we work mostly with HTML & JS to focus on the basics.
|
||||
|
||||
### The HTML
|
||||
|
||||
Using your favorite text editor, create a file named `index.html` with the following content:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>My Minesweeper Game</title>
|
||||
<style>
|
||||
html, body {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>My Minesweeper Game</h1>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Additional info on `index.html`</summary>
|
||||
The file name `index.html` is important. It is the default file that Web browsers look for in any given path/directory as the web page it will show.
|
||||
</details>
|
||||
<br />
|
||||
|
||||
If you have your browser opened to the Local address `vite` just showed earlier, you should see your very first web page with a title **My Minesweeper Game**
|
||||
|
||||
Exciting right? You can try editing the text inside `<h1>...</h1>` to see the web page change as well. :)
|
||||
|
||||
Take a second to read through the content of your `index.html`. The `<div>` element there with `id="app"` attribute will be where the game board will be rendered.
|
||||
|
||||
Now we just need JavaScript to do this. You will find the `<script>` tag that has the `src="main.js"` attribute, which means the web page is ready to load that JavaScript... but this file doesn't exist yet. So let's write the code for that.
|
||||
|
||||
### The JavaScript
|
||||
|
||||
Create a new file named `main.js` with the following content:
|
||||
|
||||
```js
|
||||
/**
|
||||
* main.js
|
||||
*/
|
||||
import '@ayo-run/mnswpr/mnswpr.css'
|
||||
import mnswpr from '@ayo-run/mnswpr'
|
||||
|
||||
const game = new mnswpr('app')
|
||||
game.initialize()
|
||||
```
|
||||
|
||||
When you create this `main.js` file, the dev server will instantly update the web page for you and you should now see your minesweeper browser game!
|
||||
|
||||
|
||||
---
|
||||
|
||||
_Just keep building._<br>
|
||||
_A project by [Ayo](https://ayo.ayco.io)_
|
||||
|
|
@ -17,7 +17,7 @@
|
|||
"start": "vite app",
|
||||
"build": "vite build app",
|
||||
"build:lib": "vite build lib",
|
||||
"publish:lib": "cd lib && npm publish",
|
||||
"publish:lib": "node scripts/publish-lib.js",
|
||||
"release": "pnpm build:lib && pnpm -F @ayo-run/mnswpr run release && pnpm publish:lib",
|
||||
"build:preview": "pnpm -F app run build:preview",
|
||||
"prepare": "husky",
|
||||
|
|
|
|||
16
scripts/publish-lib.js
Normal file
16
scripts/publish-lib.js
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
// Publishes @ayo-run/mnswpr to npm using the root project README.md as the
|
||||
// package's README (what npmjs.com displays).
|
||||
//
|
||||
// lib/README.md is a generated copy (gitignored) — the source of truth is the
|
||||
// root README.md. The library's own guide lives in lib/TUTORIAL.md.
|
||||
import { execSync } from 'node:child_process'
|
||||
import { copyFileSync } from 'node:fs'
|
||||
import { resolve } from 'node:path'
|
||||
|
||||
const root = resolve(import.meta.dirname, '..')
|
||||
const libDir = resolve(root, 'lib')
|
||||
|
||||
console.log('Copying root README.md into lib/ for the published package')
|
||||
copyFileSync(resolve(root, 'README.md'), resolve(libDir, 'README.md'))
|
||||
|
||||
execSync('npm publish', { cwd: libDir, stdio: 'inherit' })
|
||||
Loading…
Reference in a new issue