Development environment¶
Prerequisites¶
- Either Node.js 26 and npm (local run), or Docker with Compose v2 (dev container); VS Code with the Dev Containers extension is optional
- Optional: Redis (cache) for a local run
- Optional: Python 3 (documentation site)
Credentials¶
Every development setup reads the Amazon credentials from environment variables (reference), so no credential ever lands in a committed file:
git clone https://github.com/ltoinel/amw.git
cd amw
cp .env.example .env # fill in AMAZON_*; .env is never committed
The development configuration is the committed config/development.yml
(port 8080, path /amw, debug logs, 60 s HTTP cache, Redis disabled).
The start script¶
./start.sh at the repository root is the single entry point to run the project:
| Command | What it does |
|---|---|
./start.sh or ./start.sh local |
Checks Node.js >= 26, runs npm ci if dependencies are missing or outdated, builds, then runs node dist/main.js with config/production.yml. SERVER_PROJECT_DIR defaults to the clone. |
./start.sh local --env development |
Same, with config/development.yml (--env NAME loads config/NAME.yml). |
./start.sh dev |
Starts the Docker development environment in the foreground: http://localhost:8080/amw |
./start.sh docker |
Builds and starts the production stack (AMW + Redis) in the background: http://localhost:9080/item |
./start.sh stop |
Stops both Docker stacks (data volumes are kept). |
./start.sh --help |
Shows the help. |
The Docker modes require Compose v2 (docker compose, or docker-compose v2) and warn
when .env is missing. The local mode does not read .env: export the variables in
your shell or put the credentials in the YAML file.
Docker development environment¶
docker/docker-compose.dev.yml
runs the app from the bind-mounted sources with hot reload, next to a Redis server:
./start.sh dev
# or: docker compose -f docker/docker-compose.dev.yml up --build
curl http://localhost:8080/amw/health # AMW_DEV_PORT overrides the host port
- The image (
docker/Dockerfile.dev) is Node.js 26 Alpine with dev dependencies and git; it runsnpm run devas thenodeuser (UID 1000), so files written to the bind mount stay owned by you. node_moduleslives in a named volume, never mixed with a host install built for another OS.- The compose file loads
.env(optional) and forcesNODE_ENV=development,REDIS_ENABLED=true,REDIS_HOST=redisandSERVER_PROJECT_DIR=/app/. - The server restarts on every change in
src/orconfig/.
VS Code Dev Containers¶
.devcontainer/devcontainer.json
reuses the same compose file: open the repository in VS Code and run
Dev Containers: Reopen in Container. You get the ESLint and Jest extensions, a
terminal inside the app container (/app) and the running dev server; the stack is
stopped when the window closes.
Without Docker¶
npm run dev builds the widget, then runs src/main.ts through tsx (types are stripped, not checked: npm run build and the editor do that) with
NODE_ENV=development and restarts on changes in src/ and config/ (node --watch).
The widget is served from its minified copy in dist/: after editing
src/widgets/widget.js, run npm run build:widgets (or restart npm run dev).
Without Amazon credentials (mock API)¶
scripts/dev-mock.ts starts
three servers and stops them all on Ctrl+C:
| URL | What it is |
|---|---|
| http://localhost:8080/item | The real AMW server, run from src/ through tsx with config/development.yml and restarted on changes, like npm run dev. |
| http://localhost:8081 | The mock Creators API (tests/e2e/support/mockAmazonApi.ts), with mock credentials. |
| http://localhost:8082/ | A demo page embedding widgets for the ASINs below (CORS is enabled on AMW for it). |
curl "http://localhost:8080/item/product?id=B084DN3XVN"
curl "http://localhost:8080/item/products?ids=B084DN3XVN,B0NOTFOUND,B0ANYASIN1"
curl "http://localhost:8080/item/health"
The mock answers any ASIN with a generic product; some ids and keywords are special:
| Request | Mock behaviour | AMW response |
|---|---|---|
id=B084DN3XVN, B0192CTN72, B0DEMO0003 |
Realistic products (savings badge, no savings, no offer) | 200 |
id=B0NOTFOUND |
Item not accessible | 404 |
id=B0ERROR500 |
Amazon 500 | 502 |
id=B0XSSPAYLO |
javascript: URLs and HTML in the title, to check the widget neutralizes them |
200 |
keyword=nothingmatches |
No search result | 404 |
any other keyword= |
One generic result | 200 |
- No
.envneeded: the mock credentials override any exportedAMAZON_*variable, which the mock would reject. - Redis stays disabled (
config/development.yml); exportREDIS_ENABLED=true(andREDIS_HOST) to try the cache. - Ports:
AMW_DEV_PORT(default8080),AMW_MOCK_PORTandAMW_DEMO_PORT(defaultAMW_DEV_PORT+ 1 and + 2). - Product images point to Amazon's CDN, where the fake ASINs do not exist, so the cards show no picture.
npm scripts¶
| Command | Description |
|---|---|
npm run dev |
Development server with automatic restart (see above). |
npm run dev:mock |
Same, against the mock Amazon API, with a demo page (see above). |
npm run build |
Cleans dist/, compiles TypeScript (tsc) and minifies the widget (scripts/build-widgets.js). |
npm run build:widgets |
Minifies src/widgets/widget.js into dist/widgets/. |
npm start |
Runs the compiled server (node ., i.e. dist/main.js). Build first. |
npm run lint / npm run lint:fix |
ESLint on src/**/*.ts. |
npm test |
Jest test suites. |
npm run test:coverage |
Jest with a coverage report in coverage/. |
npm run test:ci |
Jest in CI mode with coverage (used by the CI workflow). |
npm run test:e2e |
API end-to-end tests against the compiled server (build first). |
npm run test:e2e:browser |
Browser end-to-end tests with Playwright (build first). |
npm run docs:screenshots |
Builds, then regenerates the user guide screenshots. |
npm run docker |
Same as ./start.sh docker. |
npm run release |
release-it (bumps, tags and pushes in one go); the release process bumps the version through a pull request instead. |
Before opening a pull request, run (details in Tests & quality):