diff --git a/.github/workflows/ports_javascript.yml b/.github/workflows/ports_javascript.yml
new file mode 100644
index 0000000000..244dc966aa
--- /dev/null
+++ b/.github/workflows/ports_javascript.yml
@@ -0,0 +1,24 @@
+name: javascript port
+
+on:
+  push:
+  pull_request:
+    paths:
+      - '.github/workflows/*.yml'
+      - 'tools/**'
+      - 'py/**'
+      - 'extmod/**'
+      - 'lib/**'
+      - 'ports/javascript/**'
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install packages
+      run: source tools/ci.sh && ci_javascript_setup
+    - name: Build
+      run: source tools/ci.sh && ci_javascript_build
+    - name: Run tests
+      run: source tools/ci.sh && ci_javascript_run_tests
diff --git a/tools/ci.sh b/tools/ci.sh
index 6d7c643f5d..a82eedd20d 100755
--- a/tools/ci.sh
+++ b/tools/ci.sh
@@ -138,6 +138,24 @@ function ci_esp8266_build {
     make ${MAKEOPTS} -C ports/esp8266 BOARD=GENERIC_1M
 }
 
+########################################################################################
+# ports/javascript
+
+function ci_javascript_setup {
+    git clone https://github.com/emscripten-core/emsdk.git
+    (cd emsdk && ./emsdk install latest && ./emsdk activate latest)
+}
+
+function ci_javascript_build {
+    source emsdk/emsdk_env.sh
+    make ${MAKEOPTS} -C ports/javascript
+}
+
+function ci_javascript_run_tests {
+    # This port is very slow at running, so only run a few of the tests.
+    (cd tests && MICROPY_MICROPYTHON=../ports/javascript/node_run.sh ./run-tests.py -j1 basics/builtin_*.py)
+}
+
 ########################################################################################
 # ports/mimxrt