Anatomy of a project
A LeCodes project is plain TypeScript — but a few rules differ from a regular codebase, and every page of this guide assumes them. Five minutes here saves confusion everywhere else.
Everything is a global — no imports
The whole SDK surface (Scene, Sprite, UIScreen, Vec3, fetch, …) is available in every file without importing anything. The build injects the implementation of what you use and strips what you don't, so the globals cost nothing.
The only import statements a project may contain are relative paths — to its own files and assets:
import { hud } from './ui/hud' // ✓ your own module
import hero from './hero.png' // ✓ an asset — resolves to its bundled URL
import _ from 'lodash' // ✗ build error: no package importsThere is no npm here by design: the runtime on the device is not Node and not a browser, and the compiler needs to see all the code to shake it down to kilobytes.
The entry point
The file with no exports is the entry point. A small project is often just one file; in a multi-file project the entry wires the other modules together and starts the app — for a UI app that's Router.init(home) or screen.open(), for a game scene.open().
Assets
Files in your project (images, models, sounds, fonts) are referenced two ways — an import, or the inline asset() macro:
import hero from './hero.png' // same thing, two spellings
const tex = await Texture2D.load(asset('./hero.png'))asset() is a compile-time macro: the bundler rewrites it into the resource reference, so the path must be a string literal — asset(someVariable) is a build error. Remote https://… URLs don't need it; pass them as plain strings.
Time: the frame loop and timers
setLoop(dt => { // fires every rendered frame
player.x += 120 * dt // dt is SECONDS since the last frame (~0.016 at 60 fps)
})
setTimeout(() => {}, 500) // timers take MILLISECONDS, like the webOne convention to internalize early: setLoop's dt is seconds — scale movement by it and your app runs the same at any frame rate. Timers and animation durations (animate, UI .animateTo()) are milliseconds.
And its companion rule: a loop runs until cleared. Whatever a screen starts in onOpen, it must stop in onClose — see lifecycle.
What the compiler does
When you hit run, the compiler packs the project into a single portable app.js: it injects the SDK, resolves assets, inlines vector math, and tree-shakes aggressively — down to unused methods of classes. That bundle is what every platform executes, with rendering, layout and physics running as native engine code — no WebView anywhere. If you're curious how the pieces fit, see Architecture.
The practical consequence: an app ships as megabytes, not tens of megabytes, and behaves the same in the browser preview, on iOS, Android, Windows, macOS and Linux.
Where to look things up
- Conventions — units, coordinate systems, colors, value semantics: the rules every API page assumes.
- Host globals —
setLoop, timers,asset(),console. - The rest of the API Reference — every global, with signatures and units.
What's next
Pick a track from the overview and start building.