SkillAgentSearch skills...

Ofeed

Orienteering Cloud Data Hub

Install / Use

/learn @orienteerfeed/Ofeed

README

OFeed

Nodejs Version CI License GitHub Stars

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/.env from apps/server/.env.example (if missing)
  • creates apps/client/.env from apps/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 environment
  • pnpm dev - run client + server in parallel via Turborepo
  • pnpm build - build all workspace packages/apps
  • pnpm lint - lint all workspace packages/apps
  • pnpm format - format repo files with Prettier
  • pnpm format:check - check formatting
  • pnpm type-check - type-check all packages/apps
  • pnpm test - run tests across workspace
  • pnpm test:watch - run tests in watch mode (parallel)
  • pnpm test:client - run only client tests
  • pnpm test:server - run only server tests
  • pnpm db:generate - run prisma generate via turbo
  • pnpm db:migrate - run prisma migrate via turbo
  • pnpm clean - clean turbo outputs

App-Level Commands

Server (apps/server)

  • pnpm dev / pnpm start:dev - run API in watch mode
  • pnpm build - build @repo/shared for Node and compile the server to dist/index.js
  • pnpm start:dist - run the built server from dist/index.js
  • pnpm test / pnpm test:watch
  • pnpm lint / pnpm lint:fix
  • pnpm db:generate
  • pnpm db:migrate
  • pnpm db:migrate:deploy
  • pnpm db:seed

Shared (packages/shared)

  • pnpm build - compile runtime JS to dist/ for Node consumers such as the built server
  • pnpm type-check

Client (apps/client)

  • pnpm dev
  • pnpm build
  • pnpm test / pnpm test:watch
  • pnpm lint / pnpm lint:fix
  • pnpm 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/.env
  • apps/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 DB
  • docker-compose.minio.yaml - local MinIO + init
  • docker-compose.traefik.yaml - Traefik labels/integration
  • docker-compose.scaled.yaml - static replicas for api/frontend
  • docker-compose.infra.yaml - attach shared external network
  • docker-compose.remote.yaml - host networking variant (API)

Docker Compose can also use a root .env only for Compose interpolation, for example:

  • SERVER_PORT=3001
  • FRONTEND_PORT=3000
  • API_HOST=api.orienteerfeed.com
  • FRONTEND_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|major to the commit body when pushing directly to main
  • use workflow_dispatch and 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.json version 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 to GITHUB_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-server
  • ghcr.io/orienteerfeed/ofeed-client

Packages are published as private by default.

Contributing

Please read CONTRIBUTING.md for contribution process and standards.

  1. Create your feature branch: git checkout -b feature/my-new-feature
  2. 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"
  1. Push to the branch: git push origin feature/my-new-feature
  2. Submit a pull request :D

Changelog

See CHANGELOG.md.

Credits

License

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.

View on GitHub
GitHub Stars14
CategoryDevelopment
Updated1d ago
Forks4

Languages

TypeScript

Security Score

95/100

Audited on Apr 5, 2026

No findings