Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "React UI (${localWorkspaceFolderBasename})",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for info: This was requested by @mbohal who usually have multiple instances of a repository on his machine. This allow to differ between multiple versions by directory name.

"initializeCommand": "bash ./setup.sh",
"dockerComposeFile": [
"../docker-compose.yml"
],
"service": "devcontainer",
"shutdownAction": "stopCompose",
"workspaceFolder": "/workspace",
"forwardPorts": [
"docs:8000"
],
"portsAttributes": {
"docs:8000": {
"label": "Docs server",
"protocol": "http",
"onAutoForward": "openBrowser"
}
},
"otherPortsAttributes": {
"onAutoForward": "ignore"
}
}
51 changes: 45 additions & 6 deletions .env.dist
Original file line number Diff line number Diff line change
@@ -1,13 +1,52 @@
###############################
# Docker compose configuration #
###############################
################################
# Docker Compose configuration #
################################

# Host system port where the live documentation is to be made accessible
COMPOSE_START_PORT=8000
# Docker compose project name must match directory name of the project to allow devcontainer to communicate with other containers
COMPOSE_PROJECT_NAME=react-ui
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is magic propagated to other scripts allowing you to run multiple instances of same repository without conflicting. $COMPOSE_PROJECT_NAME is used where needed. Check setup.sh that simplified it.


# Host system port where Playwright Component Testing report is to be made accessible
# Docker compose ports for Docs server instances
COMPOSE_START_DOCS_SERVER_PORT=8000

# Docker compose ports for Playwright Component Testing report server
COMPOSE_PLAYWRIGHT_REPORT_PORT=9323

# Flag whether to start JavaScript files watcher at container start
COMPOSE_START_JS_FILES_WATCHER_AT_START=true

# Flag whether to start docs server at container start
COMPOSE_START_DOCS_SERVER_AT_START=true

# Ownership of the files created in the container
# ⚠️ [Linux] This needs to be set to the output of `id --user`
# ⚠️ [MacOS] This needs to be set to 1000
COMPOSE_UID=1000
# ⚠️ [Linux] This needs to be set to the output of `id --group`
# ⚠️ [MacOS] This needs to be set to 1000
COMPOSE_GID=1000

#############################
# Devcontainer configuration #
#############################

# IDEs automatically mount the host's SSH agent socket into the container
# Visual Studio Code does this by default, it can be disabled by setting the following variable to true.
# JetBrains IDEs do not mount this by default, but they can be configured to do so.
BLOCK_SSH_AUTH_SOCK=false

# Select your preferred editor and visual (vim, nano)
EDITOR=vim
VISUAL=vim

# Select your preferred shell (/bin/bash, /bin/fish, /bin/zsh)
SHELL=/bin/bash

###########################
# Playwright configuration #
###########################

# Number of workers to use to run Playwright tests
PW_WORKERS=1

# Port used by Playwright Component Testing to serve the test files
PW_CT_PORT=3100
9 changes: 0 additions & 9 deletions .env.playwright.dist

This file was deleted.

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/coverage
/docker-compose.yml
/docker/react_ui_devcontainer_local
!/docker/react_ui_devcontainer_local/Dockerfile.dist
/dist
/node_modules
/playwright-report/
/site
/src/docs/_assets/generated/*
/tests/playwright/.temp/
.env
.env.playwright
statistics.html
!.gitkeep
18 changes: 3 additions & 15 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,10 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## Commands

All `npm` commands must be run inside Docker containers. Use `node_shell` for most tasks, `playwright` for visual tests.
All commands below are meant to be run directly inside the Docker container `devcontainer`.
If you open the project in a Dev Container, you can run these commands without manually
starting Docker Compose on the host.

```bash
# Enter node_shell container
docker compose run --rm node_shell

# Enter playwright container (for visual tests)
docker compose run --rm --service-ports playwright
```

**Within `node_shell`:**

```bash
npm run lint # All linters (ESLint + Stylelint + Markdownlint)
Expand All @@ -23,11 +16,6 @@ npm run stylelint # SCSS linting
npm run test:jest # All Jest unit tests
npm run test:jest:ts -- <file> # Single TypeScript test file
npm run test:jest:js -- <file> # Single JavaScript test file
```

**Within `playwright`:**

```bash
npm run test:playwright-ct:all # All component tests
npm run test:playwright-ct:all-with-update # Update snapshots
npm run test:playwright-ct:all -- -- src/components/Button # Tests for one component
Expand Down
91 changes: 91 additions & 0 deletions docker-compose.base.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
services:
# This service is responsible for providing the main development environment for developers
devcontainer:
hostname: ${COMPOSE_PROJECT_NAME:-react-ui}_devcontainer
build:
context: docker/react_ui_devcontainer/
dockerfile: Dockerfile
# Start dependent services before starting the `devcontainer` service to ensure that the necessary environments
# and tools are available when the `devcontainer` starts.
depends_on:
node:
condition: service_started
playwright:
condition: service_started
docs:
condition: service_started
user: ${COMPOSE_UID}:${COMPOSE_GID}
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

devcontainer is forced to run as ${COMPOSE_UID}:${COMPOSE_GID}. This overrides the image’s USER developer and can break the devcontainer entrypoint/wrappers that rely on the developer account having passwordless sudo (e.g. sudo chown ..., sudo docker compose ...). Consider removing user: for the devcontainer service (let the image user be used) and rely on fixuid to remap the developer UID/GID to the host values, or explicitly set user: developer here.

Suggested change
user: ${COMPOSE_UID}:${COMPOSE_GID}
user: developer

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have already tested it in private project and it works on Linux and MacOS as well correctly. So I am not sure if copilot note is right or not. @mbohal?

# Keep the container running indefinitely to allow developers to attach to it and use it as their development environment
command: sleep infinity
# Injects environment variables from the `.env` file into the `devcontainer` service,
# making them accessible within the container's environment.
env_file:
- .env
environment:
# This must be set correctly for the `devcontainer` to be able to access the host's Docker daemon,
# enabling Docker-from-Docker capabilities (e.g., running Docker commands from within the `devcontainer`).
COMPOSE_PROJECT_NAME: ${COMPOSE_PROJECT_NAME:-react-ui}
init: true
volumes:
- .:/workspace:z
# The following volume is used to allow the `devcontainer` to access the host's Docker daemon,
# enabling Docker-from-Docker capabilities (e.g., running Docker commands from within the `devcontainer`).
- /var/run/docker.sock:/var/run/docker.sock
# The following named volumes persist data (e.g. terminal history, AI tools data, etc.) across container restarts.
# Using separate named volumes (instead of a single volume with subpaths) allows Docker to automatically
# seed the volume with data from the image on first use.
- terminal-history:/home/developer/.terminal_history
- claude-config:/home/developer/.config/claude
- claude-share:/home/developer/.local/share/claude
- claude-state:/home/developer/.local/state/claude
- copilot:/home/developer/.copilot
- copilot-config:/home/developer/.config/copilot
- opencode-config:/home/developer/.config/opencode
- opencode-share:/home/developer/.local/share/opencode
- opencode-state:/home/developer/.local/state/opencode

# This service provides Node environment and NPM
node:
build: docker/node
user: ${COMPOSE_UID}:${COMPOSE_GID}
command: sh -c 'if [ "$$COMPOSE_START_JS_FILES_WATCHER_AT_START" = "true" ]; then npm ci && npm start; else sleep infinity; fi'
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The node service runs npm ci on every container start when COMPOSE_START_JS_FILES_WATCHER_AT_START=true (default in .env.dist). This makes docker compose up / Dev Container startup significantly slower and repeatedly wipes/reinstalls node_modules. Consider running npm ci only when needed (e.g., when node_modules is missing or package-lock.json changed), or splitting dependency install into an explicit setup step and having the startup command just run npm start.

Suggested change
command: sh -c 'if [ "$$COMPOSE_START_JS_FILES_WATCHER_AT_START" = "true" ]; then npm ci && npm start; else sleep infinity; fi'
command: sh -c 'if [ "$$COMPOSE_START_JS_FILES_WATCHER_AT_START" = "true" ]; then if [ ! -d node_modules ] || [ package-lock.json -nt node_modules ]; then npm ci; fi; npm start; else sleep infinity; fi'

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it this way so user always have up-to-date environment. It is same as with rebuilding images, in first phase, I did it this way. But if you want @adamkudrna, I can add check that it is executed only if node_modules does not exist (I need to make sure deps are installed prior to npm start)

env_file:
- .env
volumes:
- .:/workspace:z

# This service provides Playwright environment and tools for browser automation and testing
playwright:
build: docker/playwright
user: ${COMPOSE_UID}:${COMPOSE_GID}
command: sleep infinity
env_file:
- .env
ports:
- ${COMPOSE_PLAYWRIGHT_REPORT_PORT}:9323
volumes:
- .:/workspace:z

# This provides server for documentation
docs:
build: docker/mkdocs
user: ${COMPOSE_UID}:${COMPOSE_GID}
entrypoint: sh -c 'if [ "$$COMPOSE_START_DOCS_SERVER_AT_START" = "true" ]; then mkdocs serve; else sleep infinity; fi'
env_file:
- .env
ports:
- ${COMPOSE_START_DOCS_SERVER_PORT}:8000
volumes:
- .:/workspace:z

volumes:
# The following volumes are used to persist data (e.g. terminal history, AI tools data, etc.) across container restarts
terminal-history:
claude-config:
claude-share:
claude-state:
copilot:
copilot-config:
opencode-config:
opencode-share:
opencode-state:
43 changes: 0 additions & 43 deletions docker-compose.yml

This file was deleted.

42 changes: 42 additions & 0 deletions docker-compose.yml.dist
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
services:
# This service is responsible for providing the main development environment for developers
devcontainer:
extends:
file: docker-compose.base.yml
service: devcontainer
# Use `build` when you want to customize the devcontainer using `docker/react_ui_devcontainer_local/Dockerfile`
# build:
# context: ./docker/react_ui_devcontainer_local/
# dockerfile: Dockerfile
# Use `image` when you want to use the default devcontainer
image: react-ui_devcontainer

# This service provides Node environment and NPM
node:
extends:
file: docker-compose.base.yml
service: node

# This service provides Playwright environment and tools for browser automation and testing
playwright:
extends:
file: docker-compose.base.yml
service: playwright

# This provides server for documentation
docs:
extends:
file: docker-compose.base.yml
service: docs

volumes:
# The following volumes are used to persist data (e.g. terminal history, AI tools data, etc.) across container restarts
terminal-history:
claude-config:
claude-share:
claude-state:
copilot:
copilot-config:
opencode-config:
opencode-share:
opencode-state:
26 changes: 26 additions & 0 deletions docker/build-docker-images.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

set -e
trap 'echo "Failed to build Docker images"; exit 1' ERR

cd "$(dirname "$0")"

echo "Building Docker images..."

if [ ! -f ../.env ]; then
echo "Error: .env file not found in the project root"
exit 1
fi

PROJECT_NAME=$(grep -E '^COMPOSE_PROJECT_NAME=' ../.env | cut -d '=' -f 2-)
PROJECT_DEVCONTAINER_IMAGE="${PROJECT_NAME}_devcontainer"

echo "Building Docker image $PROJECT_DEVCONTAINER_IMAGE..."
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for info: This is needed if we want ability to allow user to specify his/her local Dockerfile (Dockerfile cannot extend from other Dockerfile, just from Docker image). This can look like a non sense, but this is the best I want able to come up with.

docker build -t "$PROJECT_DEVCONTAINER_IMAGE" -f ./react_ui_devcontainer/Dockerfile ./react_ui_devcontainer/

cd ..

echo "Building project Docker images using docker-compose..."
docker compose build

echo "All Docker images built successfully!"
Loading
Loading