Local Development
Develop and test TelemetryOS applications locally before deployment using the TelemetryOS CLI development server.
Local Development
Develop and test TelemetryOS applications locally before deployment.
Overview
The TelemetryOS Developer App provides a local development environment that simulates the platform, enabling application building and testing without cloud deployment. Download the Developer App from Studio — it includes the tos CLI.
CLI Commands
tos init
Scaffold a new application from a template.
tos init my-applicationThis command creates a project directory with a Vite + React + TypeScript template, generates a telemetry.config.json manifest, installs dependencies, and initializes a git repository. The result is a ready-to-run project that you can immediately open with tos dev.
Options:
--template <name>- Use specific template (default: vite-react-typescript)
tos dev
Open a project in the Developer App.
tos devtos serve is an alias for tos dev.
This reads your telemetry.config.json, starts the dev server defined in devServer.runCommand, and opens the project in the Developer App. The Developer App wraps your application in a simulated TelemetryOS environment so that all SDK calls work locally against mock data.
Configuration in telemetry.config.json:
{
"devServer": {
"runCommand": "vite --port $PORT",
"url": "http://localhost:$PORT",
"readyPattern": "VITE.*ready in"
}
}The $PORT variable is replaced at runtime with an available port, avoiding conflicts when multiple projects are open. The readyPattern is a regex matched against stdout to detect when the server is ready.
tos auth
Authenticate the CLI with your TelemetryOS account. This is required before you can use tos publish.
tos authWhen run without flags, the command launches an interactive prompt that asks you to paste your API token. To obtain a token, open TelemetryOS Studio and navigate to Settings > API Tokens. Tokens follow the format u followed by 32 hexadecimal characters (for example, u1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6). The CLI validates the token format before saving.
Your token is stored at ~/.config/telemetryos/cli/config.json (or under $XDG_CONFIG_HOME if set). If a token already exists, the CLI asks for confirmation before replacing it.
Options:
-t, --token <string>- Provide the API token directly, skipping the interactive prompt-f, --force- Replace an existing token without confirmation
tos publish
Publish an application to TelemetryOS from the command line. This is an alternative to uploading archives through Studio or connecting a GitHub repository.
tos publishThe command archives your project directory as a .tar.gz file (respecting .gitignore rules to exclude unnecessary files), uploads the archive to the TelemetryOS API, and then polls the platform for build status while streaming build logs to your terminal. If an application with the same name already exists, the CLI uploads a new build to it; otherwise it creates a new application automatically.
You must run tos auth before publishing. The application name is read from telemetry.config.json if present, or prompted interactively.
Options:
[project-path]- Path to the project directory (defaults to current working directory)-i, --interactive- Interactively prompt for all build configuration fields--name <name>- Application name (overridestelemetry.config.json)--base-image <image>- Docker base image for the build container (default:node:20)--build-script <script>- Build commands to run inside the container (default:npm installfollowed bynpm run build)--build-output <path>- Directory containing build output (default:/dist)--working-path <path>- Working directory inside the container (default:/)
Build configuration options (--base-image, --build-script, --build-output, --working-path) only apply when creating a new application. For existing applications, these options are ignored and the CLI prints a warning.
Development Workflow
Creating Applications
tos init weather-widget
cd weather-widgetInstalling Dependencies
npm installStarting Development
tos devOr use npm script:
npm run devAccessing Mount Points
Configured mount points are available at:
- Settings: http://localhost:3000/settings
- Render: http://localhost:3000/render
Making Changes
Files in the src/ directory support hot module replacement (HMR), which reloads changes automatically.
Developer App
The Developer App provides a simulated TelemetryOS environment for testing applications. It renders a canvas that simulates the device screen with adjustable aspect ratios and backgrounds, a settings panel that mirrors the admin sidebar, and a Web tab for web mount points. Under the hood, an SDK bridge intercepts all SDK calls and returns mock responses, while file-based storage provides persistent simulation so that your application state survives restarts.
Using the Developer App
tos devYour application's render mount point appears on the canvas, the settings mount point in the sidebar, and toolbar controls let you adjust aspect ratio, background, color scheme, and more. If your project has a web mount point, it appears as a separate tab. For a complete guide to the Developer App's visual tools, see Developer App.
Mock SDK Behavior
During local development, all SDK methods return mock data so you can build and test without a live platform connection. Storage calls use localStorage under the hood, meaning values persist across page reloads and subscriptions fire via storage events. Media methods return sample MediaContent objects. Playlist and override operations succeed immediately but do not affect actual playback. Account and user methods return placeholder data with mock identifiers.
Storage
// Works locally using localStorage
await store().instance.set('key', 'value');
const value = await store().instance.get('key');
// Subscriptions work with localStorage events
store().instance.subscribe('key', (value) => {
console.log('Value changed:', value);
});Media
// Returns sample media data
const media = await media().getAllByTag('featured');
// media contains mock MediaContent objectsPlaylist & Overrides
// Operations succeed but don't affect actual playback
await playlist().nextPage(); // Returns true
await overrides().setOverride('alert'); // Returns trueAccounts & Users
// Returns mock account and user data
const account = await accounts().getCurrent();
// account = { id: 'mock-account-id' }Troubleshooting
SDK Not Configured Error
Error: SDK is not configured
Fix: Call configure() before using SDK methods:
import { configure } from '@telemetryos/sdk';
configure();Mount Point Not Loading
Error: 404 or blank page
Fix: Check routing in App.tsx:
const path = window.location.pathname;
if (path === '/settings') return <Settings />;
if (path === '/render') return <Render />;Hot Reload Not Working
Issue: Changes don't appear automatically
If hot reload stops working, try restarting the dev server with tos dev. If the problem persists, check your Vite config for HMR settings, clear the browser cache, and look for TypeScript compilation errors that may be blocking the rebuild.
Storage Not Persisting
Issue: Data clears on refresh
Cause: Using wrong storage scope
Fix: Use instance or application scope:
// ✅ Persists across reloads
await store().instance.set('key', 'value');
// ❌ May not persist in dev environment
await store().device.set('key', 'value');Testing Patterns
Manual Testing
To test the settings mount point, navigate to /settings, configure your application settings, save them to storage, and verify that the UI updates accordingly. For the render mount point, navigate to /render, confirm that it subscribes to the settings you saved, check that the display updates when settings change, and exercise all display states (loading, error, empty, populated).
Browser DevTools
Use Chrome or Firefox DevTools for debugging:
Console:
// Access SDK directly in console
telemetry.store().instance.get('key')
telemetry.playlist().nextPage()In the Application tab you can view localStorage contents (which back the storage simulation), inspect session storage, and check service workers. The Network tab is useful for monitoring external API calls, checking proxy requests, and verifying resource loading.
React DevTools
Install the React DevTools browser extension to inspect the component tree, view props and state, profile rendering performance, and debug hooks.
Building for Production
Build Command
npm run buildCreates production files in dist/ directory.
Build Output
dist/
├── index.html
├── assets/
│ ├── index-abc123.js
│ └── index-def456.css
└── telemetry.config.json
Important: telemetry.config.json must be in build output.
Verify Build
Check that build contains:
- ✅ All HTML files
- ✅ All assets (JS, CSS, images)
- ✅ telemetry.config.json at root
- ✅ Correct mount point paths
Best Practices
Always test locally with tos dev before committing, and make sure to exercise both the settings and render mount points together since they typically depend on each other. Use TypeScript to catch errors at compile time rather than at runtime, and test on your target display resolution using the responsive mode in DevTools.
Keep your changes under version control:
# Commit working changes
git add .
git commit -m "Add weather display feature"
git push origin mainFor sensitive configuration such as API keys, use environment variables rather than hard-coding values:
// vite supports import.meta.env
const API_KEY = import.meta.env.VITE_API_KEY;.env.local:
VITE_API_KEY=your-api-key-here
Be thorough with scenario coverage: test with no configuration set, test error and loading states, and try different data combinations to make sure the application handles edge cases gracefully.
// Monitor performance
console.time('data-fetch');
const data = await fetchData();
console.timeEnd('data-fetch');Next Steps
- Defining Your Application - Register your application in TelemetryOS Studio for deployment
- Quick Start - Create your first application end-to-end
- Configuration - Configure telemetry.config.json
- Code Examples - See complete application implementations
Updated 11 minutes ago