Guidance for AI coding agents working in the LiveCodes repository.
LiveCodes is a code playground that works in the browser. It's a TypeScript/JavaScript project that uses esbuild for bundling.
- skills/ — Intent skills for LiveCodes SDK. Start with .agents/skills/livecodes/SKILL.md for an overview and decision tree linking to all sub-skills.
- docs/docs/contribution/ — Internal architecture and system documentation for contributors (build system, compiler, config, editor, etc.)
- llms-full.txt (livecodes.io/docs/llms-full.txt) — Generated list of all LiveCodes features and their descriptions.
npm run build # Full production build (app + docs + storybook)
npm run build:app # Build app only
npm run start # Dev server with watch (http://127.0.0.1:8080)
npm run docs # Start documentation server (http://localhost:3000/docs)
npm run storybook # Start storybook (http://localhost:6006)
npm run test # Run everything (typecheck + lint + unit tests)
npm run test:unit # All Jest unit tests
npm run test:unit -- --testPathPattern="utils.spec" # Single test file by path pattern
npm run test:unit -- --testNamePattern="debounce" # Single test by name
npm run test:unit -- src/livecodes/config/__tests__/build-config.spec.ts # Exact file
npm run e2e # Playwright end-to-end tests
npm run typecheck:app # TypeScript type check (tsc --noEmit)
npm run lint:eslint # ESLint check
npm run lint:prettier # Prettier format check
npm run lint:stylelint # Check styles with Stylelint
npm run fix # Auto-fix all (prettier + eslint + stylelint)
npm run fix:prettier # Auto-fix formatting only
npm run fix:eslint # Auto-fix lint only
npm run fix:stylelint # Auto-fix stylelint onlysrc/
livecodes/ # Top-level directory for the LiveCodes app
core.ts # Main application logic
models.ts # Central type definitions. Can import/re-export from `sdk/models.ts`.
vendors.ts # CDN URLs for third-party assets
config/ # Configuration (build, default, validate, upgrade)
compiler/ # Compilation pipeline
editor/ # Code editor integration (Monaco, CodeMirror, CodeJar)
languages/ # Language specs (~90 languages)
i18n/ # Internationalization (17+ locales)
UI/ # User interface controllers
html/ # User interface views
styles/ # User interface styles
utils/ # Shared utility functions
storage/ # IndexedDB/localStorage persistence
services/ # Backend services (auth, GitHub, share, CDN)
events/ # Event system (pub/sub, custom events)
notifications/ # Notification system
toolspane/ # Bottom panel (console, compiled code, tests)
result/ # Result page rendering
templates/ # Starter templates
types/ # Providing types for code editors
export/ import/ deploy/ sync/ ...
sdk/ # SDK for embedding LiveCodes (npm/jsr package). Avoid build-time dependencies.
index.ts # SDK entry point
models.ts # SDK type definitions. Should not import from any other modules.
internal/ # Internal utilities. Should not be exported by SDK.
preact.ts react.tsx solid.ts svelte.ts vue.ts web-components.ts # Framework wrappers.
Each feature directory typically contains: index.ts (barrel), models.ts (local types),
__tests__/*.spec.ts (co-located tests), and implementation files.
- Semicolons: always
- Single quotes
- Trailing commas: all (objects, arrays, function params)
- Print width: 100
- Imports auto-sorted by
prettier-plugin-organize-imports
Use import type for type-only imports (enforced by eslint):
import type { Config, Language } from '../models';
import { someFunction } from '../utils';Inline type keyword when mixing value and type imports from the same module:
import { createStores, type Stores } from './storage';Type-only re-exports in barrel files:
export type * from '../sdk/models';
export type { ProjectStorage } from './models';Import ordering is automatic (external packages first, then internal/relative).
Never import from **/_modules (restricted by eslint).
- Files/directories: kebab-case (
build-config.ts,import-map.ts) - Functions/variables: camelCase (
createEventsManager,getLanguageTitle) - Types/interfaces: PascalCase (
CompileResult,LanguageSpecs,EditorOptions) - No enums: use string union types instead (
type ParserName = 'babel' | 'html' | ...) - Test files:
<feature>.spec.tsinside__tests__/directories - Avoid underscore-prefixed names (
no-underscore-dangleenforced)
- Arrow function constants are the dominant style (not
functiondeclarations) - Named exports only -- no default exports (except i18n locale files)
- No classes in application code -- use factory functions returning plain objects
(
createEventsManager(),createNotifications(),createToolsPane()) - One variable declaration per statement (
one-var: never) - Use
prefer-constandno-var - Use concise arrow bodies where possible (
arrow-body-styleenforced) - Use object shorthand (
object-shorthandenforced)
Mark exported pure utility functions for tree-shaking:
export const debounce = /* @__PURE__ */ (fn: (...x: any[]) => any, delay: number) => {
// ...
};Use on side-effect-free functions in utility modules. Not needed on factory functions that create mutable state or functions with DOM/network side effects.
interfacefor object shapes;typefor unions, mapped types, and function signatures- Explicit class member accessibility required (
public,private,protected) - Array types:
T[]for simple,Array<T>for complex types anyis permitted (no-explicit-anyis off)- Use
for...ofover indexedforloops when index is not needed - Use
as const satisfiesfor typed constant objects - Strict mode with
noUnusedLocals,noUnusedParameters,noImplicitReturns
- Must throw
Errorobjects, not literals (no-throw-literalenforced) - Use
getErrorMessage(err)utility fromutils/for safe error message extraction - Silent catch blocks are acceptable for expected failures:
catch { return ''; } - Empty catch blocks use a
//comment:catch { // } no-consoleis enforced -- use// eslint-disable-next-line no-consolewhen needed- Fetch errors: use
handleFetchError(res)which rejects on non-ok responses
import { debounce, encodeHTML } from '..'; // import from barrel file
describe('utils', () => {
test('debounce', async () => {
// arrange, act
expect(num).toBe(1);
});
test('encodeHTML', () => {
expect(encodeHTML('<div>')).toBe('<div>');
});
});- Use
describe/test(notit) - Tests are co-located in
__tests__/dirs next to source - Import from barrel files (parent
index.ts) when available // @ts-nocheckis acceptable at top of test files for partial type testing- Never commit
.onlyon tests (no-only-testsenforced)
Follow Conventional Commits:
feat:, fix:, docs:, refactor:, test:, chore:, etc.
Branch from develop (not main) for feature work.
- Smart equality: use
===/!==(eqeqeq: smart) - Curly braces required for multi-line blocks only (
curly: multi-line) - Guard
for...inwithhasOwnPropertycheck (guard-for-in) - No bitwise operators (
no-bitwise) - No
eval(no-eval) - Max one class per file
- JSDoc alignment/indentation enforced when present (not required on all functions)
- Text strings are exported for internationalization. Run
npm run i18n-exportafter adding new user-facing text. See./docs/docs/contribution/i18n.mdxfor details.