We love contributions! This guide will help you get started quickly.
TrakRF Platform is an RFID/BLE asset tracking system for manufacturing and logistics. It provides real-time location tracking, historical analytics, and seamless integration with ERP/WMS systems. The platform consists of a Go backend, React frontend, TimescaleDB for time-series data, and an integrated MQTT broker for device communication.
- Go 1.25+ - For backend development (required for Air hot-reload)
- Node.js 18+ - For frontend development
- Docker & Docker Compose - For running dependencies
- Git - For version control
- TimescaleDB - Via Docker or TigerData cloud
# 1. Fork this repo on GitHub
# 2. Clone your fork
git clone https://github.com/YOUR_USERNAME/platform.git
cd platform
# 3. Start dependencies
docker-compose up -d timescaledb
# 4. Set up environment
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
# 5. Run migrations
cd backend && go run cmd/migrate/main.go up
# 6. Run tests
go test ./...
cd ../frontend && pnpm test# Branch naming:
# - feature/add-xyz (new features)
# - fix/broken-xyz (bug fixes)
# - docs/update-xyz (documentation)
git checkout -b feature/add-asset-historyProject Philosophy:
- Clean Architecture - Separate concerns between API, business logic, and data layers
- Real-time First - Design for live updates and streaming data
- Multi-tenant - Always consider data isolation
- API-driven - Frontend consumes only documented APIs
Backend Example (Good):
// Clear service method with proper error handling
func (s *AssetService) GetLocation(ctx context.Context, assetID string) (*Location, error) {
if err := s.validateAssetAccess(ctx, assetID); err != nil {
return nil, fmt.Errorf("access denied: %w", err)
}
return s.repo.GetLatestLocation(ctx, assetID)
}Frontend Example (Good):
// Direct API call with proper typing
export async function fetchAssetLocation(assetId: string): Promise<Location> {
const response = await api.get<Location>(`/assets/${assetId}/location`);
return response.data;
}# Backend tests
cd backend
go test ./...
go test -race ./... # Race condition check
# Frontend tests
cd frontend
pnpm test
pnpm run lint
# Integration tests (requires running services)
docker-compose up -d
go test ./tests/integration -tags=integration# Use conventional commits
git commit -m "feat: add historical location queries"
git commit -m "fix: handle MQTT reconnection"
git commit -m "docs: update API examples"// backend/services/asset_test.go
func TestAssetService_GetLocation(t *testing.T) {
// Test with mock repository
repo := &mocks.AssetRepository{}
service := services.NewAssetService(repo)
// Define expectations and test
}// frontend/src/services/__tests__/asset.test.ts
describe('Asset Service', () => {
it('fetches asset location', async () => {
const location = await fetchAssetLocation('asset-123');
expect(location).toHaveProperty('latitude');
});
});# Run full stack locally
docker-compose up -d
cd backend && go run cmd/server/main.go &
cd frontend && pnpm dev &
# Run API tests
cd tests/api && pnpm test-
Push to your fork:
git push origin feature/add-asset-history
-
Open a Pull Request:
- Go to https://github.com/trakrf/platform
- Click "New Pull Request"
- Select your branch
- Describe what you changed and why
-
PR Checklist:
- Tests pass (backend:
go test ./..., frontend:pnpm test) - Code follows project conventions
- Database migrations included if needed
- API documentation updated
- Commit messages use conventional format
- Tests pass (backend:
- Define the route in
backend/api/routes.go - Implement handler in appropriate controller
- Add service layer logic
- Write tests for handler and service
- Update API documentation
- Create component in appropriate directory
- Add API client code in
services/ - Update relevant Redux store/hooks
- Add component tests
- Update Storybook if applicable
- Create migration in
database/migrations/ - Test migration up and down
- Update repository interfaces
- Consider TimescaleDB features (continuous aggregates, compression)
TrakRF declares the platform version in the root VERSION file (TRA-1126). A
release is a reviewed one-line diff; CI produces the git tag and the release
image tag as outputs of the merge build. See
docs/adr/0004-declared-platform-version.md
for why the version is declared rather than derived, and
docs/adr/0001-platform-vs-api-versioning.md
for the three-axis versioning rationale (platform vs API contract vs spec).
The full procedure is docs/releasing.md — the backup,
the ledger relocation ordering, promotion, the post-deploy checks and rollback.
Follow it rather than the summary here.
The shape of it:
- Open a release PR that does two things and nothing else: flip
VERSIONfromX.Y.Z-devtoX.Y.Z, and move the shipping items from## [Unreleased]into a new## [X.Y.Z] - YYYY-MM-DDsection ofCHANGELOG.md.lint-testfails the PR if the section is missing.printf 'X.Y.Z\n' > VERSION just check-changelog
- Merge it. The merge build IS the release build. There is no tag to push and no ordering to get right: the version is a property of the commit, so two builds of it cannot disagree.
.github/workflows/docker-build.ymlbakes the version into the backend binary (-X main.version) and the frontend bundle (VITE_APP_VERSION), publishesghcr.io/trakrf/backend:sha-<short>, then — in thereleasejob — creates the git tagvX.Y.Z, publishes:vX.Y.Z, and opens the follow-up PR returningVERSIONto the next-dev.- Promote, once that build is green.
promote-prodre-tags the manifest — there is no rebuild — and refuses any image that is not the release commit:ArgoCD Image Updater then picks up the new digest; expect up to ~2 minutes.gh workflow run promote-prod.yml -f source=vX.Y.Z
- Verify post-deploy:
curl https://app.trakrf.id/health | jq '.version, .commit, .tag' curl https://app.trakrf.id/version.json # Both should report vX.Y.Z; UI nav header should match.
| Axis | Source | Bumped when |
|---|---|---|
| Platform release | Root VERSION file → CI mints vX.Y.Z |
A new build is shipped |
| API contract | URL path /api/v1/ |
Breaking change to customer-facing API |
| OpenAPI spec | info.version in docs/api/openapi.public.{json,yaml} |
Breaking change to spec shape (TRA-672) |
These three numbers move independently. Platform can ship many releases
inside one /api/v1/; spec can ship many revisions inside one platform
release. Do not couple them.
Optional. The git-log readability convention (feat:, fix:, chore:,
docs:) is encouraged but no tool depends on it — bumps are manual.
- Questions? Open a GitHub Discussion
- Found a bug? Open an issue with steps to reproduce
- Have an idea? Open a discussion before coding major features
Be professional, respectful, and constructive. We're building critical infrastructure for businesses - act accordingly.
By submitting a pull request, you agree that:
- You have the right to submit the contribution
- You grant DevOps To AI LLC dba TrakRF a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable license to use your contribution under any terms, including commercial licensing
- Your contribution will be licensed under BSL 1.1 for public use
- TrakRF may relicense your contribution under different terms for commercial customers
This ensures we can maintain the dual licensing model (BSL for public, commercial licenses for enterprise) while properly attributing your contribution.