diff --git a/emscripten/.gitignore b/emscripten/.gitignore
index 1188e3d9..1a71483e 100644
--- a/emscripten/.gitignore
+++ b/emscripten/.gitignore
@@ -5,3 +5,5 @@ espeakng_data_package.js
glue.*
espeakng.worker.*
pthread-main.js
+!demo.html
+!Makefile
diff --git a/emscripten/Makefile b/emscripten/Makefile
new file mode 100644
index 00000000..0f70489d
--- /dev/null
+++ b/emscripten/Makefile
@@ -0,0 +1,139 @@
+#
+# Copyright (C) 2014-2016 Eitan Isaacson
+# Copyright (C) 2016 Alberto Pettarin
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see: .
+#
+
+# NOTE: variables specific to espeak-ng + emscripten starts with "EM_"
+
+# NOTE: set to 1 to debug or to speed emscripten up while developing.
+# If the EM_DEBUG environment variable is set,
+# the value specified here will be ignored.
+EM_DEBUG ?= 0
+ifneq ($(EM_DEBUG), 1)
+ CXXFLAGS+=-O3
+endif
+
+
+
+###############################################################################
+# WARNING: modify code below this line at your own risk!
+###############################################################################
+
+# NOTE: sanity check
+ifndef EMSCRIPTEN
+ $(error EMSCRIPTEN var not set. You must use emmake to run this Makefile!)
+endif
+
+# NOTE: in the emscripten virtual FS,
+# this is the location of the eSpeak-ng data files,
+# if we configure with "./configure --prefix=/usr"
+EM_VIRTUAL_PATH_ESPEAKNG_DATA=/usr/share/espeak-ng-data
+
+# NOTE: emmake will replace EMSCRIPTEN with the actual root directory
+# of the emscripten tools inside the emscripten SDK directory
+EM_WEBIDL_BINDER=python $(EMSCRIPTEN)/tools/webidl_binder.py
+EM_FILE_PACKAGER=python $(EMSCRIPTEN)/tools/file_packager.py
+
+# NOTE: libespeak-ng.so compiled to LLVM IR code
+EM_LIBESPEAKNG_SO=../src/.libs/libespeak-ng.so
+
+# NOTE: glue code files
+EM_GLUE_PREFIX=glue
+EM_GLUE_IDL=espeakng_glue.idl
+EM_GLUE_OBJ=espeakng_glue.o
+EM_GLUE_CPP=espeakng_glue.cpp
+EM_GLUE_AUTOGEN_CPP=glue.cpp
+EM_GLUE_AUTOGEN_JS=glue.js
+
+# NOTE: preload espeak-ng-data directory...
+EM_DATA_DIR=../espeak-ng-data
+# NOTE: ... but exclude these subdirectories/files
+EM_EXCLUDE_DATA=../espeak-ng-data/mbrola_ph ../espeak-ng-data/phondata-manifest
+
+# NOTE: pre/post JS files
+EM_PRE_JS=pre.js
+EM_POST_JS=post.js
+
+# NOTE: output files
+EM_ESPEAKNG_DATA_PACKAGE_JS=espeakng_data_package.js
+EM_WORKER_DATA=js/espeakng.worker.data
+EM_WORKER_JS=js/espeakng.worker.js
+EM_PTHREAD_MAIN_JS=js/pthread-main.js
+
+# NOTE: intermediate objects
+EM_OBJS=$(EM_GLUE_OBJ) $(EM_LIBESPEAKNG_SO)
+EM_ALL_PRE_JS=$(EM_PRE_JS) $(EM_ESPEAKNG_DATA_PACKAGE_JS)
+EM_ALL_POST_JS=$(EM_GLUE_AUTOGEN_JS) $(EM_POST_JS)
+
+# NOTE: compile without async, i.e. with synchronous output
+#
+# ./emconfigure ./configure --prefix=/usr --without-async
+# ./emmake make
+CXXFLAGS+=-DESPEAK_DATA_PATH=\"$(EM_VIRTUAL_PATH_ESPEAKNG_DATA)\"
+CXXFLAGS+=-I ./ -I ../ -I ../src/include/espeak-ng
+
+# NOTE: so far, pthread is not supported in any browser
+# except Firefox Nightly.
+# If we want to enable pthread in the future,
+# we must append "-s USE_PTHREADS=1" to CXXFLAGS
+# and pass that to emconfigure and emmake.
+# If enabled, js/pthread-main.js will be created as well.
+#
+#CXXFLAGS+=-s USE_PTHREADS=1
+
+# NOTE: extra flags for emscripten
+EM_CXXFLAGS=-s RESERVED_FUNCTION_POINTERS=2 --memory-init-file 0
+
+
+
+###############################################################################
+# NOTE: actual targets
+###############################################################################
+
+all: $(EM_WORKER_JS)
+
+$(EM_WORKER_DATA):
+ $(EM_FILE_PACKAGER) $@ \
+ --js-output=$(EM_ESPEAKNG_DATA_PACKAGE_JS) \
+ --preload $(EM_DATA_DIR)@$(EM_VIRTUAL_PATH_ESPEAKNG_DATA) \
+ $(patsubst %,--exclude %,$(EM_EXCLUDE_DATA))
+
+$(EM_ESPEAKNG_DATA_PACKAGE_JS): $(EM_WORKER_DATA)
+
+$(EM_GLUE_AUTOGEN_CPP): $(EM_GLUE_IDL)
+ $(EM_WEBIDL_BINDER) $(EM_GLUE_IDL) $(EM_GLUE_PREFIX)
+
+$(EM_GLUE_AUTOGEN_JS): $(EM_GLUE_AUTOGEN_CPP)
+
+$(EM_GLUE_OBJ): $(EM_GLUE_CPP)
+
+$(EM_WORKER_JS): $(EM_GLUE_AUTOGEN_CPP) $(EM_OBJS) $(EM_ALL_PRE_JS) $(EM_ALL_POST_JS)
+ $(CXX) $(CXXFLAGS) \
+ $(EM_CXXFLAGS) \
+ $(EM_OBJS) \
+ $(patsubst %,--pre-js %,$(EM_ALL_PRE_JS)) \
+ $(patsubst %,--post-js %,$(EM_ALL_POST_JS)) \
+ -o $@
+
+clean-intermediate:
+ rm -f *.o *.out *.pkl $(EM_GLUE_AUTOGEN_CPP) $(EM_GLUE_AUTOGEN_JS) $(EM_ESPEAKNG_DATA_PACKAGE_JS)
+
+clean: clean-intermediate
+ rm -f $(EM_WORKER_DATA) $(EM_WORKER_JS) $(EM_PTHREAD_MAIN_JS)
+
+help:
+ echo "Available targets: all clean clean-intermediate help"
+
diff --git a/emscripten/demo.html b/emscripten/demo.html
new file mode 100644
index 00000000..3125eba9
--- /dev/null
+++ b/emscripten/demo.html
@@ -0,0 +1,118 @@
+
+
+
+
+
+ espeakng.js Demo
+
+
+
+
+
+
+
Loading eSpeak-ng worker and data...
+
+
+ espeakng.js Demo
+
+
+
+