
The first workout screen works. Users can record a session, and the API saves it.
Then another developer joins. They cannot identify the required environment variables. The backend starts only after an undocumented database change. A pull request breaks a calculation, but nobody notices until someone tests the screen manually.
The project needs a repeatable way to understand, verify, and change its behavior.
A maintainable fitness app project setup connects clear component boundaries, automated checks, and documentation another developer can follow.
This guide uses a hypothetical fitness application, not a real production system. It contains a mobile client and a Node.js API, with an optional administration interface.
Define the Architecture Before Creating Folders
Identify what runs, what stores data, and what communicates across a boundary.
For the hypothetical application:
- The mobile client presents workouts and records input.
- The backend API authenticates requests and manages application data.
- The database stores users, exercises, and workout records.
- An optional administration interface manages approved content.
- Shared schemas describe selected request and response formats.
- Tests and development tools verify the components.
A database layer can remain part of the API. A shared package should exist because multiple components need a maintained contract, not simply because monorepos often contain one.
Monorepo or Separate Repositories?
A monorepo keeps related components together and can make coordinated API, schema, and client changes easier to review.
Separate repositories can suit independent ownership, access restrictions, or release processes.
| Consideration | Monorepo | Separate repositories |
|---|---|---|
| Coordinated changes | One pull request can cover related changes | Changes need cross-repository coordination |
| Access boundaries | Usually broader repository visibility | Access can be isolated by component |
| Shared tooling | Central configuration is possible | Configuration may need distribution |
| Releases | Require component-specific conventions | Separate releases still need compatibility planning |
Choose according to actual coordination and ownership needs.
For framework planning, see React Native vs Flutter for fitness app development. Document the approach actually selected and its platform-specific requirements.
Design a Practical Repository Structure
This directory map is illustrative, not a mandatory template.
| Path | Responsibility |
|---|---|
apps/mobile/ |
Mobile application |
apps/admin/ |
Optional administration interface |
services/api/ |
Backend and data-access layer |
services/api/src/ |
API implementation |
services/api/tests/ |
API unit and integration tests |
services/api/migrations/ |
Database migrations when required |
packages/shared/ |
Shared contracts when justified |
docs/ |
Architecture, setup, API, and deployment documentation |
scripts/ |
Maintained development utilities |
tests/e2e/ |
Cross-component user-journey tests |
.github/workflows/ |
GitHub Actions workflows |
.github/PULL_REQUEST_TEMPLATE.md |
Pull request prompts |
.gitignore |
Excluded local and generated files |
.editorconfig |
Basic editor conventions |
README.md |
Project entry point |
CONTRIBUTING.md |
Collaboration instructions |
The API in this example has its own package manifest and lockfile. The repository does not use npm workspaces.
A smaller project can omit the admin application, shared package, and cross-component test directory.
Choose license terms appropriate to the project's intended distribution. Do not automatically apply an open-source license to proprietary code.
Organize Code Around Responsibilities
For workout logging, separate presentation, application logic, business rules, data access, and authorization.
A screen should not independently implement access policy. The backend must enforce access to protected data.
Workout calculations should not depend on UI components. A duration function should receive defined inputs and return a result without requiring a network connection.
This makes empty records, invalid values, and unit conventions easier to test.
Avoid creating interfaces and factories for every small function. Introduce abstraction when it manages an existing dependency or variation.
For related domain planning, see fitness tracking app development.
Establish Git and Collaboration Conventions
Short-lived branches and pull requests may provide enough structure for a small team.
Document branch creation, review responsibilities, required checks, release identification, and urgent-fix procedures.
Commit messages should describe the change:
Add workout history filtering by date
Reject negative exercise duration values
Fix duplicate workout import after retry
Document local database migration setup
If using Conventional Commits, document the rules and any tooling that depends on them.
Make Pull Requests Easier to Review
A useful description answers:
- What behavior changed?
- Why was it needed?
- How was it verified?
- Does it require a migration or configuration change?
- Which documentation changed?
Configure appropriate branch protection or rulesets where available. Record exact required check names: renaming a workflow check can affect merging.
Commit applicable lockfiles and review dependency changes with the application changes.
Configure Continuous Integration Around Real Checks
Continuous integration runs verification when changes are proposed or integrated.
Suitable checks include dependency installation, formatting, linting, type checking, unit tests, integration tests, builds, and security checks.
Each check should answer a question. A build verifies compilation; it does not prove that a workout is saved correctly.
CI differs from deployment. Successful checks do not require publishing an app or changing production.
Start with a small pipeline that reliably runs meaningful checks. Extend it when additional risks justify the work.
A Minimal GitHub Actions Workflow
This workflow checks only the hypothetical Node.js API.
Assumptions:
- The API lives in
services/api/. - It has its own committed
package-lock.json. - It does not depend on an unconfigured local shared package.
- Node.js 24 is compatible with its dependencies.
- The package defines lint, test, and build scripts.
- Tests run once and exit.
- Production credentials are unnecessary.
Node.js 24 is a supported LTS line at the time of writing. Choose a supported version compatible with your project and align local development with CI.
Reference: Node.js release information.
Create .github/workflows/ci.yml:
name: API CI
on:
pull_request:
push:
branches:
- main
permissions:
contents: read
jobs:
api-checks:
name: API checks
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: services/api
steps:
- name: Check out repository
uses: actions/checkout@v7
with:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: "24"
package-manager-cache: false
- name: Install dependencies
run: npm ci
- name: Run lint checks
run: npm run lint
- name: Run tests
run: npm test
- name: Validate build
run: npm run build
The workflow uses read-only repository permissions and disables persisted checkout credentials. It has no deployment step.
Consult the official checkout and setup-node documentation for runner compatibility.
For stronger control over updates, use reviewed full commit SHA pins and maintain an update process.
Configure the Package Scripts First
For a TypeScript API using ESLint and Vitest, the relevant package manifest excerpt could be:
{
"private": true,
"scripts": {
"lint": "eslint .",
"test": "vitest run",
"build": "tsc -p tsconfig.json"
}
}
This is not a complete manifest. It requires installed development dependencies, ESLint configuration, TypeScript configuration, and actual tests.
Do not hide missing required scripts with optional execution flags.
The npm ci command requires an existing lockfile and fails if it does not match the manifest. Keep installation settings consistent with those used to create the lockfile.
Reference: npm ci documentation.
Add Mobile Validation Separately
Passing API checks does not verify the mobile application.
Add checks appropriate to the actual framework and supported platforms. iOS build jobs generally need suitable macOS infrastructure and the relevant Apple toolchain.
Keep signed releases separate from ordinary pull request checks.
Handle Environment Configuration Safely
Document configuration separately for each component and environment.
An API example configuration file could contain:
DATABASE_URL=
AUTH_ISSUER_URL=
PORT=3000
The mobile component might use:
API_BASE_URL=http://localhost:3000
These examples contain no credentials. Explain how configuration is loaded and validated; an example file does not implement environment loading.
For emulators and physical devices, document how to reach the development API. Localhost refers to the device or machine interpreting the address.
Exclude Secrets and Generated Files
An illustrative root ignore file could include:
**/node_modules/
**/dist/
**/coverage/
.env
.env.*
**/.env
**/.env.*
!.env.example
!**/.env.example
Adapt generated-file exclusions to the framework.
Ignore rules do not remove files already tracked or erase history. If a credential is exposed, rotate or revoke it, review its use, and then address repository exposure.
Use restricted CI secrets only when necessary. Ordinary checks should use isolated test resources.
Mobile application configuration is not a safe place for privileged server credentials.
Write Documentation Developers Can Use
Documentation should enable tasks without duplicating information reliably maintained by tooling.
| Document | Purpose |
|---|---|
README.md |
Purpose, components, prerequisites, quick start, and checks |
docs/architecture.md |
Boundaries, data flows, and design decisions |
docs/development-setup.md |
Configuration, database setup, migrations, and synthetic data |
docs/api-overview.md |
Authentication, errors, and maintained API contracts |
docs/deployment.md |
Releases, migrations, monitoring, rollback, and recovery |
CONTRIBUTING.md |
Branches, reviews, dependencies, and documentation expectations |
A README outline:
# Project Name
## Purpose
## Components
## Prerequisites
## Local Setup
## Configuration
## Database Setup
## Running the Application
## Running Checks
## Troubleshooting
## Contribution Workflow
## Deployment Documentation
Add verified commands and state where they run. Link to maintained API schemas rather than duplicating endpoint lists.
Update documentation in the same pull request as the relevant change.
For agency-built projects, also document repository administration and handover responsibilities. Related reading: fitness app development contracts: code and data ownership.
Document Fitness Data and Failure Behavior
Define identifiers, ownership, exercises, sets, repetitions, weights, units, duration, timestamps, completion, edits, and offline behavior.
Explain which records contribute to progress calculations. Record why each data field is collected and who can access it.
Related reading: fitness app data collection checklist.
Treat Integrations as Optional Components
Not every app needs HealthKit, Health Connect, or wearables.
When included, document permissions, supported data types, synchronization direction, provider limits, and disconnection.
Explain duplicate prevention, retries, missing information, expired authorization, delayed records, and partial imports.
Health Connect recommends aggregation for cumulative records such as steps to reduce double counting. Verify behavior for each record type and provider.
Reference: Health Connect data reading guidance.
Related reading:
Document Recommendation Logic If Present
Record inputs, constraints, model or provider versions, evaluation procedures, and fallbacks.
Rules and learned recommendations have different maintenance needs. Related reading: rules-based vs machine learning personalization.
Only include AI infrastructure when the product needs it.
Build Tests Around Important Decisions
| Level | Fitness-app example |
|---|---|
| Unit | Validate duration calculations and invalid inputs |
| Integration | Save and retrieve a workout through the API and database |
| End-to-end | Sign in, complete a workout, and reopen its history |
| Build | Compile supported application components |
| Regression | Reproduce a previously fixed duplicate-import defect |
Integration tests should use an isolated database with expected migrations. Never point them at production.
Use synthetic data and deterministic inputs. Test denied access as well as valid access, including whether one user can read another user's private workouts.
More expensive suites can run at appropriate stages, provided release-critical validation happens before release.
Plan Dependency and Access Maintenance
Record supported runtimes and check compatibility before upgrading.
Review dependency updates for purpose, maintenance, licensing, and operational implications.
Apply least privilege to repository members and CI identities. Restrict production records and release credentials.
Document upgrades, migration recovery, and incident responsibilities.
Automated vulnerability checks do not establish complete security or legal compliance. Privacy obligations depend on the product, data, jurisdictions, and agreements.
For related planning considerations, see fitness app HIPAA compliance and GDPR.
Common Setup Mistakes
| Mistake | Prevention |
|---|---|
| Unstructured code | Define component responsibilities |
| Premature repositories and abstractions | Add boundaries when justified |
| Missing lockfiles | Commit and review applicable lockfiles |
| Unusable README | Verify a clean setup |
| CI invokes nonexistent scripts | Run every command locally first |
| Secrets are committed | Use restricted configuration and review changes |
| Builds are treated as correctness proof | Test behavior and integrations |
| Migrations are ignored | Version them and test a fresh database |
| Only successful integrations are documented | Explain retries, missing data, and denied access |
| Passing CI deploys production without controls | Separate verification and release operations |
Project Setup Checklist
Repository and Architecture
- [ ] Identify components and ownership.
- [ ] Choose repository boundaries based on actual needs.
- [ ] Document important data flows.
- [ ] Remove unnecessary abstractions.
Git and Collaboration
- [ ] Define branches, reviews, and release conventions.
- [ ] Add a useful pull request template.
- [ ] Configure appropriate required checks.
- [ ] Document urgent-fix procedures.
Dependencies and Environment
- [ ] Record supported runtimes and toolchains.
- [ ] Commit manifests and lockfiles.
- [ ] Provide safe configuration examples.
- [ ] Document database setup and migrations.
CI and Testing
- [ ] Verify every CI script.
- [ ] Run checks on pull requests and main-branch pushes.
- [ ] Test business logic and integrations.
- [ ] Validate supported mobile platforms.
- [ ] Isolate tests from production.
Documentation
- [ ] Add a verified quick start.
- [ ] Explain architecture, APIs, and configuration.
- [ ] Document common setup failures.
- [ ] Update documentation with relevant changes.
Security and Access
- [ ] Exclude secrets and generated files.
- [ ] Review tracked files for sensitive information.
- [ ] Apply least-privilege repository and CI permissions.
- [ ] Define credential rotation and vulnerability handling.
Fitness Integrations
- [ ] Document units and record identity.
- [ ] Record applicable permissions and consent.
- [ ] Test duplicate records and synchronization failures.
- [ ] Explain external dependencies and fallbacks.
Deployment and Maintenance
- [ ] Separate CI from releases.
- [ ] Document deployment and migration procedures.
- [ ] Define monitoring, rollback, and recovery.
- [ ] Assign maintenance responsibilities.
Verify the Foundation With a Fresh Setup
Repository structure makes responsibilities visible. CI verifies selected behavior. Documentation explains how to work with the system.
Keep all three aligned with current requirements.
Ask another developer to clone the repository, follow the instructions, run the checks, and explain the main components. Fix the points where that process breaks.
Top comments (0)