A single-page application that collects developer experience feedback through a three-question survey and displays aggregated results as a grouped bar chart. Built with React and Node.js, containerized for OpenShift, and delivered via Red Hat Developer Hub.
The survey measures friction across three dimensions:
- Development Environment Setup -- How much friction happens getting a dev environment running?
- CI/CD Pipeline Experience -- How reliable and fast are builds and deploys?
- Finding Documentation -- How easy is it to find the documentation you need?
Each question offers three responses (Low/Medium/High friction). After submitting, the user sees a bar chart of all responses collected so far.
┌──────────────────────────────────────┐
│ Single Container │
│ │
│ React SPA ──► Node.js/Express API │
│ (static) (in-memory store) │
│ │
│ Port 8080 │
└──────────────────────────────────────┘
- Frontend: React (Vite) with Recharts for data visualization
- Backend: Node.js + Express serving the static frontend and a REST API
- Storage: In-memory -- responses reset when the container restarts
- No external database is required
| Method | Path | Description |
|---|---|---|
| POST | /api/responses |
Submit a survey response |
| GET | /api/responses/results |
Retrieve aggregated counts |
POST body:
{ "q1": 2, "q2": 1, "q3": 3 }GET response:
{
"q1": { "1": 12, "2": 34, "3": 8 },
"q2": { "1": 20, "2": 15, "3": 19 },
"q3": { "1": 5, "2": 30, "3": 19 },
"total": 54
}├── frontend/ React SPA (Vite + TypeScript)
│ └── src/
│ ├── App.tsx
│ └── components/
│ ├── SurveyForm.tsx
│ └── ResultsChart.tsx
├── backend/ Node.js API (Express + TypeScript)
│ └── src/
│ ├── index.ts
│ ├── store.ts
│ └── routes/responses.ts
├── k8s/ Plain OpenShift manifests (Deployment, Service, Route)
├── tekton/ Tekton Pipeline, Triggers, and EventListener
├── docs/ Documentation (served via RHDH TechDocs)
├── Containerfile Multi-stage container build (UBI 9)
├── mkdocs.yml MkDocs config for TechDocs
├── openapi.yaml OpenAPI 3.0 spec for the REST API
├── catalog-info.yaml RHDH component and API registration
└── template.yaml RHDH Software Template (installs pipeline + triggers build)
Start the backend and frontend dev servers:
cd backend && npm install && npm run devcd frontend && npm install && npm run devThe Vite dev server (default port 5173) proxies /api requests to the backend on port 8080.
The container is built from Red Hat UBI 9 Node.js images (ubi9/nodejs-20 for build stages, ubi9/nodejs-20-minimal for the runtime).
podman build --platform linux/amd64 -f Containerfile -t developer-friction-survey .
podman run -p 8080:8080 developer-friction-surveyThe --platform linux/amd64 flag ensures the final image targets x86_64 for OpenShift. The build stages (frontend and backend) run natively on the host architecture since they only produce platform-independent output (static JS/CSS). This avoids esbuild crashes under QEMU emulation on ARM Macs.
Then open http://localhost:8080.
After building the image locally, tag and push it to your quay.io repository:
podman tag developer-friction-survey quay.io/YOUR_ORG/developer-friction-survey:latest
podman push quay.io/YOUR_ORG/developer-friction-survey:latestMake sure the repository visibility in quay.io is set appropriately for your OpenShift cluster to pull from it.
RHDH uses a Software Template to install the Tekton pipeline and trigger a full build-and-deploy:
- Register
template.yamlin your RHDH catalog locations. - In RHDH, go to Create and choose Deploy Developer Friction Survey.
- Provide the target OpenShift namespace and confirm the defaults.
- RHDH installs the Tekton Pipeline, then triggers a PipelineRun that clones the repo, builds with Buildah, pushes to quay.io, and deploys.
Monitor progress on the component's CI tab in RHDH.
Tekton Triggers are included to automatically rebuild and redeploy whenever you push to the GitHub repo.
-
Apply all Tekton resources (pipeline, triggers, event listener, and route):
oc project bobcat oc apply -f tekton/
-
Get the webhook URL:
oc get route developer-friction-survey-webhook -o jsonpath='https://{.spec.host}' -
In your GitHub repo, go to Settings > Webhooks > Add webhook:
- Payload URL: the route URL from step 2
- Content type:
application/json - Events: select Just the push event
- Active: checked
Every push to the repo will now trigger a full build-and-deploy pipeline run automatically.
oc apply -f tekton/pipeline.yaml
oc create -f tekton/pipelinerun.yamlThe pipeline clones the repo, builds the container with Buildah, pushes to quay.io/cbowland/developer-friction-survey, and deploys the app.
If the image is already in quay.io:
oc apply -f k8s/
oc rollout status deployment/developer-friction-surveyThe catalog-info.yaml registers the component in the RHDH catalog. Annotations connect it to the Kubernetes deployment and Tekton pipeline runs so you can monitor everything from the RHDH component page.