From 208530747b3a2a676a0eaca37b250dc655850d4b Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:38:52 +0200 Subject: [PATCH 01/26] add Dockerfile based on example a copy of the example from https://docs.docker.com/guides/vuejs/ using hardened images --- Dockerfile | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..78c71ad --- /dev/null +++ b/Dockerfile @@ -0,0 +1,45 @@ +# This Dockerfile is an adaptation of the example from https://docs.docker.com/guides/vuejs/ + +# ========================================= +# Stage 1: Build the Vue.js Application +# ========================================= +# Use a lightweight DHI Node.js image for building +FROM dhi.io/node:24-alpine3.22-dev AS builder + +# Set the working directory inside the container +WORKDIR /app + +# Copy package-related files first to leverage Docker's caching mechanism +COPY package.json package-lock.json* ./ + +# Install project dependencies using npm ci (ensures a clean, reproducible install) +RUN --mount=type=cache,target=/root/.npm npm ci + +# Copy the rest of the application source code into the container +COPY . . + +# Build the Vue.js application +RUN npm run build + +# ========================================= +# Stage 2: Prepare Nginx to Serve Static Files +# ========================================= + +FROM dhi.io/nginx:1.28.0-alpine3.21-dev AS runner + +# Copy custom Nginx config +COPY nginx.conf /etc/nginx/nginx.conf + +# Copy the static build output from the build stage to Nginx's default HTML serving directory +COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html + +# Use a built-in non-root user for security best practices +USER nginx + +# Expose port 8080 to allow HTTP traffic +# Note: The default Nginx container now listens on port 8080 instead of 80 +EXPOSE 8080 + +# Start Nginx directly with custom config +ENTRYPOINT ["nginx", "-c", "/etc/nginx/nginx.conf"] +CMD ["-g", "daemon off;"] From 69bb357bda3dcb6a5b702662a05c07d4b9c8f82d Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 9 Jul 2026 13:53:34 +0200 Subject: [PATCH 02/26] update base image versions and pin using index digest - switching from dev image to runtime image for nginx - using index digest (manifest list) for multi-platform support - pinning the versions, following https://docs.docker.com/build/building/best-practices/#pin-base-image-versions and https://docs.docker.com/dhi/core-concepts/digests/#multi-platform-images-and-manifests --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 78c71ad..9e9727c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ # Stage 1: Build the Vue.js Application # ========================================= # Use a lightweight DHI Node.js image for building -FROM dhi.io/node:24-alpine3.22-dev AS builder +FROM dhi.io/node:24.18.0-alpine3.24-dev@sha256:be2d2424a15059dfce410220ab4ec2eedcb7c044c8117f4cddcc2fa7a4b968fb AS builder # Set the working directory inside the container WORKDIR /app @@ -25,7 +25,7 @@ RUN npm run build # Stage 2: Prepare Nginx to Serve Static Files # ========================================= -FROM dhi.io/nginx:1.28.0-alpine3.21-dev AS runner +FROM dhi.io/nginx:1.30.3-alpine3.24@sha256:96d1aa0daa861c5dea1122135ca740861ae0afd910d111c48844cd114103cf0c AS runner # Copy custom Nginx config COPY nginx.conf /etc/nginx/nginx.conf From ecadf9ba02cf950950e6d931532f8bfe6598465b Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 9 Jul 2026 14:12:35 +0200 Subject: [PATCH 03/26] add notes about the build step --- Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 9e9727c..f525e03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,10 @@ RUN --mount=type=cache,target=/root/.npm npm ci # Copy the rest of the application source code into the container COPY . . -# Build the Vue.js application +# Build the Vue.js application. +# As can be seen in package.json, this runs the type checker and then builds the app using Vite. +# The resulting files end up in /app/dist (i.e. WORKDIR/dist) by default. +# https://vite.dev/guide/build#building-for-production RUN npm run build # ========================================= From 914c2ae85d4312018eb82f8ecb27855af1caf326 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 9 Jul 2026 14:29:07 +0200 Subject: [PATCH 04/26] add nginx config based on example copied from https://docs.docker.com/guides/vuejs/ --- nginx.conf | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 nginx.conf diff --git a/nginx.conf b/nginx.conf new file mode 100644 index 0000000..df65f63 --- /dev/null +++ b/nginx.conf @@ -0,0 +1,57 @@ +# Config based on example from https://docs.docker.com/guides/vuejs/ + +worker_processes auto; +pid /tmp/nginx.pid; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + charset utf-8; + + access_log off; + error_log /dev/stderr warn; + + sendfile on; + tcp_nopush on; + tcp_nodelay on; + keepalive_timeout 65; + keepalive_requests 1000; + + gzip on; + gzip_comp_level 6; + gzip_proxied any; + gzip_min_length 256; + gzip_vary on; + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; + + server { + listen 8080; + server_name localhost; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|map)$ { + expires 1y; + access_log off; + add_header Cache-Control "public, immutable"; + add_header X-Content-Type-Options nosniff; + } + + location /assets/ { + expires 1y; + add_header Cache-Control "public, immutable"; + add_header X-Content-Type-Options nosniff; + } + + error_page 404 /index.html; + } +} \ No newline at end of file From d752b6c44ae439598c709effac14a85ea7895f59 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 9 Jul 2026 14:29:41 +0200 Subject: [PATCH 05/26] note about dhi.io login for hardened images --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f525e03..29cca59 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,6 @@ -# This Dockerfile is an adaptation of the example from https://docs.docker.com/guides/vuejs/ +# This Dockerfile is an adaptation of the example from https://docs.docker.com/guides/vuejs/. +# The file uses hardened base images, so, before building, we need to authenticate with dhi.io: +# docker login dhi.io # ========================================= # Stage 1: Build the Vue.js Application From c6ba5cd3d437a77c8225e235420fc75a9c5e70f5 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 9 Jul 2026 17:03:21 +0200 Subject: [PATCH 06/26] add explanantory comments for nginx config generated by ai, verified by hand and amended with links etc. --- nginx.conf | 72 +++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/nginx.conf b/nginx.conf index df65f63..77f23f9 100644 --- a/nginx.conf +++ b/nginx.conf @@ -1,57 +1,63 @@ # Config based on example from https://docs.docker.com/guides/vuejs/ -worker_processes auto; -pid /tmp/nginx.pid; +worker_processes auto; # Automatically set the number of worker processes based on available CPU cores +pid /tmp/nginx.pid; # Store the master process ID file in /tmp (useful for non-root/rootless containers) events { - worker_connections 1024; + worker_connections 1024; # Maximum number of simultaneous connections each worker can handle } http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - charset utf-8; - - access_log off; - error_log /dev/stderr warn; - - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - keepalive_requests 1000; - - gzip on; - gzip_comp_level 6; - gzip_proxied any; - gzip_min_length 256; - gzip_vary on; - gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; + include /etc/nginx/mime.types; # Include the standard MIME type mappings for file extensions + default_type application/octet-stream; # Default MIME type used when a file's type cannot be determined + charset utf-8; # Set UTF-8 as the default character encoding for responses + + # https://docs.nginx.com/nginx/admin-guide/monitoring/logging/ + access_log off; # Disable the access log globally to reduce disk I/O + error_log /dev/stderr warn; # Send error logs to stderr (container-friendly) at "warn" level or higher + + # https://nginx.org/en/docs/http/ngx_http_core_module.html + sendfile on; # Enable the efficient sendfile() system call for serving static files + tcp_nopush on; # Optimize packet transmission for sendfile by delaying sends until larger packets can be formed + tcp_nodelay on; # Reduce latency on keep-alive connections + keepalive_timeout 65; # Keep idle client connections open for up to 65 seconds + keepalive_requests 1000; # Allow up to 1000 requests per keep-alive connection before closing it + + # https://nginx.org/en/docs/http/ngx_http_gzip_module.html + gzip on; # Enable gzip compression of responses + gzip_comp_level 6; # Compression level (1=fastest, 9=best); 6 is a balanced default + gzip_proxied any; # Compress responses for all proxied requests regardless of headers + gzip_min_length 256; # Only compress responses with "Content-Length" larger than 256 bytes (smaller ones aren't worth it) + gzip_vary on; # Add "Vary: Accept-Encoding" header so caches serve correct variants + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml; # MIME types to compress (text/html is always compressed by default) server { - listen 8080; - server_name localhost; + listen 8080; # Listen for HTTP connections on port 8080 + server_name localhost; # Match requests whose Host header is "localhost" - root /usr/share/nginx/html; - index index.html; + root /usr/share/nginx/html; # Root directory from which the built static files are served + index index.html; # Default file to serve when a directory is requested location / { + # Single Page App (SPA) fallback + # Check URI or directory, fall back on index.html for client-side routing. + # https://nginx.org/en/docs/http/ngx_http_core_module.html#try_files try_files $uri $uri/ /index.html; } - location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|map)$ { - expires 1y; - access_log off; - add_header Cache-Control "public, immutable"; - add_header X-Content-Type-Options nosniff; + location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|map)$ { # Case-insensitive regex match for common static asset extensions + expires 1y; # Set the Expires header to 1 year in the future for long-term caching + access_log off; # Disable access logging for these static assets + add_header Cache-Control "public, immutable"; # Tell browsers the resource URL is versioned/content-hashed and won't change during its cache lifetime + add_header X-Content-Type-Options nosniff; # Prevent browsers from MIME-sniffing the response type } - location /assets/ { + location /assets/ { # Match requests under the /assets/ path (Vite's default build output directory) expires 1y; add_header Cache-Control "public, immutable"; add_header X-Content-Type-Options nosniff; } - error_page 404 /index.html; + error_page 404 /index.html; # On 404 errors, serve index.html to let the SPA router handle the route } } \ No newline at end of file From cf453836ae4f98463cd753676748f8d5ba4ba59a Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 9 Jul 2026 17:47:13 +0200 Subject: [PATCH 07/26] rename nginx.conf to docker.nginx.conf for clarity --- Dockerfile | 2 +- nginx.conf => docker.nginx.conf | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename nginx.conf => docker.nginx.conf (98%) diff --git a/Dockerfile b/Dockerfile index 29cca59..d24fcf2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -33,7 +33,7 @@ RUN npm run build FROM dhi.io/nginx:1.30.3-alpine3.24@sha256:96d1aa0daa861c5dea1122135ca740861ae0afd910d111c48844cd114103cf0c AS runner # Copy custom Nginx config -COPY nginx.conf /etc/nginx/nginx.conf +COPY docker.nginx.conf /etc/nginx/nginx.conf # Copy the static build output from the build stage to Nginx's default HTML serving directory COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html diff --git a/nginx.conf b/docker.nginx.conf similarity index 98% rename from nginx.conf rename to docker.nginx.conf index 77f23f9..9940a2f 100644 --- a/nginx.conf +++ b/docker.nginx.conf @@ -1,3 +1,4 @@ +# Configures Nginx as a static file server. # Config based on example from https://docs.docker.com/guides/vuejs/ worker_processes auto; # Automatically set the number of worker processes based on available CPU cores From b56a22676f42a6243a74cc9e670dd405ef13cf25 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 9 Jul 2026 17:59:18 +0200 Subject: [PATCH 08/26] add .dockerignore partially based on the example from https://docs.docker.com/guides/vuejs/ --- .dockerignore | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .dockerignore diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e934cf4 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,61 @@ +# Dependencies +node_modules/ + +# Build output +dist/ + +# Testing +tests/ +coverage/ +*.test.ts + +# Version control +.git/ +.gitignore + +# CI/CD +.github/ + +# IDE & Editor +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# Documentation +README.md +CONTRIBUTING.md +LICENSE + +# Docker +Dockerfile +.dockerignore +compose.yml +compose.override.yml + +# Linting & Formatting +.eslintcache +.eslintrc* +eslint.config.ts +.prettierrc* +.oxlintrc.json + +# Environment +.env +.env.* +*.local +.nvmrc + +# OS specific +Thumbs.db +.DS_Store + +# Logs +logs/ +*.log* + +# Various +.cache/ +.tmp/ +.temp/ From ead853924a9785c787004f9d3e539dc2ebf2337a Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:16:49 +0200 Subject: [PATCH 09/26] clarify dockerfile expose comment --- Dockerfile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index d24fcf2..3ea5ebc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,8 +41,9 @@ COPY --chown=nginx:nginx --from=builder /app/dist /usr/share/nginx/html # Use a built-in non-root user for security best practices USER nginx -# Expose port 8080 to allow HTTP traffic -# Note: The default Nginx container now listens on port 8080 instead of 80 +# Inform which port the app inside the container is expected to listen on. +# This does not actually make the port accessible from the host or web. +# Note: docker.nginx.conf actually configures the Nginx app to listen on port 8080 instead of the default port 80. EXPOSE 8080 # Start Nginx directly with custom config From c386138b108adf13d3f38c9b566bf2fa87d82a4b Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Tue, 14 Jul 2026 18:33:23 +0200 Subject: [PATCH 10/26] add basic docker publish workflow (wip) --- .github/workflows/publish.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..831e3e6 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,23 @@ +name: Publish to Docker Hub + +on: + push: + branches: + - master + pull_request: + release: + types: + - created + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + # todo: add verify job calling reusable version of the ci.yml workflow + publish: + uses: FAIRDataTeam/github-workflows/.github/workflows/docker-publish.yml@v3 + secrets: inherit + with: + file: './Dockerfile' + push: ${{ github.event_name == 'push' || github.event_name == 'release' }} From 3b2b665f61e3576dda63805c0397a66822d0c83c Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Wed, 15 Jul 2026 21:24:53 +0200 Subject: [PATCH 11/26] move docker-publish job into a single ci-cd workflow file This way we don't run redundant checks and can easily implement dependence. The publish job is relatively slow, due to building the docker image, so it is skipped for pull_request updates. --- .github/workflows/{ci.yml => ci-cd.yml} | 19 +++++++++++++++++-- .github/workflows/publish.yml | 23 ----------------------- 2 files changed, 17 insertions(+), 25 deletions(-) rename .github/workflows/{ci.yml => ci-cd.yml} (64%) delete mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci-cd.yml similarity index 64% rename from .github/workflows/ci.yml rename to .github/workflows/ci-cd.yml index 72d4ca6..f732ea1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci-cd.yml @@ -1,11 +1,15 @@ -name: continuous integration checks and tests +name: continuous integration and deployment on: push: branches: - master pull_request: + pull_request_review: + types: [submitted] workflow_dispatch: + release: + types: [created] concurrency: # prevent duplicate runs @@ -13,7 +17,7 @@ concurrency: cancel-in-progress: true jobs: - build: + check: runs-on: ubuntu-latest strategy: @@ -48,3 +52,14 @@ jobs: # https://vitest.dev/config/watch name: Run tests run: npm run test + + publish: + # skip this job for pull request updates (it *will* run on review submission, push to master, and release creation) + if: ${{ github.event_name != 'pull_request' }} + needs: check + uses: FAIRDataTeam/github-workflows/.github/workflows/docker-publish.yml@v3 + secrets: inherit + with: + file: './Dockerfile' + # only publish to docker hub when triggered by push to master branch or release creation + push: ${{ github.event_name == 'push' || github.event_name == 'release' }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 831e3e6..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Publish to Docker Hub - -on: - push: - branches: - - master - pull_request: - release: - types: - - created - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - # todo: add verify job calling reusable version of the ci.yml workflow - publish: - uses: FAIRDataTeam/github-workflows/.github/workflows/docker-publish.yml@v3 - secrets: inherit - with: - file: './Dockerfile' - push: ${{ github.event_name == 'push' || github.event_name == 'release' }} From 19c8617a2a0b881df6f29a1fe07a6d5befc1d404 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Wed, 15 Jul 2026 21:37:55 +0200 Subject: [PATCH 12/26] prettier formatting --- .github/dependabot.yml | 24 ++++++++++++------------ README.md | 7 +++---- tsconfig.node.json | 5 +---- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 91c27f1..b5a90c3 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,24 +3,24 @@ version: 2 updates: - - package-ecosystem: "npm" - directory: "/" + - package-ecosystem: 'npm' + directory: '/' schedule: - interval: "weekly" - target-branch: "master" + interval: 'weekly' + target-branch: 'master' labels: - - "dependencies" + - 'dependencies' # Group minor updates and patch updates and create separate PRs for updates that do not match any grouping rule. groups: minor-updates: applies-to: version-updates update-types: - - "minor" - - "patch" - - package-ecosystem: "github-actions" - directory: "/" + - 'minor' + - 'patch' + - package-ecosystem: 'github-actions' + directory: '/' schedule: - interval: "weekly" - target-branch: "master" + interval: 'weekly' + target-branch: 'master' labels: - - "dependencies" + - 'dependencies' diff --git a/README.md b/README.md index e334180..fabfc2e 100644 --- a/README.md +++ b/README.md @@ -40,18 +40,17 @@ Here's how to install project dependencies and run the development server, provi ```bash npm run dev - ``` + ``` To specify a custom port, we can use the `--port` argument. - For example: - + For example: + ```bash npm run dev -- --port 8000 ``` Also see [vite development server] for more options. - [FAIRDataPoint]: https://github.com/FAIRDataTeam/FAIRDataPoint [FAIRDataPoint-client]: https://github.com/FAIRDataTeam/FAIRDataPoint-client [npm]: https://docs.npmjs.com/cli/v11/commands diff --git a/tsconfig.node.json b/tsconfig.node.json index d99dfbd..d1bb76a 100644 --- a/tsconfig.node.json +++ b/tsconfig.node.json @@ -1,9 +1,6 @@ { "extends": "@tsconfig/node24/tsconfig.json", - "include": [ - "vite.config.*", - "eslint.config.*" - ], + "include": ["vite.config.*", "eslint.config.*"], "compilerOptions": { "module": "preserve", "moduleResolution": "bundler", From c0b48fae4d39549bb0ed8240fbf189265e4ecacd Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Wed, 15 Jul 2026 21:54:06 +0200 Subject: [PATCH 13/26] comment about github env variables and secrets for publish workflow --- .github/workflows/ci-cd.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index f732ea1..69e0e5f 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -57,6 +57,9 @@ jobs: # skip this job for pull request updates (it *will* run on review submission, push to master, and release creation) if: ${{ github.event_name != 'pull_request' }} needs: check + # The docker-publish.yml workflow expects the following GitHub actions settings: + # Environment variables: DOCKER_HUB_NAMESPACE, DOCKER_IMAGE_NAME, DOCKER_HUB_USERNAME + # Environment secrets: DOCKER_HUB_PASSWORD uses: FAIRDataTeam/github-workflows/.github/workflows/docker-publish.yml@v3 secrets: inherit with: From e05163654e91359e3eb4252e4feb2d4fa0eefd42 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Wed, 15 Jul 2026 23:19:24 +0200 Subject: [PATCH 14/26] amend readme with background and deployment instructions (wip) --- README.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index fabfc2e..1351b3a 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,62 @@ # FAIR Data Point client redux -A browser-based client for administration of the FAIR Data Point reference implementation ([FAIRDataPoint]). +A browser-based client for administration of the FAIR Data Point (FDP) reference implementation ([FAIRDataPoint]). -This client replaces the original [FAIRDataPoint-client]. +This client replaces the original [FAIRDataPoint-client], which has been archived. +## Background + +### FAIR principles + +The [FAIR principles] aim to make _data_ more **F**indable, **A**ccessible, **I**nteroperable, and **R**eusable. + +### FAIR Data Point (FDP) + +A FAIR Data Point (FDP) is a web application, backed by a triple store, that facilitates the publication of _metadata_ as [Linked (Open) Data] in the form of [RDF] and [DCAT], following the [FAIR principles]. +The FDP reference implementation ([FAIRDataPoint]) is a Java-based implementation of the [FAIRDataPoint specification] that provides an HTTP API for manipulating these metadata. +The FDP API is intended primarily for machine interaction. +For example, the API enables data stewards to build automated metadata publication workflows for the FDP. +However, direct human interaction with the FDP API can be a bit cumbersome. +To simplify direct human interaction with the FDP API, we offer the FDP client. + +### FAIR Data Point Client (FDP client) + +The FAIR Data Point Client (FDP client) is a JavaScript (TypeScript) application that runs entirely in the browser, without any server-side rendering. +The client provides a web interface that makes it easier for humans to interact with the FAIR Data Point by hiding the interactions with the FDP API. +The main goal of the FDP client is to enable basic administration of the FDP, inspection of FDP content, and execution of simple queries. + +> [!NOTE] +> The FDP client was not designed for bulk operations or complicated queries. +> Those are best performed by direct interaction with the FDP API. + +## Quickstart + +The FDP client is published as a Docker image ([fairdata/fairdatapoint-client-redux]) and is designed to run in a container. +The Docker image is based on the official [Nginx hardened image], configured as a static file server listening on port `8080`. + +One way to deploy the client is using Docker compose, as follows: + +```yaml +# compose.yaml +services: + fdp-client-redux: + image: fairdata/fairdatapoint-client-redux + volumes: + # Override the default runtime config to specify the URL of the FDP API + - './config.json:/usr/share/nginx/html/config.json' +``` + +where `config.json` is a runtime configuration file that defines the primary endpoint URL of the FDP API, for example: + +```yaml +# config.json +{ apiEndpointUrl: https://fdp.example.org } +``` + +It is also possible to run the FDP client application from source, but this is only recommended for development purposes. + ## Setting up a development machine ### Environment variables @@ -53,6 +104,7 @@ Here's how to install project dependencies and run the development server, provi [FAIRDataPoint]: https://github.com/FAIRDataTeam/FAIRDataPoint [FAIRDataPoint-client]: https://github.com/FAIRDataTeam/FAIRDataPoint-client +[FAIRDataPoint specification]: https://specs.fairdatapoint.org/ [npm]: https://docs.npmjs.com/cli/v11/commands [npm clean-install]: https://docs.npmjs.com/cli/v11/commands/npm-ci [npm install]: https://docs.npmjs.com/cli/v11/commands/npm-install @@ -61,3 +113,9 @@ Here's how to install project dependencies and run the development server, provi [vite development server]: https://vite.dev/guide/cli#dev-server [dotenv]: https://github.com/motdotla/dotenv [vite docs]: https://vite.dev/guide/env-and-mode#env-files +[fairdata/fairdatapoint-client-redux]: https://hub.docker.com/r/fairdata/fairdatapoint-client-redux +[RDF]: https://www.w3.org/TR/rdf12-primer/ +[DCAT]: https://www.w3.org/TR/vocab-dcat-3/ +[Linked (Open) Data]: https://www.w3.org/DesignIssues/LinkedData +[FAIR principles]: https://doi.org/10.1038/sdata.2016.18 +[Nginx hardened image]: https://hub.docker.com/hardened-images/catalog/dhi/nginx From b2cf096fa3da4d05256152c4797a096d6a04c0bc Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 16 Jul 2026 11:31:36 +0200 Subject: [PATCH 15/26] clarify name of ci-cd.yml workflow --- .github/workflows/ci-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 69e0e5f..5ddc61c 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -1,4 +1,4 @@ -name: continuous integration and deployment +name: check, test, build image, and publish on: push: From 1557463a64e04b0b8e199c145f4a5d21ae093104 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 16 Jul 2026 11:39:08 +0200 Subject: [PATCH 16/26] run the workflow on any type of pull_request_review types are: submitted, edited, or dismissed this allows us to trigger the publish job manually, as a workaround for the fact that manual triggers via workflow_dispatch only work on the default branch --- .github/workflows/ci-cd.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 5ddc61c..7261f4f 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -5,9 +5,8 @@ on: branches: - master pull_request: - pull_request_review: - types: [submitted] - workflow_dispatch: + pull_request_review: # enables us to trigger the publish job in pull requests, without pushing to docker hub + workflow_dispatch: # allows manual triggering, but only on the default branch release: types: [created] @@ -54,7 +53,7 @@ jobs: run: npm run test publish: - # skip this job for pull request updates (it *will* run on review submission, push to master, and release creation) + # skip this job for pull request updates (it *will* run on pr review, push to master, and release creation) if: ${{ github.event_name != 'pull_request' }} needs: check # The docker-publish.yml workflow expects the following GitHub actions settings: From 8ca92240018b6a8ccc94e016285e89328dfc2044 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:57:43 +0200 Subject: [PATCH 17/26] fix readme links --- README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 3cff558..c647dd7 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,9 @@ # FAIR Data Point client redux -A browser-based client for administration of the FAIR Data Point (FDP) reference implementation ([FAIRDataPoint]). +A browser-based client for FAIR Data Point (FDP) administration. -This client replaces the original [FAIRDataPoint-client], which has been archived. +>[!NOTE] +> This client replaces the [legacy FDP client], which has been archived. @@ -15,7 +16,7 @@ The [FAIR principles] aim to make _data_ more **F**indable, **A**ccessible, **I* ### FAIR Data Point (FDP) A FAIR Data Point (FDP) is a web application, backed by a triple store, that facilitates the publication of _metadata_ as [Linked (Open) Data] in the form of [RDF] and [DCAT], following the [FAIR principles]. -The FDP reference implementation ([FAIRDataPoint]) is a Java-based implementation of the [FAIRDataPoint specification] that provides an HTTP API for manipulating these metadata. +The [FDP reference implementation] is a Java-based implementation of the [FDP specification] that provides an HTTP API for manipulating these metadata. The FDP API is intended primarily for machine interaction. For example, the API enables data stewards to build automated metadata publication workflows for the FDP. However, direct human interaction with the FDP API can be a bit cumbersome. @@ -104,9 +105,8 @@ If such a file exists, it is picked up automatically by the Vite development ser For example, you could use this to point the client to an actual FDP on the web, as follows: -#### public/config.local.json - -```json +```yaml +# public/config.local.json { "apiEndpointUrl": "https://app.fairdatapoint.org" } @@ -114,8 +114,9 @@ For example, you could use this to point the client to an actual FDP on the web, Note that the `config.local.json` file is ignored by `git`. -[FAIRDataPoint]: https://github.com/FAIRDataTeam/FAIRDataPoint -[FAIRDataPoint-client]: https://github.com/FAIRDataTeam/FAIRDataPoint-client +[FDP reference implementation]: https://github.com/FAIRDataTeam/FAIRDataPoint +[legacy FDP client]: https://github.com/FAIRDataTeam/FAIRDataPoint-client +[FDP specification]: https://specs.fairdatapoint.org [FAIRDataTeam/compose]: https://github.com/FAIRDataTeam/compose/tree/master/fdp/ephemeral/v1/dev/fdp-client-redux [npm]: https://docs.npmjs.com/cli/v11/commands [npm clean-install]: https://docs.npmjs.com/cli/v11/commands/npm-ci From 9cb627f2e5e8b66920c972c90f4fc215497228f0 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 16 Jul 2026 13:11:52 +0200 Subject: [PATCH 18/26] mention SPARQL in readme --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c647dd7..a72832a 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ The [FAIR principles] aim to make _data_ more **F**indable, **A**ccessible, **I* ### FAIR Data Point (FDP) -A FAIR Data Point (FDP) is a web application, backed by a triple store, that facilitates the publication of _metadata_ as [Linked (Open) Data] in the form of [RDF] and [DCAT], following the [FAIR principles]. +A FAIR Data Point (FDP) is a web application that facilitates the publication of _metadata_ as [Linked (Open) Data] in the form of [RDF] and [DCAT], following the [FAIR principles]. +The FDP application is backed by a [triple store], a type of graph database specialized for storing [RDF], which provides the ability to query the metadata using the [SPARQL] query language. The [FDP reference implementation] is a Java-based implementation of the [FDP specification] that provides an HTTP API for manipulating these metadata. The FDP API is intended primarily for machine interaction. For example, the API enables data stewards to build automated metadata publication workflows for the FDP. @@ -130,6 +131,8 @@ Note that the `config.local.json` file is ignored by `git`. [fairdata/fairdatapoint-client-redux]: https://hub.docker.com/r/fairdata/fairdatapoint-client-redux [RDF]: https://www.w3.org/TR/rdf12-primer/ [DCAT]: https://www.w3.org/TR/vocab-dcat-3/ +[SPARQL]: https://www.w3.org/TR/sparql11-query/ [Linked (Open) Data]: https://www.w3.org/DesignIssues/LinkedData [FAIR principles]: https://doi.org/10.1038/sdata.2016.18 [Nginx hardened image]: https://hub.docker.com/hardened-images/catalog/dhi/nginx +[triple store]: https://opendatahandbook.org/glossary/en/terms/triple-store/ From b6033cb05d1aca22830ccd305026f8aae260534d Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 16 Jul 2026 18:29:21 +0200 Subject: [PATCH 19/26] add background section to readme --- README.md | 73 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index a72832a..683b145 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A browser-based client for FAIR Data Point (FDP) administration. ->[!NOTE] +> [!NOTE] > This client replaces the [legacy FDP client], which has been archived. @@ -15,53 +15,80 @@ The [FAIR principles] aim to make _data_ more **F**indable, **A**ccessible, **I* ### FAIR Data Point (FDP) -A FAIR Data Point (FDP) is a web application that facilitates the publication of _metadata_ as [Linked (Open) Data] in the form of [RDF] and [DCAT], following the [FAIR principles]. -The FDP application is backed by a [triple store], a type of graph database specialized for storing [RDF], which provides the ability to query the metadata using the [SPARQL] query language. -The [FDP reference implementation] is a Java-based implementation of the [FDP specification] that provides an HTTP API for manipulating these metadata. -The FDP API is intended primarily for machine interaction. -For example, the API enables data stewards to build automated metadata publication workflows for the FDP. +#### Purpose + +A FAIR Data Point (FDP) is a tool for the publication of **_metadata_** describing datasets in a standardized form that unlocks the powers of [Semantic Web] technology. +The FDP uses the Resource Description Framework ([RDF]) and the Data Catalog Vocabulary ([DCAT]) to facilitate publication of metadata as [Linked (Open) Data], following the [FAIR principles]. + +[RDF] describes _things_ using statements of the form `(, , )`, called triples. +By storing metadata, in the form of RDF, in a [triple store], a type of graph database specialized for handling [RDF], the we gain the ability to perform advanced queries using the [SPARQL] query language. + +Due to the use of [Semantic Web] technology, metadata published on an FDP becomes part of a world wide web of knowledge. +This enables people and machines from around the globe to explore the metadata and discover relations between different datasets using logical inference and reasoning techniques. + +#### Specification + +The requirements for the [RDF] representation of FAIR Data Point metadata are defined in the [FDP 1.2 specification]. +Compliance with the [FDP 1.2 specification] specification implies the following: + +1. The FDP root URL must resolve to a metadata description of the FDP itself as a [DCAT] `MetadataService`. + This description must include a link to the FDP's primary API endpoint, indicated by `dcat:endpointURL`. +2. The FDP must expose metadata in the form of [RDF], supporting at least the [Turtle] (default) and [JSON-LD] representations. +3. Each metadata record on an FDP should be linked to a "profile" which points to a metadata schema, expressed in the Shapes Constraint Language ([SHACL]), that can be used for validation. +4. FDP metadata schemas must have (a subclass of) [DCAT] `Resource` as the target class. +5. The FDP metadata must include Linked Data Platform ([LDP]) containment statements. + +The [FDP 1.2 specification] also mentions that the FDP must provide an API following REST guidelines so that a client is able to discover the available actions and access the resources it needs. + +#### Reference implementation and API + +The [FDP reference implementation] is a Java-based implementation of the [FDP 1.2 specification] that provides an HTTP API for manipulating and querying RDF metadata. +This enables users, like data stewards, to build automated metadata publication workflows for the FDP. +The FDP API is intended primarily for machine interaction and exposes machine-readable documentation based on the [OpenAPI 3 spec]. + However, direct human interaction with the FDP API can be a bit cumbersome. To simplify direct human interaction with the FDP API, we offer the FDP client. -### FAIR Data Point Client (FDP client) +## FAIR Data Point Client (FDP client) The FAIR Data Point Client (FDP client) is a JavaScript (TypeScript) application that runs entirely in the browser, without any server-side rendering. The client provides a web interface that makes it easier for humans to interact with the FAIR Data Point by hiding the interactions with the FDP API. The main goal of the FDP client is to enable basic administration of the FDP, inspection of FDP content, and execution of simple queries. > [!NOTE] -> The FDP client was not designed for bulk operations or complicated queries. +> The FDP client was not designed for bulk operations or advanced queries. > Those are best performed by direct interaction with the FDP API. -## Quickstart +### Quickstart The FDP client is published as a Docker image ([fairdata/fairdatapoint-client-redux]) and is designed to run in a container. The Docker image is based on the official [Nginx hardened image], configured as a static file server listening on port `8080`. -One way to deploy the client is using Docker compose, as follows: +One way to deploy the client is using [Docker Compose], as follows: ```yaml # compose.yaml services: fdp-client-redux: image: fairdata/fairdatapoint-client-redux + # ... volumes: # Override the default runtime config to specify the URL of the FDP API - - './config.json:/usr/share/nginx/html/config.json' + - './my.config.json:/usr/share/nginx/html/config.json' ``` -where `config.json` is a runtime configuration file that defines the primary endpoint URL of the FDP API, for example: +where `my.config.json` is a custom runtime configuration file that defines the primary endpoint URL of the FDP API, for example: ```yaml -# config.json +# my.config.json { apiEndpointUrl: https://fdp.example.org } ``` It is also possible to run the FDP client application from source, but this is only recommended for development purposes. -## Setting up a development machine +### Setting up a development machine -### Dependencies and development server +#### Dependencies and development server Here's how to install project dependencies and run the development server, provided you've got [npm] installed: @@ -94,7 +121,7 @@ Here's how to install project dependencies and run the development server, provi Also see [vite development server] for more options. -### App configuration for development +#### App configuration for development The browser-based client application needs an API, provided by a FAIR Data Point (FDP), to function properly. The URL for the primary API endpoint is defined in the [public/config.json] file and defaults to `http://localhost:8080`. @@ -108,16 +135,14 @@ For example, you could use this to point the client to an actual FDP on the web, ```yaml # public/config.local.json -{ - "apiEndpointUrl": "https://app.fairdatapoint.org" -} +{ 'apiEndpointUrl': 'https://app.fairdatapoint.org' } ``` Note that the `config.local.json` file is ignored by `git`. [FDP reference implementation]: https://github.com/FAIRDataTeam/FAIRDataPoint [legacy FDP client]: https://github.com/FAIRDataTeam/FAIRDataPoint-client -[FDP specification]: https://specs.fairdatapoint.org +[FDP 1.2 specification]: https://specs.fairdatapoint.org [FAIRDataTeam/compose]: https://github.com/FAIRDataTeam/compose/tree/master/fdp/ephemeral/v1/dev/fdp-client-redux [npm]: https://docs.npmjs.com/cli/v11/commands [npm clean-install]: https://docs.npmjs.com/cli/v11/commands/npm-ci @@ -136,3 +161,11 @@ Note that the `config.local.json` file is ignored by `git`. [FAIR principles]: https://doi.org/10.1038/sdata.2016.18 [Nginx hardened image]: https://hub.docker.com/hardened-images/catalog/dhi/nginx [triple store]: https://opendatahandbook.org/glossary/en/terms/triple-store/ +[Semantic Web]: https://www.w3.org/2001/sw/SW-FAQ +[Turtle]: https://www.w3.org/TR/rdf12-turtle/ +[JSON-LD]: https://json-ld.org/primer/latest/ +[SHACL]: https://www.w3.org/TR/shacl/ +[LDP]: https://www.w3.org/TR/ldp/ +[OpenAPI 3 spec]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.2.0.md +[REST]: https://roy.gbiv.com/pubs/dissertation/rest_arch_style.htm +[Docker Compose]: https://docs.docker.com/compose/ From 07f349540d703da8b04dbf223a5fae2f48693584 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Fri, 17 Jul 2026 09:56:44 +0200 Subject: [PATCH 20/26] mention graph nodes and edges in readme --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 683b145..a4fe2a2 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ A FAIR Data Point (FDP) is a tool for the publication of **_metadata_** describi The FDP uses the Resource Description Framework ([RDF]) and the Data Catalog Vocabulary ([DCAT]) to facilitate publication of metadata as [Linked (Open) Data], following the [FAIR principles]. [RDF] describes _things_ using statements of the form `(, , )`, called triples. -By storing metadata, in the form of RDF, in a [triple store], a type of graph database specialized for handling [RDF], the we gain the ability to perform advanced queries using the [SPARQL] query language. +Together, these triples define a knowledge graph where the `` and `` terms represent nodes and the `` terms represent edges. +By storing metadata, in the form of RDF, in a [triple store], a type of graph database specialized for handling [RDF], an FDP gains the ability to perform advanced queries using the [SPARQL] query language. Due to the use of [Semantic Web] technology, metadata published on an FDP becomes part of a world wide web of knowledge. This enables people and machines from around the globe to explore the metadata and discover relations between different datasets using logical inference and reasoning techniques. From 3067f64b1b6cf13432f10c3c4e129a07f5b67212 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:18:25 +0200 Subject: [PATCH 21/26] minor rephrasing and fix rest link --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a4fe2a2..32b6f64 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Compliance with the [FDP 1.2 specification] specification implies the following: 4. FDP metadata schemas must have (a subclass of) [DCAT] `Resource` as the target class. 5. The FDP metadata must include Linked Data Platform ([LDP]) containment statements. -The [FDP 1.2 specification] also mentions that the FDP must provide an API following REST guidelines so that a client is able to discover the available actions and access the resources it needs. +The [FDP 1.2 specification] also mentions that the FDP must provide an API following [REST] guidelines so that a client is able to discover the available actions and access the resources it needs. #### Reference implementation and API @@ -50,10 +50,10 @@ The FDP API is intended primarily for machine interaction and exposes machine-re However, direct human interaction with the FDP API can be a bit cumbersome. To simplify direct human interaction with the FDP API, we offer the FDP client. -## FAIR Data Point Client (FDP client) +## FAIR Data Point Client -The FAIR Data Point Client (FDP client) is a JavaScript (TypeScript) application that runs entirely in the browser, without any server-side rendering. -The client provides a web interface that makes it easier for humans to interact with the FAIR Data Point by hiding the interactions with the FDP API. +The FAIR Data Point (FDP) _client_ is a JavaScript (TypeScript) application that runs entirely in the browser, without any server-side rendering. +The client provides a web-based user interface that makes it easier for humans to interact with a FAIR Data Point by hiding the interactions with the FDP API. The main goal of the FDP client is to enable basic administration of the FDP, inspection of FDP content, and execution of simple queries. > [!NOTE] @@ -85,7 +85,7 @@ where `my.config.json` is a custom runtime configuration file that defines the p { apiEndpointUrl: https://fdp.example.org } ``` -It is also possible to run the FDP client application from source, but this is only recommended for development purposes. +It is also possible to run the FDP client application from source, but this is only recommended for client development purposes. ### Setting up a development machine From bb4c0d5df851d08d69e73104426e2c72d978bd8f Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:35:35 +0200 Subject: [PATCH 22/26] explain what goes on under the hood --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 32b6f64..76f1971 100644 --- a/README.md +++ b/README.md @@ -52,8 +52,9 @@ To simplify direct human interaction with the FDP API, we offer the FDP client. ## FAIR Data Point Client -The FAIR Data Point (FDP) _client_ is a JavaScript (TypeScript) application that runs entirely in the browser, without any server-side rendering. -The client provides a web-based user interface that makes it easier for humans to interact with a FAIR Data Point by hiding the interactions with the FDP API. +The FAIR Data Point (FDP) _client_ provides a web-based user interface that makes it easier for humans to interact with a FAIR Data Point by hiding the interactions with the FDP API. +The client is a JavaScript (TypeScript) application that runs entirely in the browser, without any server-side rendering. +Under the hood, the FDP client uses the JavaScript [Fetch API] to make HTTP requests to a remote FDP API that complies with the [FDP 1.2 specification]. The main goal of the FDP client is to enable basic administration of the FDP, inspection of FDP content, and execution of simple queries. > [!NOTE] @@ -170,3 +171,4 @@ Note that the `config.local.json` file is ignored by `git`. [OpenAPI 3 spec]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.2.0.md [REST]: https://roy.gbiv.com/pubs/dissertation/rest_arch_style.htm [Docker Compose]: https://docs.docker.com/compose/ +[Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API From b662841bfa59949a50a488e1d852d52c9883d4bb Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:39:33 +0200 Subject: [PATCH 23/26] remove background section again moved it onto a separate branch docs/readme-background because it is not directly related to the present pr --- README.md | 59 +------------------------------------------------------ 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/README.md b/README.md index 76f1971..8d6137c 100644 --- a/README.md +++ b/README.md @@ -7,54 +7,11 @@ A browser-based client for FAIR Data Point (FDP) administration. -## Background - -### FAIR principles - -The [FAIR principles] aim to make _data_ more **F**indable, **A**ccessible, **I**nteroperable, and **R**eusable. - -### FAIR Data Point (FDP) - -#### Purpose - -A FAIR Data Point (FDP) is a tool for the publication of **_metadata_** describing datasets in a standardized form that unlocks the powers of [Semantic Web] technology. -The FDP uses the Resource Description Framework ([RDF]) and the Data Catalog Vocabulary ([DCAT]) to facilitate publication of metadata as [Linked (Open) Data], following the [FAIR principles]. - -[RDF] describes _things_ using statements of the form `(, , )`, called triples. -Together, these triples define a knowledge graph where the `` and `` terms represent nodes and the `` terms represent edges. -By storing metadata, in the form of RDF, in a [triple store], a type of graph database specialized for handling [RDF], an FDP gains the ability to perform advanced queries using the [SPARQL] query language. - -Due to the use of [Semantic Web] technology, metadata published on an FDP becomes part of a world wide web of knowledge. -This enables people and machines from around the globe to explore the metadata and discover relations between different datasets using logical inference and reasoning techniques. - -#### Specification - -The requirements for the [RDF] representation of FAIR Data Point metadata are defined in the [FDP 1.2 specification]. -Compliance with the [FDP 1.2 specification] specification implies the following: - -1. The FDP root URL must resolve to a metadata description of the FDP itself as a [DCAT] `MetadataService`. - This description must include a link to the FDP's primary API endpoint, indicated by `dcat:endpointURL`. -2. The FDP must expose metadata in the form of [RDF], supporting at least the [Turtle] (default) and [JSON-LD] representations. -3. Each metadata record on an FDP should be linked to a "profile" which points to a metadata schema, expressed in the Shapes Constraint Language ([SHACL]), that can be used for validation. -4. FDP metadata schemas must have (a subclass of) [DCAT] `Resource` as the target class. -5. The FDP metadata must include Linked Data Platform ([LDP]) containment statements. - -The [FDP 1.2 specification] also mentions that the FDP must provide an API following [REST] guidelines so that a client is able to discover the available actions and access the resources it needs. - -#### Reference implementation and API - -The [FDP reference implementation] is a Java-based implementation of the [FDP 1.2 specification] that provides an HTTP API for manipulating and querying RDF metadata. -This enables users, like data stewards, to build automated metadata publication workflows for the FDP. -The FDP API is intended primarily for machine interaction and exposes machine-readable documentation based on the [OpenAPI 3 spec]. - -However, direct human interaction with the FDP API can be a bit cumbersome. -To simplify direct human interaction with the FDP API, we offer the FDP client. - ## FAIR Data Point Client The FAIR Data Point (FDP) _client_ provides a web-based user interface that makes it easier for humans to interact with a FAIR Data Point by hiding the interactions with the FDP API. The client is a JavaScript (TypeScript) application that runs entirely in the browser, without any server-side rendering. -Under the hood, the FDP client uses the JavaScript [Fetch API] to make HTTP requests to a remote FDP API that complies with the [FDP 1.2 specification]. +Under the hood, the FDP client uses the JavaScript [Fetch API] to make HTTP requests to a remote FDP API that complies with the [FDP 1.2 specification]. The main goal of the FDP client is to enable basic administration of the FDP, inspection of FDP content, and execution of simple queries. > [!NOTE] @@ -142,7 +99,6 @@ For example, you could use this to point the client to an actual FDP on the web, Note that the `config.local.json` file is ignored by `git`. -[FDP reference implementation]: https://github.com/FAIRDataTeam/FAIRDataPoint [legacy FDP client]: https://github.com/FAIRDataTeam/FAIRDataPoint-client [FDP 1.2 specification]: https://specs.fairdatapoint.org [FAIRDataTeam/compose]: https://github.com/FAIRDataTeam/compose/tree/master/fdp/ephemeral/v1/dev/fdp-client-redux @@ -156,19 +112,6 @@ Note that the `config.local.json` file is ignored by `git`. [dotenv]: https://github.com/motdotla/dotenv [vite docs]: https://vite.dev/guide/env-and-mode#env-files [fairdata/fairdatapoint-client-redux]: https://hub.docker.com/r/fairdata/fairdatapoint-client-redux -[RDF]: https://www.w3.org/TR/rdf12-primer/ -[DCAT]: https://www.w3.org/TR/vocab-dcat-3/ -[SPARQL]: https://www.w3.org/TR/sparql11-query/ -[Linked (Open) Data]: https://www.w3.org/DesignIssues/LinkedData -[FAIR principles]: https://doi.org/10.1038/sdata.2016.18 [Nginx hardened image]: https://hub.docker.com/hardened-images/catalog/dhi/nginx -[triple store]: https://opendatahandbook.org/glossary/en/terms/triple-store/ -[Semantic Web]: https://www.w3.org/2001/sw/SW-FAQ -[Turtle]: https://www.w3.org/TR/rdf12-turtle/ -[JSON-LD]: https://json-ld.org/primer/latest/ -[SHACL]: https://www.w3.org/TR/shacl/ -[LDP]: https://www.w3.org/TR/ldp/ -[OpenAPI 3 spec]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.2.0.md -[REST]: https://roy.gbiv.com/pubs/dissertation/rest_arch_style.htm [Docker Compose]: https://docs.docker.com/compose/ [Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API From 5256e89eced1e5dfd8114b5cb77b817824c82bd3 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Fri, 17 Jul 2026 13:55:01 +0200 Subject: [PATCH 24/26] configure nginx to send cache-control no-cache for files from public/ dir this prevents clients from using stale copies, because it forces the browser to re-validate the file with the server, based on ETag or Last-Modified headers see https://httpwg.org/specs/rfc7234.html#validation.model --- docker.nginx.conf | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docker.nginx.conf b/docker.nginx.conf index 9940a2f..3d8b888 100644 --- a/docker.nginx.conf +++ b/docker.nginx.conf @@ -46,7 +46,22 @@ http { try_files $uri $uri/ /index.html; } + location ~* ^\/(?:config\.json|favicon\.svg|assets\/fair-logo\.png)$ { # Case-insensitive regex match for overridable static files + # For static files from the public/ folder, which can be overridden using docker bind-mounts, + # cache-busting by versioned or content-hashed URL is not convenient. + # To prevent clients from using stale copies of these files, we use "no-cache" to enforce re-validation based on ETag or Last-Modified headers. + # https://httpwg.org/specs/rfc7234.html#validation.model + # Note that Nginx automatically generates ETag headers for static files by default. + # https://nginx.org/en/docs/http/ngx_http_core_module.html#etag + add_header Cache-Control "no-cache"; # Can be stored in caches, but must be re-validated with server before reuse + add_header X-Content-Type-Options nosniff; + } + location ~* \.(?:ico|css|js|gif|jpe?g|png|woff2?|eot|ttf|svg|map)$ { # Case-insensitive regex match for common static asset extensions + # Static files outside the public/ folder are processed during Vite builds and get a content-hashed filename. + # As a result, the URL changes whenever the file content changes. + # This enables cache-busting and allows the resources to be cached as "immutable". + # https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching#cache_busting expires 1y; # Set the Expires header to 1 year in the future for long-term caching access_log off; # Disable access logging for these static assets add_header Cache-Control "public, immutable"; # Tell browsers the resource URL is versioned/content-hashed and won't change during its cache lifetime From 3f1e35f21e521c736acb43ebe88fd9bd900dbf73 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Fri, 17 Jul 2026 10:44:50 +0200 Subject: [PATCH 25/26] add FDP background section to readme --- README.md | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/README.md b/README.md index 8d6137c..5b35214 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,49 @@ A browser-based client for FAIR Data Point (FDP) administration. +## Background + +### FAIR principles + +The [FAIR principles] aim to make _data_ more **F**indable, **A**ccessible, **I**nteroperable, and **R**eusable. + +### FAIR Data Point (FDP) + +#### Purpose + +A FAIR Data Point (FDP) is a tool for the publication of **_metadata_** describing datasets in a standardized form that unlocks the powers of [Semantic Web] technology. +The FDP uses the Resource Description Framework ([RDF]) and the Data Catalog Vocabulary ([DCAT]) to facilitate publication of metadata as [Linked (Open) Data], following the [FAIR principles]. + +[RDF] describes _things_ using statements of the form `(, , )`, called triples. +Together, these triples define a knowledge graph where the `` and `` terms represent nodes and the `` terms represent edges. +By storing metadata, in the form of RDF, in a [triple store], a type of graph database specialized for handling [RDF], an FDP gains the ability to perform advanced queries using the [SPARQL] query language. + +Due to the use of [Semantic Web] technology, metadata published on an FDP becomes part of a world wide web of knowledge. +This enables people and machines from around the globe to explore the metadata and discover relations between different datasets using logical inference and reasoning techniques. + +#### Specification + +The requirements for the [RDF] representation of FAIR Data Point metadata are defined in the [FDP 1.2 specification]. +Compliance with the [FDP 1.2 specification] specification implies the following: + +1. The FDP root URL must resolve to a metadata description of the FDP itself as a [DCAT] `MetadataService`. + This description must include a link to the FDP's primary API endpoint, indicated by `dcat:endpointURL`. +2. The FDP must expose metadata in the form of [RDF], supporting at least the [Turtle] (default) and [JSON-LD] representations. +3. Each metadata record on an FDP should be linked to a "profile" which points to a metadata schema, expressed in the Shapes Constraint Language ([SHACL]), that can be used for validation. +4. FDP metadata schemas must have (a subclass of) [DCAT] `Resource` as the target class. +5. The FDP metadata must include Linked Data Platform ([LDP]) containment statements. + +The [FDP 1.2 specification] also mentions that the FDP must provide an API following [REST] guidelines so that a client is able to discover the available actions and access the resources it needs. + +#### Reference implementation and API + +The [FDP reference implementation] is a Java-based implementation of the [FDP 1.2 specification] that provides an HTTP API for manipulating and querying RDF metadata. +This enables users, like data stewards, to build automated metadata publication workflows for the FDP. +The FDP API is intended primarily for machine interaction and exposes machine-readable documentation based on the [OpenAPI 3 spec]. + +However, direct human interaction with the FDP API can be a bit cumbersome. +To simplify direct human interaction with the FDP API, we offer the FDP client. + ## FAIR Data Point Client The FAIR Data Point (FDP) _client_ provides a web-based user interface that makes it easier for humans to interact with a FAIR Data Point by hiding the interactions with the FDP API. @@ -99,6 +142,7 @@ For example, you could use this to point the client to an actual FDP on the web, Note that the `config.local.json` file is ignored by `git`. +[FDP reference implementation]: https://github.com/FAIRDataTeam/FAIRDataPoint [legacy FDP client]: https://github.com/FAIRDataTeam/FAIRDataPoint-client [FDP 1.2 specification]: https://specs.fairdatapoint.org [FAIRDataTeam/compose]: https://github.com/FAIRDataTeam/compose/tree/master/fdp/ephemeral/v1/dev/fdp-client-redux @@ -112,6 +156,19 @@ Note that the `config.local.json` file is ignored by `git`. [dotenv]: https://github.com/motdotla/dotenv [vite docs]: https://vite.dev/guide/env-and-mode#env-files [fairdata/fairdatapoint-client-redux]: https://hub.docker.com/r/fairdata/fairdatapoint-client-redux +[RDF]: https://www.w3.org/TR/rdf12-primer/ +[DCAT]: https://www.w3.org/TR/vocab-dcat-3/ +[SPARQL]: https://www.w3.org/TR/sparql11-query/ +[Linked (Open) Data]: https://www.w3.org/DesignIssues/LinkedData +[FAIR principles]: https://doi.org/10.1038/sdata.2016.18 [Nginx hardened image]: https://hub.docker.com/hardened-images/catalog/dhi/nginx +[triple store]: https://opendatahandbook.org/glossary/en/terms/triple-store/ +[Semantic Web]: https://www.w3.org/2001/sw/SW-FAQ +[Turtle]: https://www.w3.org/TR/rdf12-turtle/ +[JSON-LD]: https://json-ld.org/primer/latest/ +[SHACL]: https://www.w3.org/TR/shacl/ +[LDP]: https://www.w3.org/TR/ldp/ +[OpenAPI 3 spec]: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.2.0.md +[REST]: https://roy.gbiv.com/pubs/dissertation/rest_arch_style.htm [Docker Compose]: https://docs.docker.com/compose/ [Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API From 3856352c04c83d55171e86ac67badca97c972038 Mon Sep 17 00:00:00 2001 From: dennisvang <29799340+dennisvang@users.noreply.github.com> Date: Thu, 13 Aug 2026 14:53:22 +0200 Subject: [PATCH 26/26] mention swagger-ui --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eeb23b7..b379aa6 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,8 @@ The [FDP 1.2 specification] also mentions that the FDP must provide an API follo The [FDP reference implementation] is a Java-based implementation of the [FDP 1.2 specification] that provides an HTTP API for manipulating and querying RDF metadata. This enables users, like data stewards, to build automated metadata publication workflows for the FDP. The FDP API is intended primarily for machine interaction and exposes machine-readable documentation based on the [OpenAPI 3 spec]. - -However, direct human interaction with the FDP API can be a bit cumbersome. +The FDP reference implementation also provides a [swagger-ui] interface that allows humans to explore the API using a web browser. +However, direct human interaction with the FDP API can still be a bit cumbersome. To simplify direct human interaction with the FDP API, we offer the FDP client. ## FAIR Data Point Client @@ -173,3 +173,4 @@ Note that the `config.local.json` file is ignored by `git`. [Nginx hardened image]: https://hub.docker.com/hardened-images/catalog/dhi/nginx [Docker Compose]: https://docs.docker.com/compose/ [Fetch API]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API +[swagger-ui]: https://swagger.io/open-source/swagger-ui/