diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..bf9ffa1
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,65 @@
+name: CI
+
+on:
+ push:
+ branches: [dev, master]
+ pull_request:
+ branches: [dev, master]
+
+# Cancel superseded runs on the same branch / PR.
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ unit:
+ name: Unit tests (Vitest)
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '22'
+ cache: npm
+ - run: npm ci
+ - run: npm test
+
+ build-and-e2e:
+ name: Build wasm + JS, run Playwright
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ submodules: recursive
+
+ - uses: actions/setup-node@v4
+ with:
+ node-version: '22'
+ cache: npm
+
+ - uses: mymindstorm/setup-emsdk@v14
+ with:
+ version: 3.1.61
+ actions-cache-folder: emsdk-cache
+
+ - run: npm ci
+
+ - name: Build wasm
+ run: npm run build
+
+ - name: Build JS bundles
+ run: npm run build-es6
+
+ - name: Install Playwright browsers
+ run: npx playwright install --with-deps chromium
+
+ - name: Run Playwright e2e
+ run: npm run test:e2e
+
+ - name: Upload Playwright report on failure
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: playwright-report
+ path: playwright-report/
+ retention-days: 7
diff --git a/.gitignore b/.gitignore
index 235a4e0..c702279 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,8 @@ node_modules
build/libar.bc
build/libar.o
doc/*
+# Test outputs
+test-results/
+playwright-report/
+playwright/.cache/
+coverage/
diff --git a/.npmignore b/.npmignore
index 274a133..7bb705a 100644
--- a/.npmignore
+++ b/.npmignore
@@ -4,7 +4,11 @@ emscripten/**/*
example/*
tools/
tools/*
+tests/
+test-result/
build/*.bc
+build/*.o
*.zip
docs/**/*
docs/
+.github/
diff --git a/README.md b/README.md
index 61402d3..1e1063c 100644
--- a/README.md
+++ b/README.md
@@ -1,28 +1,225 @@
# FeatureSET-Display
-A little javascript lib for display .iset and .fset .fset3 files
+> Display the contents of NFT marker files (`.iset`, `.fset`, `.fset3`) — the
+> image preview plus the feature points used for detection and tracking — in
+> a browser, via WebAssembly.
-## Introduction of the project
+Useful for inspecting markers generated with
+[NFT-Marker-Creator](https://github.com/Carnaux/NFT-Marker-Creator) or [Nft-Marker-Creator-App](https://github.com/webarkit/Nft-Marker-Creator-App) :
+see at a glance whether a marker has enough trackable features, whether
+they're clustered in a corner, or whether the source image lost
+contrast during the dataset build.
-With this little library it is possible to display NFT markers (.fset .iset and .fset3) files, generated with [NFT-Marker-Creator](https://github.com/.Carnaux/NFT-Marker-Creator). For now it may show you the image set from .iset file and the feature points from .fset and .fset3 files. Very useful utility to understand the stength and key points of the NFT marker.
+---
-### List of working features
-- Display of the first the ImageSet.
-- Display the features points used in identifying and features points used in continuous tracking.
+## What you get
-Display of various imageSet and FeatureSet infos in the console:
+For any marker triplet (`name.iset` + `name.fset` + `name.fset3`),
+the library:
-- NFT number of ImageSet
-- NFT dpi
-- NFT marker width
-- NFT marker height
-- NFT number of Feature sets
-- NFT number of feature points
+- Reads the imageSet preview into an HTML5 canvas.
+- Overlays the detection feature points as **light green** circles.
+- Overlays the tracking feature points as **small red** circles.
+- Logs the marker dimensions, DPI, and feature-point counts to the
+ browser console.
-### List of features to add
+## Install
-- display the ImageSet (the entire array of images as a choice)
+```bash
+npm install @webarkit/featureset-display
+```
-### Example
+Or load the UMD bundle directly:
-An example is included in the **example** folder. Run a http server (python or node) and open the **example.html** file.
+```html
+
+```
+
+## Quick start (ES module)
+
+```html
+
+```
+
+The library will create a `