diff --git a/demo/modules/README.md b/demo/modules/README.md
new file mode 100644
index 0000000..f13c964
--- /dev/null
+++ b/demo/modules/README.md
@@ -0,0 +1,76 @@
+# Module import demos
+
+## Intro
+pas2js can convert the $linklib directive to a JS import statement:
+
+The following:
+
+```delphi
+{$linklib ./modules/canvas.js canvas}
+```
+
+is converted to
+```js
+import * as canvas from "./modules/canvas.js";
+```
+If the alias is omitted, one is constructed for you:
+
+```delphi
+{$linklib ./modules/some-api.js}
+```
+is converted to
+```js
+import * as some_api from "./modules/some-api.js";
+```
+The import statements are always inserted in the main program.
+This is because modules are like windows libraries: self-contained programs,
+which only import and export well-defined symbols.
+
+For this reason, a new target "operating system" has been invented:
+the module.
+This means that you must compile with target module:
+
+```sh
+pas2js -Tmodule -Jirtl.js main.pp
+```
+
+The nodejs target will also work, but in the future the 2 targets may
+diverge.
+
+## Demos
+
+Each directory contains 1 demo. Compile with the command-line as above:
+
+```sh
+pas2js -Tmodule -Jirtl.js main.pp
+```
+
+### Basic
+
+This shows a simple program, no units, that uses the linklib directive to
+import a javascript module. It uses an external class definition to access
+the exported symbols from the modules.
+
+### Basic-Units
+
+This is the same as the Basic example, but the import definitions are split
+out in units.
+
+### Flat
+
+This shows a simple program, no units, that uses the linklib directive to
+import a javascript module. It uses only external 'name' definitions to access
+the exported symbols from the modules; no external class is used.
+
+### Flat-Units
+
+This is the same as the flat example, but the import definitions are split
+out in units.
+
+
+
+
+
+
+
+
diff --git a/demo/modules/basic-units/canvas.pp b/demo/modules/basic-units/canvas.pp
new file mode 100644
index 0000000..74a1b1c
--- /dev/null
+++ b/demo/modules/basic-units/canvas.pp
@@ -0,0 +1,28 @@
+{$mode objfpc}
+{$modeswitch externalclass}
+// filename export object alias
+{$linklib ./modules/canvas.js canvas}
+
+unit canvas;
+
+interface
+
+uses js, web;
+
+type
+ TCreateCanvasResult = class external name 'Object' (TJSObject)
+ ctx: TJSCanvasRenderingContext2D;
+ id : string;
+ end;
+
+ TCanvasAPI = class external name 'Object' (TJSObject)
+ function create (aID : String; AParent : TJSElement; aWidth,aHeight : Integer) : TCreateCanvasResult;
+ function createReportList(aWrapperID : String) : String;
+ end;
+
+Var
+ CanvasAPI : TCanvasAPI; external name 'canvas';
+
+implementation
+
+end.
\ No newline at end of file
diff --git a/demo/modules/basic-units/index.html b/demo/modules/basic-units/index.html
new file mode 100644
index 0000000..c064cec
--- /dev/null
+++ b/demo/modules/basic-units/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Basic JavaScript module example
+
+
+
+
+
+
+
diff --git a/demo/modules/basic-units/main.pp b/demo/modules/basic-units/main.pp
new file mode 100644
index 0000000..2e42710
--- /dev/null
+++ b/demo/modules/basic-units/main.pp
@@ -0,0 +1,17 @@
+{$mode objfpc}
+{$modeswitch externalclass}
+uses js, web, canvas, square;
+
+Var
+ MyCanvas : TCreateCanvasResult;
+ MyReportList : string;
+ MySquare2,MySquare1 : TDrawResult;
+
+begin
+ MyCanvas:=CanvasAPI.create('myCanvas', document.body, 480, 320);
+ MyreportList:=CanvasAPI.createReportList(myCanvas.id);
+ MySquare1:=SquareAPI.draw(myCanvas.ctx, 50, 50, 100, 'blue');
+ SquareAPI.reportArea(MySquare1.length, MyReportList);
+ SQuareAPI.reportPerimeter(MySquare1.length,MyReportList);
+ MySquare2:=SquareAPI.randomSquare(myCanvas.ctx);
+end.
\ No newline at end of file
diff --git a/demo/modules/basic-units/square.pp b/demo/modules/basic-units/square.pp
new file mode 100644
index 0000000..780380d
--- /dev/null
+++ b/demo/modules/basic-units/square.pp
@@ -0,0 +1,32 @@
+{$mode objfpc}
+{$modeswitch externalclass}
+// filename export object alias
+{$linklib ./modules/square.js square}
+
+unit square;
+
+interface
+
+uses js, web;
+
+Type
+ TDrawResult = class external name 'Object' (TJSObject)
+ length,x,y : Integer;
+ color : string;
+ end;
+
+ TSquareAPI = class external name 'Object' (TJSObject)
+ name : string;
+ // Default export
+ function randomsquare(aCtx : TJSCanvasRenderingContext2D) : TDrawResult; external name 'default';
+ function draw(aCtx : TJSCanvasRenderingContext2D; alength,x,y : Integer; color : string) : TDrawResult;
+ procedure reportArea(length : Integer; ListID : String);
+ procedure reportPerimeter(length : Integer; ListID : String);
+ end;
+
+var
+ SquareAPI : TSquareAPI; external name 'square';
+
+implementation
+
+end.
\ No newline at end of file
diff --git a/demo/modules/basic/index.html b/demo/modules/basic/index.html
new file mode 100644
index 0000000..c064cec
--- /dev/null
+++ b/demo/modules/basic/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Basic JavaScript module example
+
+
+
+
+
+
+
diff --git a/demo/modules/basic/main.pp b/demo/modules/basic/main.pp
new file mode 100644
index 0000000..f07bfe1
--- /dev/null
+++ b/demo/modules/basic/main.pp
@@ -0,0 +1,49 @@
+// filename export object alias
+{$linklib ./modules/canvas.js canvas}
+{$linklib ./modules/square.js square}
+{$mode objfpc}
+{$modeswitch externalclass}
+uses js, web;
+
+type
+ TCreateCanvasResult = class external name 'Object' (TJSObject)
+ ctx: TJSCanvasRenderingContext2D;
+ id : string;
+ end;
+
+ TCanvasAPI = class external name 'Object' (TJSObject)
+ function create (aID : String; AParent : TJSElement; aWidth,aHeight : Integer) : TCreateCanvasResult;
+ function createReportList(aWrapperID : String) : String;
+ end;
+
+ TDrawResult = class external name 'Object' (TJSObject)
+ length,x,y : Integer;
+ color : string;
+ end;
+
+ TSquareAPI = class external name 'Object' (TJSObject)
+ name : string;
+ // Default export
+ function randomsquare(aCtx : TJSCanvasRenderingContext2D) : TDrawResult; external name 'default';
+ function draw(aCtx : TJSCanvasRenderingContext2D; alength,x,y : Integer; color : string) : TDrawResult;
+ procedure reportArea(length : Integer; ListID : String);
+ procedure reportPerimeter(length : Integer; ListID : String);
+ end;
+
+var
+ CanvasAPI : TCanvasAPI; external name 'canvas';
+ SquareAPI : TSquareAPI; external name 'square';
+
+Var
+ MyCanvas : TCreateCanvasResult;
+ MyReportList : string;
+ MySquare2,MySquare1 : TDrawResult;
+
+begin
+ MyCanvas:=CanvasAPI.create('myCanvas', document.body, 480, 320);
+ MyreportList:=CanvasAPI.createReportList(myCanvas.id);
+ MySquare1:=SquareAPI.draw(myCanvas.ctx, 50, 50, 100, 'blue');
+ SquareAPI.reportArea(MySquare1.length, MyReportList);
+ SQuareAPI.reportPerimeter(MySquare1.length,MyReportList);
+ MySquare2:=SquareAPI.randomSquare(myCanvas.ctx);
+end.
\ No newline at end of file
diff --git a/demo/modules/flat-units/canvas.pp b/demo/modules/flat-units/canvas.pp
new file mode 100644
index 0000000..498d80f
--- /dev/null
+++ b/demo/modules/flat-units/canvas.pp
@@ -0,0 +1,22 @@
+{$linklib ./modules/canvas.js canvas}
+{$mode objfpc}
+{$modeswitch externalclass}
+unit canvas;
+
+interface
+
+uses js, web;
+
+Type
+
+ TCreateCanvasResult = class external name 'Object' (TJSObject)
+ ctx: TJSCanvasRenderingContext2D;
+ id : string;
+ end;
+
+function create (aID : String; AParent : TJSElement; aWidth,aHeight : Integer) : TCreateCanvasResult; external name 'canvas.create';
+function createReportList(aWrapperID : String) : String; external name 'canvas.createReportList';
+
+implementation
+
+end.
diff --git a/demo/modules/flat-units/index.html b/demo/modules/flat-units/index.html
new file mode 100644
index 0000000..c852c5c
--- /dev/null
+++ b/demo/modules/flat-units/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Basic Pas2JS JavaScript module example - flat API
+
+
+
+
+
+
+
diff --git a/demo/modules/flat-units/main.pp b/demo/modules/flat-units/main.pp
new file mode 100644
index 0000000..07b6544
--- /dev/null
+++ b/demo/modules/flat-units/main.pp
@@ -0,0 +1,16 @@
+// filename export object alias
+uses web,canvas, square;
+
+Var
+ MyCanvas : TCreateCanvasResult;
+ MyReportList : string;
+ MySquare2,MySquare1 : TDrawResult;
+
+begin
+ MyCanvas:=create('myCanvas', document.body, 480, 320);
+ MyreportList:=createReportList(myCanvas.id);
+ MySquare1:=draw(myCanvas.ctx, 50, 50, 100, 'blue');
+ reportArea(MySquare1.length, MyReportList);
+ reportPerimeter(MySquare1.length,MyReportList);
+ MySquare2:=randomSquare(myCanvas.ctx);
+end.
\ No newline at end of file
diff --git a/demo/modules/flat-units/square.pp b/demo/modules/flat-units/square.pp
new file mode 100644
index 0000000..d7242cb
--- /dev/null
+++ b/demo/modules/flat-units/square.pp
@@ -0,0 +1,28 @@
+{$linklib ./modules/square.js square}
+{$mode objfpc}
+{$modeswitch externalclass}
+unit square;
+
+interface
+
+uses js, web;
+
+Type
+ TDrawResult = class external name 'Object' (TJSObject)
+ length,x,y : Integer;
+ color : string;
+ end;
+
+// Square API
+
+var
+ name : string; external name 'square.name';
+
+function randomsquare(aCtx : TJSCanvasRenderingContext2D) : TDrawResult; external name 'square.default';
+function draw(aCtx : TJSCanvasRenderingContext2D; alength,x,y : Integer; color : string) : TDrawResult; external name 'square.draw';
+procedure reportArea(length : Integer; ListID : String); external name 'square.reportArea';
+procedure reportPerimeter(length : Integer; ListID : String); external name 'square.reportPerimeter';
+
+implementation
+
+end.
diff --git a/demo/modules/flat/index.html b/demo/modules/flat/index.html
new file mode 100644
index 0000000..c852c5c
--- /dev/null
+++ b/demo/modules/flat/index.html
@@ -0,0 +1,16 @@
+
+
+
+
+ Basic Pas2JS JavaScript module example - flat API
+
+
+
+
+
+
+
diff --git a/demo/modules/flat/main.pp b/demo/modules/flat/main.pp
new file mode 100644
index 0000000..9b8366f
--- /dev/null
+++ b/demo/modules/flat/main.pp
@@ -0,0 +1,47 @@
+// filename export object alias
+{$linklib ./modules/canvas.js canvas}
+{$linklib ./modules/square.js square}
+{$mode objfpc}
+{$modeswitch externalclass}
+uses js, web;
+
+// canvas API
+
+type
+ TCreateCanvasResult = class external name 'Object' (TJSObject)
+ ctx: TJSCanvasRenderingContext2D;
+ id : string;
+ end;
+
+function create (aID : String; AParent : TJSElement; aWidth,aHeight : Integer) : TCreateCanvasResult; external name 'canvas.create';
+function createReportList(aWrapperID : String) : String; external name 'canvas.createReportList';
+
+Type
+ TDrawResult = class external name 'Object' (TJSObject)
+ length,x,y : Integer;
+ color : string;
+ end;
+
+// Square API
+
+var
+ name : string; external name 'square.name';
+
+function randomsquare(aCtx : TJSCanvasRenderingContext2D) : TDrawResult; external name 'square.default';
+function draw(aCtx : TJSCanvasRenderingContext2D; alength,x,y : Integer; color : string) : TDrawResult; external name 'square.draw';
+procedure reportArea(length : Integer; ListID : String); external name 'square.reportArea';
+procedure reportPerimeter(length : Integer; ListID : String); external name 'square.reportPerimeter';
+
+Var
+ MyCanvas : TCreateCanvasResult;
+ MyReportList : string;
+ MySquare2,MySquare1 : TDrawResult;
+
+begin
+ MyCanvas:=create('myCanvas', document.body, 480, 320);
+ MyreportList:=createReportList(myCanvas.id);
+ MySquare1:=draw(myCanvas.ctx, 50, 50, 100, 'blue');
+ reportArea(MySquare1.length, MyReportList);
+ reportPerimeter(MySquare1.length,MyReportList);
+ MySquare2:=randomSquare(myCanvas.ctx);
+end.
\ No newline at end of file