diff --git a/README.md b/README.md
index 92442418c33ead139e0f8fffbcc352dd3704cc96..3d3d479a52dbce8b287ee9fd09551e56f5e87828 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,25 @@
 
 A Game Boy emulator that is written in Rust 🦀.
 
+## Build
+
+### WASM for Node.js
+
+```bash
+cargo install wasm-pack
+wasm-pack build --release --target=nodejs -- --features wasm
+```
+
+### WASM for Web
+
+```bash
+cargo install wasm-pack
+wasm-pack build --release --target=web --out-dir=examples/web/lib -- --features wasm
+cd examples/web
+npm install && npm run build
+cd dist && python3 -m http.server
+```
+
 ## Inspiration
 
 ### Documentation
diff --git a/src/gb.rs b/src/gb.rs
index f1ae2ce11a196be9869eebd7a1663d2696617118..e918ba68414c40cf8a7aba37695b63136b5a7f81 100644
--- a/src/gb.rs
+++ b/src/gb.rs
@@ -5,11 +5,17 @@ use crate::{
     util::read_file,
 };
 
+#[cfg(feature = "wasm")]
+use wasm_bindgen::prelude::*;
+
+#[cfg_attr(feature = "wasm", wasm_bindgen)]
 pub struct GameBoy {
     cpu: Cpu,
 }
 
+#[cfg_attr(feature = "wasm", wasm_bindgen)]
 impl GameBoy {
+    #[cfg_attr(feature = "wasm", wasm_bindgen(constructor))]
     pub fn new() -> GameBoy {
         let ppu = Ppu::new();
         let mmu = Mmu::new(ppu);
@@ -31,6 +37,22 @@ impl GameBoy {
         self.ppu().clock(cycles)
     }
 
+    pub fn load_rom(&mut self, path: &str) {
+        let data = read_file(path);
+        self.cpu.mmu().write_rom(0x0000, &data);
+    }
+
+    pub fn load_boot(&mut self, path: &str) {
+        let data = read_file(path);
+        self.cpu.mmu().write_boot(0x0000, &data);
+    }
+
+    pub fn load_boot_default(&mut self) {
+        self.load_boot("./res/dmg_rom.bin");
+    }
+}
+
+impl GameBoy {
     pub fn cpu(&mut self) -> &mut Cpu {
         &mut self.cpu
     }
@@ -46,18 +68,4 @@ impl GameBoy {
     pub fn frame_buffer(&mut self) -> &Box<[u8; FRAME_BUFFER_SIZE]> {
         &(self.ppu().frame_buffer)
     }
-
-    pub fn load_rom(&mut self, path: &str) {
-        let data = read_file(path);
-        self.cpu.mmu().write_rom(0x0000, &data);
-    }
-
-    pub fn load_boot(&mut self, path: &str) {
-        let data = read_file(path);
-        self.cpu.mmu().write_boot(0x0000, &data);
-    }
-
-    pub fn load_boot_default(&mut self) {
-        self.load_boot("./res/dmg_rom.bin");
-    }
 }