ippclub/dora-ssr/dora-engine-coding

Claude Code and agent skill by ippclub/dora-ssr

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Dora SSR coding rules for game/workspace projects; prevents browser DOM/Canvas/Node.js code in Dora engine scripts and forces Dora API lookup before using unfamiliar engine APIs.

Install

npx vskill@latest install ippclub/dora-ssr/dora-engine-coding

SKILL.md

Dora Engine Coding Rules

These rules apply whenever writing, fixing or reviewing code for a Dora SSR workspace/game project.

What Runtime This Is

  • Dora runtime game code is executed by the Dora engine, not by a browser or Node.js.
  • The normal runtime entry is the project-root init.ts or init.lua.
  • TypeScript/TSX is source code and is transpiled to Lua. The engine executes the Lua output.
  • Prefer editing .ts/.tsx source files. Do not hand-edit generated .lua unless the task is specifically about Lua output or the project is Lua-only.
  • If a project contains web files (index.html, DOM Canvas code, etc.) and also has init.ts, treat init.ts as the Dora runtime entry unless the user explicitly asks for a browser/Web IDE frontend.

Runtime vs Browser Decision

Before writing code, decide the target:

  1. Dora game/runtime script: use Dora engine APIs and this skill.
  2. Web IDE/frontend page: browser APIs may be valid, but only if the user explicitly asks for Web IDE/frontend/browser work.

For Dora runtime scripts, never generate:

  • document, window, HTMLElement, HTMLCanvasElement, CanvasRenderingContext2D
  • requestAnimationFrame, browser alert, DOM event listeners
  • setInterval, setTimeout, NodeJS.Timeout
  • npm-only packages, Node fs/path/process
  • HTML index.html as the runtime game entry

If those APIs already exist in a Dora runtime project, treat them as incompatible code to rewrite.

Hard Rule: Do Not Guess Dora APIs

Dora has its own TypeScript definitions such as Dora.d.ts. Do not invent names/signatures.

Lookup protocol

Call search_dora_doc before using any Dora API that is not shown in the baseline section below or not already used correctly in the project.

For implementation tasks, keep lookup bounded so it does not replace implementation:

  • When the runtime reports a fresh project, start from the disclosed short code file or create the requested entry directly (default to init.ts for a Dora TypeScript task). Consult relevant tutorials or APIs when they help, and prefer an early build so subsequent work can use compiler feedback.
  • If the requested game fits the baseline APIs below, do not search first. Inspect the entry, implement the smallest complete playable loop, then build.
  • Before the first edit, use at most one batched search_dora_doc call for all genuinely unfamiliar APIs. Do not issue separate searches for APIs already covered by the baseline.
  • After that lookup, edit and build. Search again only for a concrete compiler or runtime error that cannot be resolved from the returned signature.
  • Do not use runtime command tools for project discovery, file inspection, or API/type-definition lookup. Use the corresponding file/search tools.
  • Prefer build diagnostics over speculative design research. Do not spend repeated Agent steps comparing optional architectures before a playable baseline exists.
  • After editing source, build before another search_dora_doc call. A later search is justified only by a concrete build/runtime diagnostic that requires an unfamiliar API.

Use:

  • programmingLanguage: "ts" for .ts files.
  • programmingLanguage: "tsx" for DoraX/JSX files.
  • docType: "dora-api" for signatures/types.
  • docType: "dora-tutorial" for usage examples when signatures alone are not enough.
  • docLanguage: "zh" if the user is Chinese or Chinese docs are preferred; otherwise "en".

After searching:

  1. Read the returned signature/JSDoc carefully.
  2. Use the exact module name, export name, parameter order, return type, and enum value.
  3. If the result is incomplete, search narrower terms or read the referenced .d.ts/tutorial file.
  4. If search fails, say the API was not found and implement a simpler baseline Dora version instead of guessing.

Search especially for:

  • physics/collision: PhysicsWorld, Body, BodyDef, FixtureDef, Sensor
  • ECS: Entity, Group, Observer, component queries
  • UI/components/layout: Button, Menu, AlignNode, UI controls
  • audio: Audio, AudioSource, buses/effects
  • async/coroutines: thread, threadLoop, sleep, once, loop, scheduler jobs
  • scene/camera: Director, Camera, Director.ui, Director.entry, scheduler APIs
  • resources/files: Content, Cache, Path, asset loading/saving
  • sprite/animation/actions: Sprite, Model, Playable, Action, Move, Scale, Sequence, animation slots
  • particles/effects/video: Particle, EffekNode, VideoNode, TIC80Node
  • tile maps: TileNode
  • Platformer helpers: Platformer, PlatformWorld, platformer bodies/units
  • vector graphics/custom rendering: DrawNode, VGNode, nvg
  • input beyond simple keyboard: Mouse, touch, controller, IME, node slots

Example tool searches:

text
search_dora_doc pattern="PhysicsWorld|Body|FixtureDef" docType="dora-api" programmingLanguage="ts" limit=8
search_dora_doc pattern="Button|Menu|AlignNode" docType="dora-api" programmingLanguage="ts" limit=8
search_dora_doc pattern="AudioSource|Audio" docType="dora-api" programmingLanguage="ts" limit=8
search_dora_doc pattern="thread|sleep|threadLoop" docType="dora-api" programmingLanguage="ts" limit=8

Module Import Rules

Use Dora runtime modules, not browser packages:

  • Core engine APIs: import { ... } from 'Dora';
  • JSX/DoraX UI syntax: use .tsx and import from DoraX. Use toNode() for one-shot scene creation, or createRoot() with signal() for dynamic TSX diff rendering.
  • DoraX dynamic roots track the signals read during render. Use stable key values for dynamic sibling lists, and call root.unmount() when a dynamic root is no longer needed.
  • Platformer framework: import * as Platformer from 'Platformer'; or exact exports found by API search.
  • ImGui tools/UI: import * as ImGui from 'ImGui'; plus enum exports from ImGui when needed.
  • Vector graphics: import * as nvg from 'nvg'; when using VGNode/NanoVG APIs.
  • Do not import React from npm for DoraX runtime code.

TypeScript Hygiene

  • Do not use any in Dora runtime TypeScript. Use concrete types, unknown with narrowing, generics, or exact unions/records.
  • Do not use bare null in runtime code. Use undefined/omitted fields for absent Lua values.
  • In edit_file content, indent with ordinary space characters. Never emit the two literal characters \\t at the beginning of a source line; they are not indentation and will make TypeScript parsing fail.
  • Dora factory namespaces are values, not annotation types. Annotate instances with Vec2.Type, Color.Type, Label.Type, DrawNode.Type, and the corresponding X.Type; do not use bare X or ReturnType<typeof X>.
  • The Dora TypeScript-to-Lua subset does not support Math.hypot or Math.imul. Use Math.sqrt(x*x + y*y) and ordinary bounded arithmetic.
  • Lua arrays cannot represent undefined/null elements. Do not build arrays from optional factory results such as Label(...); narrow each optional result before inserting it, or handle the labels individually.

Coordinate System

  • Dora uses a left-handed coordinate system, positive X is right and positive Y is up.
  • Director.entry, Director.ui, and similar root nodes use screen-center origin: (0, 0) is the screen center.
  • Do not use browser-style top-left coordinates unless explicitly converting from that space.
  • For game screen adaptation, read ts/adapting-to-screen.md directly before designing responsive layout behavior.
Parent and child local coordinates
  • For a parent node with nonzero width and height, anchor selects which point of the parent's own rectangle is placed at the parent's position. It does not move the local origin used by the parent's children.
  • A child is positioned in the parent's rectangular local space, whose (0, 0) is the rectangle's bottom-left corner. Even with the default anchor = Vec2(0.5, 0.5), a child at Vec2.zero is at that bottom-left corner, not at the parent's center.
  • To center a child in the parent rectangle, place it at Vec2(parent.width / 2, parent.height / 2).
  • To align a child with the parent's anchor point, place it at Vec2(parent.width * parent.anchor.x, parent.height * parent.anchor.y).

Keep a full-screen drawing root unsized when its children should use screen-center coordinates:

ts
const screen = Node();
screen.addTo(Director.entry); // unsized: child (0, 0) remains the screen center
const background = DrawNode();
const {width, height} = View.size;
background.drawPolygon([
Vec2(-width / 2, -height / 2),
Vec2(width / 2, -height / 2),
Vec2(width / 2, height / 2),
Vec2(-width / 2, height / 2),
], Color(20, 30, 50, 255));
background.addTo(screen);

For a sized parent, position children in its bottom-left-based local rectangle:

ts
panel.size = Size(320, 180);
panel.position = Vec2.zero; // the panel's anchor point is at screen center
label.position = Vec2(panel.width / 2, panel.height / 2); // center inside panel

Inside that sized node's touch handler, touch.location uses the same bottom-left-based local space. Convert it before comparing against centered model coordinates:

ts
const local = touch.location;
const centered = Vec2(
local.x - panel.width * panel.anchor.x,
local.y - panel.height * panel.anchor.y
);

Do not give a full-screen drawing root a size merely for adaptation. Add a separate sized input node when a real hit area is required, and deliberately use or convert its local coordinates as shown above.

Input coordinate and enum baseline

These names come directly from the built-in Dora.d.ts; do not spend a search step rediscovering them:

  • touch.location: position in the receiving node's local coordinate system.
  • touch.viewLocation: position in the current view's logical coordinate system.
  • touch.worldLocation: position in world coordinates. Prefer node-local handlers with touchEnabled = true and the node's real size over global manual hit testing.
  • The return key is KeyName.Return, not KeyName.Enter. Number keys are KeyName.Num0 through KeyName.Num9; letters and arrows use names such as KeyName.W, KeyName.Left, and KeyName.Up.
  • Controller buttons use ButtonName.A/B/X/Y, Back, Start, Up/Down/Left/Right, LeftShoulder/RightShoulder, and LeftStick/RightStick. Axes use AxisName.LeftX/LeftY/RightX/RightY/LeftTrigger/RightTrigger.
  • Controller calls are Controller.isButtonDown/Up/Pressed(controllerId, ButtonName.X) and Controller.getAxis(controllerId, AxisName.LeftX).
  • For a centered playfield of width w and height h, every model-space object and configured region must initially lie within [-w/2,w/2] × [-h/2,h/2]. With Dora's positive-Y-up convention, a bottom paddle has negative Y, bricks near the top have positive Y below h/2, launch-up velocity is positive Y, and falling velocity is negative Y. Check these signs and bounds before the first build.

Scheduling Semantics

  • A Dora Node has one schedule slot. Calling node.schedule(...) again replaces that node's previous scheduled callback; it does not add another concurrent callback.
  • Put update and render work in one scheduled callback, or attach independent callbacks to distinct child nodes.
  • Runtime probes must never add another schedule to the node whose game loop is being tested. Observe state from the existing callback or use a separate probe node, then remove the probe after validation.

Baseline Dora APIs for Simple 2D Prototypes

For a tiny runtime prototype, this baseline is allowed without extra API search:

ts
// @preview-file on clear
import { Color, Director, DrawNode, KeyName, Keyboard, Label, Node, Vec2, View } from 'Dora';
const root = Node();
root.addTo(Director.entry);
const draw = DrawNode();
draw.addTo(root);
const title = Label('sarasa-mono-sc-regular', 20);
if (title) {
title.text = 'Dora Game';
title.y = View.size.height / 2 - 40;
title.addTo(root);
}

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
512
Repository forks
72
7-day trend score
31

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 27 Aug 2026, 2 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/ippclub/dora-ssr/dora-engine-coding/badge)](https://verified-skill.com/skills/ippclub/dora-ssr/dora-engine-coding)

Something wrong with this skill or its page? Tell us.