roblox-dart

Write Dart. Ship Luau.

Because Luau is fine, but Dart is home.

roblox-dart is a Dart-to-Luau transpiler for Roblox development. Write your game logic in Dart — with real classes, null safety, and a proper type system — and compile it to idiomatic Luau that runs natively in Roblox Studio.

Inspired by roblox-ts. Built for Dart developers who want to feel at home on Roblox.

⚠️ Early development. roblox-dart is functional but not production-ready. APIs will change, edge cases exist, and not every Dart or Roblox feature is supported yet. Use it for personal projects, experiments, and contributions — not for shipped games. Feedback and PRs are very welcome.


How it works

// src/server/main.server.dart
import 'package:roblox_dart/services.dart' show workspace;
import 'package:roblox_dart/roblox.dart';

void main() {
  workspace.gravity = 0;

  final part = Instance("Part");
  part.parent = workspace;

  final pos = Vector3(0, 10, 0);
  final goal = Vector3(0, 0, 0);
  final lerped = pos.lerp(goal, 0.5);
}

Compiles to:

local workspace = game:GetService("Workspace")

function main()
  workspace.Gravity = 0

  local part = Instance.new("Part")
  part.Parent = workspace

  local pos = Vector3.new(0, 10, 0)
  local goal = Vector3.new(0, 0, 0)
  local lerped = pos:Lerp(goal, 0.5)
end

main()

Installation

Requirements: Dart SDK 3.0+, Rojo 7+

dart pub global activate roblox_dart

Make sure the pub cache bin folder is in your system's PATH so you can run the roblox-dart command from anywhere.

Windows

On Windows, the pub cache is usually located at %LOCALAPPDATA%\Pub\Cache\bin.

PowerShell (Run once, then restart the terminal):

$env:PATH += ";$env:LOCALAPPDATA\Pub\Cache\bin"
# To make it permanent:
[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";$env:LOCALAPPDATA\Pub\Cache\bin", "User")

Command Prompt:

setx PATH "%PATH%;%LOCALAPPDATA%\Pub\Cache\bin"

macOS / Linux

Add this to your ~/.bashrc, ~/.zshrc, or ~/.bash_profile:

export PATH="$HOME/.pub-cache/bin:$PATH"

Quick start

macOS / Linux / Git Bash:

mkdir my-game && cd my-game
roblox-dart init
roblox-dart watch

Windows (PowerShell / Command Prompt):

mkdir my-game
cd my-game
roblox-dart init
roblox-dart watch

Then open Roblox Studio, connect Rojo, and start building.


Commands

Command Description
roblox-dart init Creates project structure, default.project.json, and runs dart pub get
roblox-dart watch Compiles all files in src/ and watches for changes
roblox-dart translate -t <file> Translates a single Dart file to Luau

File conventions

File naming determines the Roblox script type — same convention as roblox-ts:

File Luau output Roblox type
foo.server.dart foo.server.luau Script (server)
foo.client.dart foo.client.luau LocalScript (client)
foo.dart foo.luau ModuleScript

Project structure

roblox-dart init generates this structure:

my-game/
├── default.project.json   ← Rojo config
├── pubspec.yaml
├── src/
│   ├── server/            → ServerScriptService
│   ├── client/            → StarterPlayer.StarterPlayerScripts
│   └── shared/            → ReplicatedStorage.shared
└── out/                   ← compiled Luau (gitignored)
    ├── include/           → ReplicatedStorage.include (RuntimeLib)
    ├── server/
    ├── client/
    └── shared/

Roblox API

Services

import 'package:roblox_dart/services.dart' show workspace, players;

workspace.gravity = 0;
final local = players.localPlayer;

Types

import 'package:roblox_dart/roblox.dart';

// Value types
final v = Vector3(1, 2, 3);
final mag = v.magnitude;        // → v.Magnitude
final u = v.unit;               // → v.Unit
final d = v.dot(other);         // → v:Dot(other)
final l = v.lerp(goal, 0.5);    // → v:Lerp(goal, 0.5)
final zero = Vector3.zero;      // → Vector3.zero

final cf = CFrame(0, 5, 0);
final color = Color3.fromRGB(255, 0, 0);
final size = UDim2.fromScale(1, 0.5);

// Instances
final part = Instance("Part");
part.parent = workspace;
part.name = "MyPart";
final child = part.findFirstChild("Handle");   // → part:FindFirstChild("Handle")
part.destroy();                                 // → part:Destroy()

Supported types

Type Status
Vector3
CFrame
Color3
UDim2
Instance
BasePart
Humanoid
Workspace
Players
TweenService 🔜
RemoteEvent 🔜
RBXScriptSignal 🔜

Language features

Feature Status
Classes + inheritance
Mixins
Static members
Getters / setters
Factory constructors
Null safety (?., ??, ??=)
Generics (basic)
Enums
Closures / lambdas
async / await 🔜
Extension methods 🔜

Adding new Roblox types

The type system is designed to scale. Adding a new type takes three steps:

1. Create the stub (lib/packages/types/tween_service.dart):

import 'package:roblox_dart/packages/types/instance.dart';

class TweenService extends Instance {
  external factory TweenService();
  external Tween create(Instance instance, TweenInfo tweenInfo, Map<String, dynamic> propertyTable);
}

2. Register it (lib/compiler/macros/roblox/roblox_macro_registry.dart):

'TweenService': RobloxTypeMacro(),

3. Export it (lib/services.dart):

TweenService get tweenService => throw UnimplementedError('Transpiler only');

All methods automatically translate camelCasePascalCase with the correct : or . separator. No extra mapping needed.


Architecture

Dart source
    ↓  analyzer (dart:analyzer)
    AST
    ↓  RobloxVisitor (visitor pattern)
    ↓    ExpressionVisitor  → MacroResolver → RobloxMacroRegistry
    ↓    StatementVisitor
    ↓    ImportVisitor      → game:GetService() for services
    ↓    ClassVisitor       → metatables + inheritance
    Luau AST nodes
    ↓  emit()
    Luau source

Contributing

Issues and PRs welcome at github.com/Andzzio/roblox-dart.


Built by someone who loves Dart and Roblox, but prefers not to write Luau.

Libraries

cli/command_manager
cli/commands/init_command
cli/commands/translate_command
cli/commands/watch_command
compiler/compiler_logger
compiler/macros/list_macros
compiler/macros/macro_resolver
compiler/macros/roblox/roblox_macro_registry
compiler/macros/roblox/roblox_type_macro
compiler/macros/roblox/vector3_macros
compiler/macros/string_macros
compiler/macros/type_macros
compiler/parameter_result
compiler/roblox_compiler
compiler/roblox_visitor
compiler/visitor/class_visitor
compiler/visitor/expression_visitor
compiler/visitor/import_visitor
compiler/visitor/literal_visitor
compiler/visitor/roblox_visitor_base
compiler/visitor/statement_visitor
luau/declaration/luau_anonymous_function
luau/declaration/luau_class
luau/declaration/luau_constructor
luau/declaration/luau_enum
luau/declaration/luau_function
luau/declaration/luau_method
luau/declaration/luau_parameter
luau/expression/luau_assignment_expression
luau/expression/luau_binary_expression
luau/expression/luau_call_expression
luau/expression/luau_conditional_expression
luau/expression/luau_function_invocation
luau/expression/luau_index_expression
luau/expression/luau_list_literal
luau/expression/luau_literal
luau/expression/luau_map_literal
luau/luau_node
luau/statement/luau_continue_statement
luau/statement/luau_do_statement
luau/statement/luau_expression_statement
luau/statement/luau_for_in_statement
luau/statement/luau_for_statement
luau/statement/luau_if_statement
luau/statement/luau_numeric__for_statement
luau/statement/luau_pair_for_each
luau/statement/luau_return_statement
luau/statement/luau_try_catch
luau/statement/luau_variable_declaration
luau/statement/luau_variable_declaration_group
luau/statement/luau_while_statement
packages/services/players
packages/services/workspace
packages/types/base_part
packages/types/cframe
packages/types/color3
packages/types/humanoid
packages/types/instance
packages/types/udim2
packages/types/vector3
roblox
rojo/rojo_resolver
services
version