Ofeed
Orienteering Cloud Data Hub
Install / Use
/learn @orienteerfeed/OfeedREADME
OFeed
OrienteerFeed (OFeed) is a monorepo web platform for orienteering event data, combining REST + GraphQL APIs, real-time event workflows, and a modern React frontend.
⭐ Star us on GitHub — it motivates us a lot!
How It Works
This application is like a digital hub for all things related to orienteering events. It serves as a one-stop platform where you can get details about various events, the classes offered at these events, and the competitors participating in them. It provides these services through a web server and is capable of communicating using both RESTful APIs and GraphQL, which are two ways of fetching data from a server.
Localization
We are using Weblate free localization hosting, thanks to weblate.org and Michal Čihař.
Tech Stack
- Client: Vite + React + TypeScript
- Server: Hono + TypeScript + Prisma (MariaDB adapter)
- UI: shadcn/ui + Tailwind CSS
- Data and Routing: TanStack Query + TanStack Router
- i18n: i18next + react-i18next
- Monorepo: pnpm workspaces + Turborepo
- Shared:
@repo/shared(shared schemas/types)
Repository Layout
apps/
client/ # Vite + React application
server/ # Hono + Prisma API
packages/
shared/ # shared schemas/types
Requirements
- Node.js version pinned in
.nvmrc(22.20.0) - pnpm
>=10.20.0 <11(recommended:10.29.2)
Use nvm to install and activate the exact Node.js version from .nvmrc:
nvm install
nvm use
Use Corepack:
corepack enable
corepack prepare pnpm@10.29.2 --activate
pnpm -v
Quick Start (Local Development)
git clone https://github.com/orienteerfeed/ofeed.git
cd ofeed
pnpm setup:dev
pnpm setup:dev:
- installs dependencies
- creates
apps/server/.envfromapps/server/.env.example(if missing) - creates
apps/client/.envfromapps/client/.env.example(if missing)
Then run:
docker compose -f docker-compose.mysql.yaml up -d mysql
pnpm db:generate
pnpm db:migrate
pnpm dev
Default local URLs:
- Client:
http://localhost:3000 - API:
http://localhost:3001 - GraphQL:
http://localhost:3001/graphql - OpenAPI JSON:
http://localhost:3001/doc - API Reference UI:
http://localhost:3001/reference - Health:
http://localhost:3001/health - Metrics (Prometheus):
http://localhost:3001/metrics
Development Commands (Root)
pnpm setup:dev- bootstrap local dev environmentpnpm dev- run client + server in parallel via Turborepopnpm build- build all workspace packages/appspnpm lint- lint all workspace packages/appspnpm format- format repo files with Prettierpnpm format:check- check formattingpnpm type-check- type-check all packages/appspnpm test- run tests across workspacepnpm test:watch- run tests in watch mode (parallel)pnpm test:client- run only client testspnpm test:server- run only server testspnpm db:generate- run prisma generate via turbopnpm db:migrate- run prisma migrate via turbopnpm clean- clean turbo outputs
App-Level Commands
Server (apps/server)
pnpm dev/pnpm start:dev- run API in watch modepnpm build- build@repo/sharedfor Node and compile the server todist/index.jspnpm start:dist- run the built server fromdist/index.jspnpm test/pnpm test:watchpnpm lint/pnpm lint:fixpnpm db:generatepnpm db:migratepnpm db:migrate:deploypnpm db:seed
Shared (packages/shared)
pnpm build- compile runtime JS todist/for Node consumers such as the built serverpnpm type-check
Client (apps/client)
pnpm devpnpm buildpnpm test/pnpm test:watchpnpm lint/pnpm lint:fixpnpm e2e
Database and Prisma
- Prisma schema:
apps/server/prisma/schema.prisma - Prisma Client output is generated into:
apps/server/src/generated/prisma - ORM: Prisma v7 with MariaDB adapter (
@prisma/adapter-mariadb)
Docker Compose
This repository does not require root .env for application runtime.
Use app-level env files:
apps/server/.envapps/client/.env
Create them from examples:
cp apps/server/.env.example apps/server/.env
cp apps/client/.env.example apps/client/.env
Start full app stack:
docker compose up -d --build
Available compose overlays:
docker-compose.mysql.yaml- local MySQL/MariaDB-compatible DBdocker-compose.minio.yaml- local MinIO + initdocker-compose.traefik.yaml- Traefik labels/integrationdocker-compose.scaled.yaml- static replicas for api/frontenddocker-compose.infra.yaml- attach shared external networkdocker-compose.remote.yaml- host networking variant (API)
Docker Compose can also use a root .env only for Compose interpolation, for example:
SERVER_PORT=3001FRONTEND_PORT=3000API_HOST=api.orienteerfeed.comFRONTEND_HOST=orienteerfeed.com
Helm / k3s Deployment
- Helm chart:
deploy/helm/ofeed - Deployment guide:
docs/DEPLOYMENT_K3S.md
CI/CD and Versioning Flow
Automated versioning and GitHub releases
Releases are automated from main via semantic-release
(.github/workflows/release.yaml), but only when a release is explicitly
requested.
You can request a release in three ways:
- label a PR with one of
release:patch,release:minor,release:major - add
Release-Type: patch|minor|majorto the commit body when pushing directly tomain - use
workflow_dispatchand select the desired release type manually
You can also use a commit marker like [release:patch], but the
Release-Type: trailer is preferred because it keeps the subject line clean.
When a requested release reaches main, the workflow:
- calculates the next version from the requested release type
- creates git tag
vX.Y.Z - creates GitHub Release
- if needed, opens or updates a follow-up PR that syncs the root
package.jsonversion to the released tag
Because main is protected and changes must go through a pull request, the
workflow does not push generated release commits directly back to main.
Automated release notes live on the GitHub Release; keep CHANGELOG.md
maintained manually when you want a repository-local summary.
If no explicit release request is present, the workflow exits without creating a new version.
Note:
- set optional secret
RELEASE_PLEASE_TOKEN(PAT) to allow tag/release events to trigger downstream workflows (for example Docker publish). If it is not set, workflow falls back toGITHUB_TOKEN.
Example direct push with explicit patch release:
git commit -m "fix(auth): handle invalid refresh token" -m "Release-Type: patch"
git push origin main
Docker image publishing
Docker images are published by .github/workflows/publish-images-ghcr.yaml on tag v* to GHCR:
ghcr.io/orienteerfeed/ofeed-serverghcr.io/orienteerfeed/ofeed-client
Packages are published as private by default.
Contributing
Please read CONTRIBUTING.md for contribution process and standards.
- Create your feature branch:
git checkout -b feature/my-new-feature - Commit your changes using Conventional Commits:
git commit -m "feat(server): add event image upload validation"
git commit -m "fix(auth): handle invalid refresh token"
git commit -m "docs(readme): update contributing examples"
git commit -m "feat(events): add competitor status sync" -m "Refs #45"
git commit -m "feat(events): add competitor status sync" -m "Closes #45"
- Push to the branch:
git push origin feature/my-new-feature - Submit a pull request :D
Changelog
See CHANGELOG.md.
Credits
License
This repository is licensed under the GNU General Public License v3.0. See LICENSE.
Contributions are accepted under the terms of CLA.md. By contributing, you agree that your contributions may be relicensed and used in commercial products and SaaS offerings.
