Dora Start!On this pageDora Start! 1. What is Dora SSR? A Short IntroductionDora SSR is a game engine for rapid development of games on various devices. It has a built-in easy-to-use Web IDE development tool chain that supports direct game development on mobile phones, open source handhelds and other devices. 2. Installation AndroidWindowsmacOSLinux Download and install the APK package on the game's running terminal. Download APK▼ Run the software. If Mobile UI is shown, tap Classic UI at the top left of the Feed. Access the server address shown in the traditional UI from a browser on your PC (tablet or other development device) in the LAN. Start game development. Download and install the latest supported X86 Visual C++ v14 Redistributable for Visual Studio 2017-2026 (the MSVC runtime package vc_redist.x86) to run this application. You can download it from here (more details see Microsoft website). Download and run the software. Download Software▼ Access the server address displayed by the software through a browser. Start game development. Download and run the software. Download Software▼ Or you can install with Homebrew using: brew install --cask ippclub/tap/dora-ssr Subsequent updates can be performed using the following commands: brew updatebrew upgrade dora-ssr# or try to update the revision of the same version by reinstallingbrew reinstall dora-ssr When you first run the software, you may see a prompt saying "Dora cannot be opened". Please go to "System Preferences" > "Security & Privacy" and click "Open Anyway". Access the server address displayed by the software through a browser. Start game development. Installation. Ubuntu sudo add-apt-repository ppa:ippclub/dora-ssrsudo apt updatesudo apt install dora-ssr Debian Bookworm sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 9C7705BFsudo add-apt-repository -S "deb https://ppa.launchpadcontent.net/ippclub/dora-ssr/ubuntu jammy main"sudo apt updatesudo apt install dora-ssr Run the software and access the server address displayed by the software through a browser. Start game development. Switch between Mobile and traditional UI Both interfaces are available on Android, iOS, Windows, macOS, and Linux. On first launch, Android/iOS default to Mobile UI and desktop platforms default to the traditional UI. Your selection is remembered in the application's settings on the current device, including when you change workspaces. In the traditional home screen, select Mobile UI at the top to browse the game Feed. Connecting Web IDE takes priority over both local UI modes. When no game is running, the engine shows the same fixed Web IDE connected screen, with no mode switch. Local Feed, Remix and playtesting controls are suspended, including text input. Web IDE can still run and stop games normally. After the last Web IDE connection closes, the previous local UI returns without changing your saved preference; if a remote run replaced the scene, Mobile returns to its Feed when the game stops. In the Mobile Feed, select Classic UI at the top left to return to the traditional project/tool list and Web IDE connection information. Switching takes effect without restarting the application or Web service. It does not change the workspace, projects, or model configuration. Return from Remix or exit playtesting before switching. During installation, wait for the operation to finish; the switch is temporarily disabled. Mobile UI adapts to the current window or device orientation; selecting it on a desktop does not force a portrait window. Mobile UI always uses the larger text size; there is no font-size toggle. The Feed opens Local when runnable local projects exist, otherwise Discover. Returning from Remix or playtesting restores that project's card and its original tab, even when the list has been reordered or the Catalog refreshes. If the original Catalog entry is no longer available, its installed local project is used when present. Create a project from Mobile Feed Open Local and select + New at the top. Enter one folder name in the bottom sheet, then select Create and Remix. Mobile creates a runnable TypeScript project with init.ts and its initial runnable output in the current workspace, refreshes Local, selects the new project, and opens its Remix conversation. The entry remains available when Local is empty. If the name is empty, contains a path separator, or conflicts with an existing file or folder ignoring letter case, the sheet stays open so you can change it. A folder or init.ts write failure also leaves a retryable message; an incomplete folder created by that attempt is rolled back without removing existing content. Select Cancel or use the system Back action to return to the Feed without creating anything. Project names use a single-line input with horizontal scrolling. It shares its input component with the multiline Remix prompt: the border turns gold when focused and gray when focus is lost. Following Remix progress Use Back at the top right, or swipe left across the conversation area, to return to the Feed. The whole Remix page follows your drag with the same resistance as Feed cards; releasing a short swipe springs it back, while a completed swipe switches directly to the Feed without an extra slide-out animation. Input editing, buttons, and vertical scrolling do not trigger this gesture. The existing safety rule still applies: stop a running Agent before leaving Remix. The multiline input shows a blinking caret while focused and hides its placeholder. Tap to position the caret, use arrow keys to move, and press Enter for a new line; Ctrl/Cmd+Enter sends. Long text wraps and scrolls inside the input without covering other controls. You can scroll within it with a drag or mouse wheel; editing brings the caret back into view. Tap outside the input or press Esc to dismiss the keyboard and caret without losing your committed draft. An empty input shows its placeholder again; tap it to resume editing. Backgrounding the app or connecting the Web IDE also releases input focus. If a tap cancels unfinished IME composition, it does not send the draft at the same time. Use Plan or Code above the input to manually select the Agent's working mode, just as in Web IDE. New sessions default to Code; existing sessions keep their saved mode, shared with Web IDE. The setting belongs to each project's main session and survives app restarts; having plan files does not enable Plan mode. Sending or reopening Remix does not reset the mode. Switching modes preserves your draft and does not send a request; there is no mandatory Plan → Start Remix sequence. Mode switching and sending are disabled while a task is running, awaiting an answer, or finalizing. Remix shows conversation history and compact work cards in a scrollable area between the fixed header and input controls. Card text and status update while the Agent works. When you are at the bottom, new content stays in view; if you scroll up to read earlier messages, your reading position is preserved. Select New activity · Latest to resume following the latest content. The lightweight view loads only the latest 10 conversation rounds, including the current round. A round starts with your request and includes its replies, rather than being a single message. Only the current task shows work cards; earlier rounds show requests and replies. When older rounds are omitted, a notice at the top directs you to Web IDE. There is no “load more” action in Remix. This display limit does not delete history or change the Agent’s context strategy. The button beside the input switches between Send when idle and Stop while the Agent is working. It stays disabled while stopping or finalizing, then returns to Send; stopping preserves your next draft. Local Agent run/stop checks keep the Remix conversation and input available. Completed Code work stays visible with Play now; after a Plan reply, you can continue discussing or manually switch to Code. Web IDE still takes control when connected; open the same project’s Dora tab there to see its shared conversation and detailed execution results. 3. Write the Game Step One: Create a new project In the browser, right click on the menu "Workspace" of the resource tree on the left side of the Dora Dora editor. Click the New menu item, select "New Folder", and name it Hello. If you are trying to use Wa language to develop games, you can skip the step of creating the project folder and create a new game project in Wa language named Hello, by selecting the Wa language in the new file dialog and then checking the "create as Wa project" option. Step Two: Write the game code Create a new game entry code file in the project folder, select the Lua language (or Teal, TypeScript, YueScript), and name it init. If you are using the Wa language project, you can just reuse the main.wa file as the game entry code file. If you are developing a Wa project outside the Web IDE, first start Dora SSR and its Web IDE, then use the built-in Dora CLI mode to create, build, and run it directly. Replace Dora with the path to your Dora executable if needed. Dora cli wa init hello_dora --host <web_ide_host>cd hello_doraDora cli wa run --host <web_ide_host> Write the code: LuaTealTypeScriptTSXYueScriptWaHello/init.lua-- import moduleslocal Sprite <const> = require("Sprite")local Node <const> = require("Node")local Move <const> = require("Move")local Ease <const> = require("Ease")-- create the root node of the game scene treelocal root = Node()-- create a spritelocal sprite = Sprite("Image/logo.png")-- mount the sprite to the root nodesprite:addTo(root)-- register for click events to move the spriteroot:onTapBegan(function(touch) sprite:perform( Move( 1, -- duration in seconds sprite.position, -- start position touch.location, -- end position Ease.OutBack -- easing function ) )end)Hello/init.tl-- import moduleslocal Sprite <const> = require("Sprite")local Node <const> = require("Node")local Move <const> = require("Move")local Ease <const> = require("Ease")local type Touch = require("Touch")-- create the root node of the game scene treelocal root = Node()-- create a spritelocal sprite = Sprite("Image/logo.png")if not sprite is nil then -- mount the sprite to the root node root:addChild(sprite) -- register for click events to move the sprite root:onTapBegan(function(touch: Touch.Type) sprite:perform( Move( 1, -- duration in seconds sprite.position, -- start position touch.location, -- end position Ease.OutBack -- easing function ) ) end)endHello/init.ts// import modulesimport {Ease, Move, Node, Slot, Sprite} from 'Dora';// create the root node of the game scene treeconst root = Node();// create a spriteconst sprite = Sprite("Image/logo.png");if (sprite) { // mount the sprite to the root node root.addChild(sprite); // register for click events to move the sprite root.onTapBegan(touch => { sprite.perform( Move( 1, // duration in seconds sprite.position, // start position touch.location, // end position Ease.OutBack // easing function ) ); });}Hello/init.tsx// @preview-file onimport {React, toNode, toAction, useRef} from 'DoraX';import {Ease, Sprite, Touch} from 'Dora';const sprite = useRef<Sprite.Type>();// define the touch event handlerconst onTapBegan = (touch: Touch.Type) => { const {current} = sprite; if (current) { const {x, y} = touch.location; current.perform(toAction( <move time={1} startX={current.x} startY={current.y} stopX={x} stopY={y} easing={Ease.OutBack} /> )); }};// create the root node of the game scene tree// and a sprite as a child nodetoNode( <node onTapBegan={onTapBegan}> <sprite ref={sprite} file='Image/logo.png'/> </node>);Hello/init.yue-- import modules_ENV = Dora-- create a spritesprite = Sprite "Image/logo.png"-- create the root node of the game scene treewith Node! -- mount the sprite to the root node \addChild sprite -- receive and process click events to move the sprite \onTapBegan (touch) -> sprite\perform Move( 1 -- duration in seconds sprite.position -- start position touch.location -- end position Ease.OutBack -- easing function )Hello/main.wa// import moduleimport "dora"func init { // create a sprite sprite := dora.NewSpriteWithFile("Image/logo.png") // create the root node of the game scene tree root := dora.NewNode() // mount the sprite to the root node root.AddChild(sprite.Node) // receive and process click events to move the sprite root.OnTapBegan(func(touch: dora.Touch) { sprite.PerformDef(dora.ActionDefMoveTo( 1.0, // Duration, in seconds sprite.GetPosition(), // Start position touch.GetLocation(), // End position dora.EaseOutBack, // Easing function ), false) })} Step Three: Run the game Click the 🎮 icon in the lower right corner of the editor, then click the Run menu item. Alternatively, press the Ctrl + r key combination. 4. Publish the Game Open the right-click menu of the newly created project folder in the game resource tree on the left side of the editor. Click the Download option and wait for the browser to prompt for downloading the packaged project file.