Learn
Project Structure

Project Structure

A TracePath project is an observability boundary. It controls which telemetry shares dashboards and distributed traces, which framework-specific setup appears on the Connection page, and which runtime and artifact-upload credentials are used.

Choose projects around application runtime boundaries, not folders or processes.

The browser and mobile framework options below create real projects, but the browser and mobile SDKs are not published yet. Backend instrumentation via OpenTelemetry is the integration path that works today. Plan the project layout now; create the browser and mobile projects when their SDKs ship.

Recommended Structure

Application partTracePath projectFrameworkWhat it records
Backend systemOne backend projectOpenTelemetryEndpoints, spans, issues, background tasks, AI traces, logs, application metrics, and host metrics
Browser applicationSeparate project per deployed browser appReact, Svelte, Vue.js, or jQueryBrowser errors, web vitals, session replay, distributed-trace linkage, and source-mapped stacks
Mobile applicationSeparate project per independently released appFlutter, React Native, Android, or iOSMobile errors and crashes, replay where supported, and symbolicated stacks
Full-stack JavaScript applicationBackend and browser projectsOpenTelemetry + browser frameworkServer telemetry stays in the backend project; browser telemetry stays in the browser project

Do not send browser or mobile telemetry to the backend project. Those runtimes use different SDKs, build artifacts, and dashboard behavior.

The framework picker offers exactly nine options, and every backend takes the same one:

GroupOptions
BackendOpenTelemetry
BrowserReact, Svelte, Vue.js, jQuery
MobileFlutter, React Native, Android, iOS

There is no Gin, Django, Laravel, or Hono entry, because the language and web framework are chosen later on the project's Connection page, which then shows the exact install and exporter setup. A meta-framework picks the framework it renders with: Next.js and Remix select React, SvelteKit selects Svelte, Nuxt selects Vue.js.

Organizations

Projects live inside an organization, which is the boundary for everything that is not telemetry: members and roles, dashboards, teams, on-call schedules, escalation policies, and status pages. It is also what the organization overview summarizes, putting every server, issue, monitor, and open page across all of the organization's projects one sidebar click apart.

Split by project first. A second organization is right when two groups of projects should share no members, no dashboards, and no on-call rotation, an agency's separate clients for example. Splitting one fleet across organizations costs you the single view of it.

Keep Backend Signals Together

The main backend project should receive all server-side signals:

  • HTTP endpoints and their child spans
  • Queue consumers, scheduled work, and CLI tasks
  • AI and LLM spans
  • Exceptions and OTel logs
  • Application and runtime metrics
  • Host CPU, memory, disk, filesystem, network, and process metrics from the host agent, or from the Kubernetes collectors when the backend runs in a cluster

APIs, workers, schedulers, and the host agent use the same backend project token. Give each process or host a stable service.name so it remains filterable inside the project:

checkout-api
checkout-worker
checkout-scheduler
checkout-prod-host-1

Create separate backend projects only when the services are separate products or require different ownership, access control, compliance, or data isolation. A different deployment process alone is not a reason to split them.

Browser and Mobile Boundaries

Create one project for each independently deployed browser application. Its framework selection drives the browser SDK setup on the Connection page, and its dedicated upload token keeps source maps scoped to that application.

Create one project for each independently released mobile application. A Flutter product that ships to both Android and iOS normally uses one Flutter project. Separate native Android and iOS applications use separate projects and credentials.

A full-stack framework such as Next.js, SvelteKit, or Remix needs two projects only when its server runs meaningful production code:

  • OpenTelemetry project for API routes, server rendering, workers, tasks, AI calls, and server metrics
  • Browser-framework project for code running in the user's browser

For Next.js, the server half is covered by the Next.js OpenTelemetry guide and the browser half by the React SDK. Each half uses its own project token.

A static export with an external API needs only the browser project; the external API belongs to its backend project.

Create the Projects

For each application boundary:

  1. Open app.tracepath.dev (opens in a new tab).
  2. Open the project selector in the header and select Add Project.
  3. Choose the organization.
  4. Enter a name that identifies the product and runtime, such as Acme Backend, Acme Web, or Acme Mobile.
  5. Select the framework:
    • OpenTelemetry for the backend, regardless of language or HTTP framework; it is the only backend option, and the preselected default
    • React, Svelte, Vue.js, or jQuery for a browser project
    • Flutter, React Native, Android, or iOS for a mobile project
  6. Select New Project.
  7. Save the project token and open Go to Connection for the tailored setup. For a backend project, the Connection page asks for your language and web framework there and then shows the matching install commands.

Repeat until every deployed browser app and independently released mobile app has its own project. Do not reuse the backend token for them.

Credentials

CredentialPurposeWhere it belongs
Project tokenAuthenticates OTLP traces, metrics, and logs for that projectDeployment secret, sent as Authorization: Bearer <token>
Upload tokenUploads JavaScript source maps for that projectCI secret; never embed it in the application

A project token is per project, not per service: every process reporting into one project presents the same token and is told apart by its service.name. It is a write-only credential — it can send telemetry and nothing else — but it should still be treated as a secret, because anyone holding it can write into your project and consume your ingest quota.

Generate an upload token from the project's Connection page under Source Maps. Upload tokens are project-specific. Regenerating one invalidates the previous value, so update the corresponding CI secret immediately.

Use component-specific environment variables for runtime credentials so a monorepo cannot accidentally cross-wire projects:

TRACEPATH_BACKEND_TOKEN
TRACEPATH_WEB_UPLOAD_TOKEN

Source maps upload over plain multipart HTTP, so any CI runner with curl can do it — no plugin to install:

curl -fsS -X POST https://app.tracepath.dev/api/sourcemaps/upload \
  -H "Authorization: Bearer $TRACEPATH_WEB_UPLOAD_TOKEN" \
  -F "files=@dist/assets/index-a1b2c3.js" \
  -F "files=@dist/assets/index-a1b2c3.js.map"

Repeat the files=@… field once per file. Only .js, .cjs, .mjs and .map extensions are accepted; anything else in the request is ignored rather than rejected. Each file is capped at 50 MB, and a larger one answers 400. A bad or revoked token answers 401.

Upload tokens never use a public prefix and never ship inside the application. Keep them in the CI secret store, one per project, and scope the secret per job when a repository releases more than one application.

Example Monorepo

For a repository containing a Go API, a Svelte dashboard, one shared worker binary, and a Flutter application, create three projects:

ProjectFrameworkReporters
Acme BackendOpenTelemetryGo API, worker, scheduler, AI model calls, OTel Agent
Acme WebSvelteSvelte browser SDK and source-map upload job
Acme MobileFlutterFlutter SDK and symbol-upload job when release builds are obfuscated

The API and worker use different service.name values but the same backend project token. This keeps an endpoint, its queued task, its AI calls, and the affected server metrics in the same project.

Next Steps