← Back to all projects

LEARN HAXE DEEP DIVE

Learn Haxe: From Zero to Cross-Platform Compilation Master

Goal: Deeply understand Haxe—from its unique cross-platform compilation architecture to its powerful type system, macro metaprogramming, game development capabilities, and the internal workings of its multi-target compiler.


Why Learn Haxe?

Haxe is a remarkable programming language that solves a fundamental problem in software development: writing code once and deploying it everywhere. Unlike other cross-platform solutions that provide runtime abstractions, Haxe compiles your source code directly into native code for each target platform—JavaScript, C++, C#, Java, Python, Lua, PHP, and more.

This isn’t just transpilation; it’s a sophisticated multi-stage compiler written in OCaml that produces idiomatic, optimized code for each target. Haxe has powered successful indie games like Dead Cells (Motion Twin), Northgard (Shiro Games), and is used by major companies for cross-platform development.

After completing these projects, you will:

  • Understand Haxe’s unique multi-target compilation architecture
  • Master the expressive type system (abstract types, enums, pattern matching)
  • Leverage compile-time macros for powerful metaprogramming
  • Build games that run on desktop, web, and mobile from one codebase
  • Write efficient cross-platform libraries and tools
  • Understand the compiler internals and how code transforms across targets

Core Concept Analysis

The Haxe Compilation Architecture

                        ┌─────────────────────────────────┐
                        │         HAXE SOURCE CODE        │
                        │                                 │
                        │   class Player {                │
                        │       public var health:Int;    │
                        │       public function attack()  │
                        │   }                             │
                        └─────────────────────────────────┘
                                        │
                                        ▼
                        ┌─────────────────────────────────┐
                        │       HAXE COMPILER (OCaml)     │
                        │                                 │
                        │  ┌───────────────────────────┐  │
                        │  │     FRONTEND              │  │
                        │  │  • Lexer / Parser         │  │
                        │  │  • Type Inference         │  │
                        │  │  • Macro Expansion        │  │
                        │  │  • AST Generation         │  │
                        │  └───────────────────────────┘  │
                        │              │                  │
                        │              ▼                  │
                        │  ┌───────────────────────────┐  │
                        │  │     TYPED AST             │  │
                        │  │  (Platform-Agnostic IR)   │  │
                        │  └───────────────────────────┘  │
                        │              │                  │
                        │              ▼                  │
                        │  ┌───────────────────────────┐  │
                        │  │     CODE GENERATORS       │  │
                        │  │  (One per target)         │  │
                        │  └───────────────────────────┘  │
                        └─────────────────────────────────┘
                                        │
          ┌─────────────────────────────┼─────────────────────────────┐
          │              │              │              │              │
          ▼              ▼              ▼              ▼              ▼
    ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
    │JavaScript│  │   C++    │  │   C#     │  │  Python  │  │ HashLink │
    │  .js     │  │  .cpp    │  │  .cs     │  │  .py     │  │  .hl     │
    └──────────┘  └──────────┘  └──────────┘  └──────────┘  └──────────┘
          │              │              │              │              │
          ▼              ▼              ▼              ▼              ▼
    ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
    │ Browser  │  │ Native   │  │ .NET     │  │ Python   │  │ HashLink │
    │ Node.js  │  │ Binary   │  │ Unity    │  │ Runtime  │  │ VM       │
    └──────────┘  └──────────┘  └──────────┘  └──────────┘  └──────────┘

Haxe’s Key Differentiators

Feature Haxe TypeScript C# Java
Multi-Target Compilation ✓ (9+ targets) ✗ (JS only) ✗ (.NET only) ✗ (JVM only)
Compile-Time Macros ✓ (Full AST access) ✗ (Limited)
Abstract Types ✓ (Zero-cost)
Pattern Matching ✓ (Native) ✓ (Limited) ✓ (Limited)
Null Safety ✓ (Optional type) ✓ (Nullable) ✓ (Optional)
Algebraic Data Types ✓ (Enums) ✓ (Sealed)

The Type System

// Strong Static Typing with Inference
var name = "Haxe";                     // Inferred as String
var numbers = [1, 2, 3];               // Inferred as Array<Int>

// Enums (Algebraic Data Types)
enum Color {
    Red;
    Green;
    Blue;
    Rgb(r:Int, g:Int, b:Int);
    Hex(value:Int);
}

// Pattern Matching
switch (color) {
    case Red: "Pure red";
    case Rgb(r, _, _) if (r > 200): "Very red";
    case Rgb(r, g, b): 'RGB($r, $g, $b)';
    case _: "Other color";
}

// Abstract Types (Zero-Cost Wrappers)
abstract Percent(Float) {
    public inline function new(value:Float) {
        this = Math.min(100, Math.max(0, value));
    }
    
    @:to public function toFloat():Float return this / 100;
    @:op(A + B) static function add(a:Percent, b:Percent):Percent {
        return new Percent(a.toFloat() + b.toFloat());
    }
}

Macro System (Compile-Time Metaprogramming)

// Macros run at compile time and can:
// 1. Generate code
// 2. Validate code
// 3. Transform AST
// 4. Read files
// 5. Make HTTP requests (yes, at compile time!)

class Macros {
    // This generates a trace at compile time
    macro public static function debug(expr:Expr):Expr {
        var str = ExprTools.toString(expr);
        return macro {
            trace($v{str} + " = " + $expr);
        };
    }
}

// Usage: debug(1 + 2) generates: trace("1 + 2 = " + (1 + 2));

Compilation Targets Comparison

┌─────────────────────────────────────────────────────────────────────┐
│                    HAXE COMPILATION TARGETS                         │
├──────────────┬─────────────────────────────────────────────────────┤
│ TARGET       │ USE CASES                                           │
├──────────────┼─────────────────────────────────────────────────────┤
│ JavaScript   │ Web apps, Node.js, browser games                    │
│ HashLink     │ High-performance games, native applications         │
│ C++          │ Game consoles, mobile, performance-critical apps    │
│ C#           │ Unity integration, .NET applications                │
│ Java         │ Android, enterprise applications                    │
│ Python       │ Scripting, data science, automation                 │
│ Lua          │ Embedded scripting, game mods                       │
│ PHP          │ Web backend, WordPress plugins                      │
│ Flash        │ Legacy Flash applications (deprecated)              │
│ Neko         │ Command-line tools, web servers                     │
│ JVM          │ Direct JVM bytecode generation                      │
└──────────────┴─────────────────────────────────────────────────────┘

Project List

The following 15 projects will take you from Haxe fundamentals to building real cross-platform applications.


Project 1: Multi-Target Hello World

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A (Haxe-specific project)
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: Cross-Platform Compilation / Build Systems
  • Software or Tool: Haxe Compiler, haxelib
  • Main Book: Haxe Manual (haxe.org)

What you’ll build: A single Haxe program that compiles to JavaScript, Python, C++, Lua, and PHP—demonstrating how the same source code produces different outputs for each platform.

Why it teaches Haxe: This forces you to understand the compilation pipeline, target-specific differences, and how Haxe abstracts platform details while giving you access to platform-specific APIs.

Core challenges you’ll face:

  • Setting up the toolchain → maps to understanding haxelib, compilation flags, and build.hxml
  • Target-specific output → maps to seeing how the same code transforms for each platform
  • Running on different runtimes → maps to understanding each target’s execution environment
  • Conditional compilation → maps to using #if js, #if cpp, etc.

Key Concepts:

  • Compilation Targets: Haxe Manual - Compiler Targets
  • Build Files: haxe.org/manual/compiler-usage-hxml.html
  • Conditional Compilation: Haxe Manual - Conditional Compilation

Difficulty: Beginner Time estimate: 1-2 days Prerequisites: Basic programming knowledge, command line familiarity

Real world outcome:

$ haxe build.hxml -js out/main.js
$ node out/main.js
Hello from Haxe! Running on: JavaScript

$ haxe build.hxml -python out/main.py
$ python3 out/main.py
Hello from Haxe! Running on: Python

$ haxe build.hxml -cpp out/
$ ./out/Main
Hello from Haxe! Running on: C++

$ haxe build.hxml -lua out/main.lua
$ lua out/main.lua
Hello from Haxe! Running on: Lua

# All from the same source file!

Implementation Hints:

Your build.hxml file will define compilation options:

-cp src
-main Main
# Each target uses different output flags:
# -js out/main.js
# -python out/main.py
# -cpp out/
# -lua out/main.lua

Think about:

  • How do you detect which target you’re compiling for at compile time?
  • What happens when you try to use a browser-specific API in the C++ target?
  • How does Haxe handle platform differences in its standard library?

Use conditional compilation to show platform-specific behavior:

#if js
    trace("Running on JavaScript");
#elseif cpp
    trace("Running on C++");
#elseif python
    trace("Running on Python");
#end

Learning milestones:

  1. Compile to one target → Understand basic compilation
  2. Compile to all targets → See the multi-target power
  3. Add conditional code → Platform-specific behavior
  4. Use platform-specific APIs → Understand extern and @:native

Project 2: Type System Explorer

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Type Systems / Static Analysis
  • Software or Tool: Haxe Compiler
  • Main Book: “Types and Programming Languages” by Benjamin Pierce

What you’ll build: A collection of type system experiments demonstrating Haxe’s advanced features: abstract types, enums with data, pattern matching, null safety, and type inference—with visual output showing type relationships.

Why it teaches Haxe: Haxe’s type system is its superpower. Understanding abstract types and algebraic data types unlocks the ability to write expressive, safe, and zero-cost abstractions.

Core challenges you’ll face:

  • Creating abstract types → maps to zero-cost wrappers with operator overloading
  • Defining algebraic data types → maps to enums with data constructors
  • Pattern matching → maps to exhaustive case analysis
  • Understanding type inference → maps to how Haxe deduces types

Resources for key challenges:

  • Haxe Manual - Abstract Types: https://haxe.org/manual/types-abstract.html
  • Haxe Manual - Enum: https://haxe.org/manual/types-enum-instance.html
  • Pattern Matching: https://haxe.org/manual/lf-pattern-matching.html

Key Concepts:

  • Abstract Types: Haxe Manual - Abstract Types
  • Enum Instance: Haxe Manual - Enum
  • Pattern Matching: Haxe Manual - Pattern Matching
  • Null Safety: Haxe Manual - Null Safety

Difficulty: Intermediate Time estimate: 1 week Prerequisites: Project 1, understanding of basic type systems

Real world outcome:

$ haxe build.hxml
$ ./TypeExplorer

=== Abstract Type: Distance ===
Creating distances:
  5 meters = 5.0m
  3 feet = 0.9144m (converted)
  5m + 3ft = 5.9144m

=== Enum: Result<T, E> ===
Result.Success(42) -> Matched success with value: 42
Result.Error("Network failed") -> Matched error: Network failed
Result.Success([1,2,3]) -> Success with 3 items

=== Pattern Matching: JSON Parser ===
{"name": "Alice", "age": 30}
Matched object with 2 fields:
  name: Alice (String)
  age: 30 (Number)

=== Null Safety Demo ===
maybeValue: Null<String> = null
Safe access: (no crash, returned null)
Forced access: Would crash with "Null access"
With default: "default value"

Implementation Hints:

Abstract types are zero-cost at runtime but add type safety:

abstract Meters(Float) {
    public inline function new(v:Float) this = v;
    
    @:op(A + B) static function add(a:Meters, b:Meters):Meters
        return new Meters((a:Float) + (b:Float));
}

abstract Feet(Float) {
    @:to public inline function toMeters():Meters
        return new Meters(this * 0.3048);
}

Think about:

  • What happens at runtime with abstract types? (Hint: nothing—they’re erased!)
  • How does the compiler enforce type safety between Meters and Feet?
  • Why is inline important for abstract methods?

Learning milestones:

  1. Create abstract types → Understand zero-cost abstractions
  2. Define rich enums → Algebraic data types with data
  3. Master pattern matching → Exhaustive case handling
  4. Understand null safety → Null as explicit type

Project 3: Macro-Powered JSON Parser

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Metaprogramming / Compile-Time Code Generation
  • Software or Tool: Haxe Macro System
  • Main Book: Haxe Manual - Macros

What you’ll build: A JSON parser that uses compile-time macros to generate type-safe parsing code. Given a Haxe type definition, the macro generates all serialization/deserialization code at compile time—no reflection, no runtime overhead.

Why it teaches Haxe: Macros are Haxe’s most powerful and unique feature. Understanding them unlocks domain-specific languages, compile-time validation, and zero-cost abstractions that are impossible in other languages.

Core challenges you’ll face:

  • Understanding the AST → maps to expression types, typed expressions
  • Building expressions programmatically → maps to reification with macro
  • Type introspection at compile time → maps to Context.getType, TypeTools
  • Error reporting → maps to Context.error, position information

Resources for key challenges:

  • Haxe Manual - Macros: https://haxe.org/manual/macro.html
  • Haxe Macro Guide: https://code.haxe.org/category/macros/
  • tink_macros library for examples

Key Concepts:

  • Expression Macros: Haxe Manual - Expression Macros
  • Build Macros: Haxe Manual - Build Macros
  • Type Building: Haxe Manual - Type Building
  • AST Manipulation: haxe.macro.Expr documentation

Difficulty: Advanced Time estimate: 2-3 weeks Prerequisites: Projects 1-2, understanding of ASTs and compilers

Real world outcome:

// Define your type
typedef User = {
    name: String,
    age: Int,
    email: Null<String>,
    roles: Array<String>
}

// Macro generates parsing code at compile time!
var json = '{"name": "Alice", "age": 30, "roles": ["admin", "user"]}';
var user:User = JsonMacro.parse(json);

trace(user.name);    // "Alice"
trace(user.age);     // 30
trace(user.roles);   // ["admin", "user"]
trace(user.email);   // null (optional field)

// Type errors caught at compile time:
// var bad:User = JsonMacro.parse('{"name": 123}');
// ERROR: Expected String for field 'name', got Int

// Generated code is type-safe and fast:
$ haxe --display src/Main.hx@25 --display-details
// Shows: The macro expanded to 47 lines of type-safe parsing code

Implementation Hints:

A macro receives AST nodes and returns transformed AST:

class JsonMacro {
    macro public static function parse(jsonExpr:Expr):Expr {
        // Get the expected return type from context
        var expectedType = Context.getExpectedType();
        
        // Generate parsing code for this type
        return generateParser(expectedType, jsonExpr);
    }
    
    static function generateParser(type:Type, jsonExpr:Expr):Expr {
        switch (type) {
            case TAnonymous(ref):
                // Generate field-by-field parsing
                var fields = ref.get().fields;
                // Build expression that parses each field
                return macro {
                    var obj = haxe.Json.parse($jsonExpr);
                    // ... generated field access code
                };
            case _:
                Context.error("Unsupported type", Context.currentPos());
                return macro null;
        }
    }
}

Think about:

  • What happens if the JSON doesn’t match the type? Compile error or runtime error?
  • How do you handle nested types (objects containing objects)?
  • How do you report meaningful error messages with file/line information?

Learning milestones:

  1. Write basic macro → Transform simple expressions
  2. Introspect types → Read type information at compile time
  3. Generate code → Build complex expressions programmatically
  4. Handle errors → Report compile-time errors with positions

Project 4: Cross-Platform Game with HaxeFlixel

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Game Development / Cross-Platform
  • Software or Tool: HaxeFlixel, OpenFL
  • Main Book: “HaxeFlixel Tutorial” (haxeflixel.com)

What you’ll build: A complete 2D platformer game that compiles to HTML5/JavaScript, Windows/macOS/Linux native, and mobile (Android/iOS) from a single codebase.

Why it teaches Haxe: Game development is Haxe’s most mature ecosystem. HaxeFlixel and OpenFL demonstrate real-world cross-platform development, asset management, and performance optimization.

Core challenges you’ll face:

  • Game loop architecture → maps to update/render cycles, delta time
  • Asset management → maps to loading images, sounds, tilemaps
  • Input handling → maps to keyboard, touch, gamepad abstraction
  • Multi-platform builds → maps to lime/openfl build targets

Resources for key challenges:

  • HaxeFlixel Demos: https://haxeflixel.com/demos/
  • OpenFL Documentation: https://openfl.org/documentation/
  • HaxeFlixel Snippets: https://snippets.haxeflixel.com/

Key Concepts:

  • FlxState/FlxSprite: HaxeFlixel API Documentation
  • OpenFL Display List: OpenFL documentation
  • Lime Build System: Lime project.xml format
  • Asset Embedding: OpenFL Assets class

Difficulty: Intermediate Time estimate: 3-4 weeks Prerequisites: Projects 1-2, basic game development concepts

Real world outcome:

# Build for HTML5 (web browser)
$ lime build html5
$ firefox bin/html5/bin/index.html

# Build for Windows
$ lime build windows
$ ./bin/windows/PlatformerGame.exe

# Build for macOS
$ lime build mac
$ open bin/mac/PlatformerGame.app

# Build for Linux
$ lime build linux
$ ./bin/linux/PlatformerGame

# Build for Android
$ lime build android
$ adb install bin/android/bin/PlatformerGame.apk

# All from the SAME source code!
# Features:
# - Tile-based levels loaded from Tiled map editor
# - Player with run, jump, wall-slide
# - Enemies with basic AI
# - Collectibles and score
# - Sound effects and music
# - Touch controls on mobile

Implementation Hints:

A basic FlxState for your platformer:

class PlayState extends FlxState {
    var player:Player;
    var level:FlxTilemap;
    var enemies:FlxTypedGroup<Enemy>;
    
    override public function create():Void {
        // Load tilemap from Tiled
        level = new FlxTilemap();
        level.loadMapFromAssets("assets/data/level1.csv", 
                                "assets/images/tiles.png");
        add(level);
        
        // Create player
        player = new Player(100, 100);
        add(player);
        
        // Platform-specific input
        #if mobile
        add(new TouchController(player));
        #end
        
        super.create();
    }
    
    override public function update(elapsed:Float):Void {
        super.update(elapsed);
        
        // Collision detection
        FlxG.collide(player, level);
        FlxG.overlap(player, enemies, playerHitEnemy);
    }
}

Think about:

  • How does HaxeFlixel abstract input across keyboard/touch/gamepad?
  • What’s the performance difference between HTML5 and native builds?
  • How do you handle different screen resolutions and aspect ratios?

Learning milestones:

  1. Create basic game state → FlxState lifecycle
  2. Add player movement → Physics and input
  3. Build levels → Tilemap and collision
  4. Deploy to multiple platforms → Build system mastery

Project 5: Heaps.io 3D Renderer

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 3: Advanced
  • Knowledge Area: 3D Graphics / Game Engines
  • Software or Tool: Heaps.io, HashLink
  • Main Book: Heaps.io Documentation

What you’ll build: A 3D scene renderer using Heaps.io (the engine behind Dead Cells and Northgard) that loads models, applies materials, handles lighting, and allows camera control—running at 60fps via HashLink.

Why it teaches Haxe: Heaps.io represents professional-grade Haxe development. It showcases HashLink’s performance capabilities and Haxe’s ability to compete with native game engines.

Core challenges you’ll face:

  • 3D scene graph → maps to h3d objects, transformations, hierarchy
  • Shader programming → maps to HXSL (Haxe Shader Language)
  • Resource loading → maps to hxd format, asset pipelines
  • HashLink optimization → maps to native performance, garbage collection

Resources for key challenges:

  • Heaps.io Documentation: https://heaps.io/documentation/home.html
  • Heaps.io Samples: https://github.com/HeapsIO/heaps/tree/master/samples
  • HashLink: https://hashlink.haxe.org/

Key Concepts:

  • h3d.scene.Scene: Heaps 3D scene documentation
  • HXSL Shaders: Heaps shader documentation
  • hxd Resources: Heaps resource management
  • HashLink VM: HashLink documentation

Difficulty: Advanced Time estimate: 3-4 weeks Prerequisites: Projects 1-2, 3D math (vectors, matrices), basic shader knowledge

Real world outcome:

$ haxe build.hxml
$ hl bin/Scene3D.hl

# Opens a window with:
# - Loaded .obj or .fbx model with textures
# - Dynamic lighting (point lights, directional)
# - Real-time shadows
# - Camera orbit controls (mouse drag to rotate)
# - FPS counter showing 60fps performance
# - Multiple materials (diffuse, specular, normal maps)

# Press keys:
# WASD - Move camera
# Mouse - Look around
# 1-5 - Switch lighting modes
# R - Reload shaders (hot reload!)

Implementation Hints:

Basic Heaps.io 3D scene setup:

class Main extends hxd.App {
    var scene:h3d.scene.Scene;
    var obj:h3d.scene.Object;
    
    override function init() {
        scene = s3d;  // 3D scene (vs s2d for 2D)
        
        // Load a model
        var cache = new h3d.prim.ModelCache();
        obj = cache.loadModel(hxd.Res.models.character);
        scene.addChild(obj);
        
        // Add lighting
        var light = new h3d.scene.fwd.DirLight(
            new h3d.Vector(0.5, 0.5, -0.5), scene
        );
        light.enableSpecular = true;
        
        // Camera setup
        scene.camera.pos.set(0, -10, 5);
        scene.camera.target.set(0, 0, 0);
    }
    
    override function update(dt:Float) {
        // Rotate object
        obj.rotate(0, 0, dt);
    }
}

Think about:

  • How does HXSL differ from GLSL/HLSL? (It’s type-safe Haxe!)
  • What’s the performance difference between HashLink and JavaScript targets?
  • How does Heaps handle shader compilation for different backends?

Learning milestones:

  1. Render 3D primitive → Basic scene setup
  2. Load external model → Asset pipeline
  3. Add lighting and shadows → Forward/deferred rendering
  4. Write custom shaders → HXSL programming

Project 6: Cross-Platform GUI Application

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: GUI Development / Desktop Applications
  • Software or Tool: HaxeUI
  • Main Book: HaxeUI Documentation

What you’ll build: A desktop application (file manager, text editor, or todo app) with native look-and-feel that compiles to OpenFL, HTML5, WinForms, Kha, and more—from a single UI definition.

Why it teaches Haxe: HaxeUI demonstrates how Haxe’s abstraction capabilities extend beyond games to business applications. Understanding component-based UI and theming systems is valuable for any platform.

Core challenges you’ll face:

  • XML-based layouts → maps to declarative UI definition
  • Data binding → maps to reactive updates
  • Theming → maps to CSS-like styling, native look-and-feel
  • Backend selection → maps to choosing render backends

Resources for key challenges:

  • HaxeUI Documentation: http://haxeui.org/documentation/
  • HaxeUI Examples: https://github.com/haxeui/haxeui-examples
  • Component Reference: http://haxeui.org/api/

Key Concepts:

  • Component System: HaxeUI Component documentation
  • Layout System: HaxeUI Layout documentation
  • Theming: HaxeUI CSS/Styling documentation
  • Backends: HaxeUI Backend documentation

Difficulty: Intermediate Time estimate: 2-3 weeks Prerequisites: Projects 1-2, basic UI/UX concepts

Real world outcome:

# Build for native desktop (via OpenFL)
$ haxelib run haxeui-openfl build.hxml
$ ./bin/TodoApp

# Build for web (HTML5)
$ haxelib run haxeui-html5 build.hxml
# Open bin/index.html

# Same app features on all platforms:
# - Task list with add/remove/edit
# - Categories and filtering
# - Search functionality
# - Local storage persistence
# - Dark/Light theme toggle
# - Keyboard shortcuts

Implementation Hints:

Define UI in XML:

<vbox style="padding:10px">
    <hbox>
        <textfield id="newTask" placeholder="Add new task..." />
        <button text="Add" onclick="addTask" />
    </hbox>
    
    <listview id="taskList" width="100%" height="100%">
        <data>
            <item text="Task 1" completed="false" />
            <item text="Task 2" completed="true" />
        </data>
    </listview>
    
    <hbox>
        <label text="Filter:" />
        <dropdown id="filter">
            <data>
                <item text="All" />
                <item text="Active" />
                <item text="Completed" />
            </data>
        </dropdown>
    </hbox>
</vbox>

Think about:

  • How does HaxeUI abstract native widgets vs custom rendering?
  • What’s the tradeoff between native look-and-feel and consistent appearance?
  • How do you handle platform-specific features (file dialogs, notifications)?

Learning milestones:

  1. Create basic layout → XML definition, components
  2. Add interactivity → Event handlers, callbacks
  3. Implement data binding → Reactive UI updates
  4. Apply theming → CSS-like styling, dark mode

Project 7: Network Protocol Implementation

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Networking / Protocol Design
  • Software or Tool: Haxe sys package, hxbit
  • Main Book: “TCP/IP Illustrated” by W. Richard Stevens

What you’ll build: A cross-platform networking library that implements a custom binary protocol with serialization (using hxbit), supporting both TCP and UDP, working on native and web (WebSocket) targets.

Why it teaches Haxe: Networking showcases Haxe’s ability to handle low-level concerns while maintaining cross-platform compatibility. Understanding how to abstract TCP sockets vs WebSockets is a real-world skill.

Core challenges you’ll face:

  • Binary serialization → maps to hxbit, efficient data encoding
  • Socket abstraction → maps to sys.net.Socket vs js.html.WebSocket
  • Async I/O → maps to callbacks, promises, or threads depending on target
  • Protocol design → maps to message framing, acknowledgments, reliability

Resources for key challenges:

  • Haxe sys.net: https://api.haxe.org/sys/net/
  • hxbit library: https://github.com/HeapsIO/hxbit
  • WebSocket in Haxe: https://lib.haxe.org/p/hxWebSockets/

Key Concepts:

  • Binary Serialization: hxbit documentation
  • Socket Programming: Haxe sys.net.Socket
  • Cross-Target Networking: Conditional compilation for network APIs
  • Message Framing: Binary protocol design

Difficulty: Advanced Time estimate: 3-4 weeks Prerequisites: Projects 1-3, networking fundamentals

Real world outcome:

# Start server (compiles to C++ for performance)
$ haxe server.hxml -cpp bin/server
$ ./bin/server/Server
Server listening on port 9000...

# Connect from native client
$ haxe client.hxml -cpp bin/client
$ ./bin/client/Client
Connected to server!
> send Hello World
Sent: Message { type: TEXT, payload: "Hello World", seq: 1 }
Received ACK for seq 1

# Connect from web client (same client code!)
$ haxe client.hxml -js bin/client.js
# Open in browser - connects via WebSocket automatically
WebSocket connected to ws://localhost:9000
> send Hello from browser!
Sent: Message { type: TEXT, payload: "Hello from browser!", seq: 1 }

# Server shows:
Client connected: 192.168.1.10
Received: Message { type: TEXT, payload: "Hello World", seq: 1 }
Client connected: [WebSocket] browser-client
Received: Message { type: TEXT, payload: "Hello from browser!", seq: 1 }

Implementation Hints:

Abstract networking for different targets:

// Use hxbit for serialization
class Message implements hxbit.Serializable {
    @:s var type:MessageType;
    @:s var payload:String;
    @:s var sequence:Int;
}

// Abstract socket layer
interface ISocket {
    function connect(host:String, port:Int):Void;
    function send(data:haxe.io.Bytes):Void;
    function onData(callback:(haxe.io.Bytes)->Void):Void;
    function close():Void;
}

// Native implementation
#if sys
class NativeSocket implements ISocket {
    var socket:sys.net.Socket;
    // ... implementation using sys.net.Socket
}
#elseif js
class WebSocketWrapper implements ISocket {
    var ws:js.html.WebSocket;
    // ... implementation using WebSocket API
}
#end

Think about:

  • How do you handle partial reads (message spanning multiple TCP packets)?
  • What’s the performance difference between hxbit and JSON serialization?
  • How do you handle reconnection and connection state across platforms?

Learning milestones:

  1. Implement TCP server → Basic socket I/O
  2. Add binary serialization → hxbit for efficient encoding
  3. Abstract for web → WebSocket support
  4. Add protocol features → ACKs, sequencing, reliability

Project 8: Haxe-to-JavaScript Library for npm

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: TypeScript (for type definitions)
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Library Development / JavaScript Ecosystem
  • Software or Tool: Haxe JS target, npm
  • Main Book: Haxe Manual - JavaScript Target

What you’ll build: A reusable library written in Haxe that compiles to JavaScript with TypeScript definitions, publishable to npm, usable by JavaScript/TypeScript developers who don’t know Haxe exists.

Why it teaches Haxe: This demonstrates Haxe’s power as a “better JavaScript” toolchain. You can use Haxe’s type safety and then expose a clean API to the JS ecosystem.

Core challenges you’ll face:

  • Exposing APIs to JS → maps to @:expose, @:keep, extern classes
  • Generating TypeScript definitions → maps to dts generation, type mapping
  • ES modules vs CommonJS → maps to JavaScript module systems
  • Minification and bundling → maps to output optimization

Resources for key challenges:

  • Haxe JavaScript Target: https://haxe.org/manual/target-javascript.html
  • dts-generator: https://lib.haxe.org/p/dts-generator/
  • hxgenjs: https://github.com/nicegamer7/hxgenjs

Key Concepts:

  • @:expose annotation: Haxe Manual - JavaScript Target
  • Extern Classes: Haxe Manual - Externs
  • TypeScript Generation: dts-generator documentation
  • npm Publishing: npm documentation

Difficulty: Intermediate Time estimate: 2 weeks Prerequisites: Projects 1-2, npm/JavaScript ecosystem knowledge

Real world outcome:

# Build the library
$ haxe build.hxml -js dist/my-haxe-lib.js

# Generate TypeScript definitions
$ haxe build.hxml --macro "dts.Generator.generate()"

# Package structure:
dist/
├── my-haxe-lib.js        # Compiled library
├── my-haxe-lib.min.js    # Minified version
├── my-haxe-lib.d.ts      # TypeScript definitions
└── package.json

# Usage from JavaScript:
const { StringUtils, Validator } = require('my-haxe-lib');

console.log(StringUtils.slugify("Hello World!")); // "hello-world"
console.log(Validator.isEmail("test@example.com")); // true

# Usage from TypeScript (with full type safety!):
import { StringUtils, Validator } from 'my-haxe-lib';

const slug: string = StringUtils.slugify("Hello World!");
const valid: boolean = Validator.isEmail("test@example.com");

# npm publish
$ npm publish
+ my-haxe-lib@1.0.0

Implementation Hints:

Expose Haxe classes to JavaScript:

@:expose("StringUtils")
class StringUtils {
    @:expose
    public static function slugify(input:String):String {
        return input.toLowerCase()
            .split(" ").join("-")
            .split(~/[^a-z0-9-]/).join("");
    }
    
    @:expose
    public static function truncate(s:String, maxLen:Int):String {
        if (s.length <= maxLen) return s;
        return s.substr(0, maxLen - 3) + "...";
    }
}

// Generate ES6 module output
// build.hxml: -D js-es=6

Think about:

  • How do Haxe types map to TypeScript types?
  • What happens to Haxe-specific features (enums, abstracts) in the JS output?
  • How do you handle async operations across Haxe and JavaScript conventions?

Learning milestones:

  1. Compile simple library → Basic JS output
  2. Expose clean API → @:expose annotations
  3. Generate TypeScript definitions → Type safety for JS users
  4. Publish to npm → Real-world distribution

Project 9: Compiler Plugin / Build Macro

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 4: Expert
  • Knowledge Area: Compiler Development / Metaprogramming
  • Software or Tool: Haxe Macro System, Build Macros
  • Main Book: Haxe Manual - Macros

What you’ll build: A build-time macro that analyzes your codebase and generates code: an automatic dependency injection framework, or an ORM that generates database queries from type definitions.

Why it teaches Haxe: Build macros are Haxe’s most advanced feature. They run during compilation to generate entire classes and modules. This is how professional Haxe libraries achieve zero-runtime-cost abstractions.

Core challenges you’ll face:

  • @:build and @:autoBuild macros → maps to class-level transformations
  • Type building → maps to Context.defineType, creating new classes
  • Caching → maps to avoiding recompilation, incremental builds
  • IDE integration → maps to completion server, hover information

Resources for key challenges:

  • Build Macros: https://haxe.org/manual/macro-type-building.html
  • haxe.macro.Context: https://api.haxe.org/haxe/macro/Context.html
  • Tinkerbell DI: https://github.com/ustutz/tink_core (example)

Key Concepts:

  • @:build Macro: Haxe Manual - Type Building
  • Type Creation: Context.defineType documentation
  • Field Generation: ClassField manipulation
  • Compile-Time Caching: Context.onAfterTyping

Difficulty: Expert Time estimate: 3-4 weeks Prerequisites: Projects 1-3, deep understanding of type systems

Real world outcome:

// Define your entities with simple annotations
@:entity
class User {
    @:id var id:Int;
    @:column("user_name") var name:String;
    @:column var email:String;
    @:hasMany var posts:Array<Post>;
}

@:entity
class Post {
    @:id var id:Int;
    @:column var title:String;
    @:belongsTo var author:User;
}

// The macro generates at compile time:
// - UserRepository with typed CRUD methods
// - SQL query builders
// - Migration scripts
// - Type-safe joins

// Usage (all type-checked at compile time!):
var repo = new UserRepository(db);
var users = repo.findWhere(u -> u.name == "Alice" && u.posts.length > 5);
// Generates: SELECT * FROM users u WHERE u.user_name = 'Alice' 
//            AND (SELECT COUNT(*) FROM posts WHERE author_id = u.id) > 5

// Compile output:
$ haxe build.hxml
Generating entity: User
  - Created UserRepository with 12 methods
  - Generated 3 SQL query patterns
Generating entity: Post
  - Created PostRepository with 12 methods
  - Created User -> Post relation methods

Implementation Hints:

A build macro transforms a class during compilation:

class EntityMacro {
    macro public static function build():Array<Field> {
        var fields = Context.getBuildFields();
        var cls = Context.getLocalClass().get();
        
        // Find @:column fields
        var columns = [];
        for (field in fields) {
            if (field.meta.has(":column")) {
                columns.push(extractColumnInfo(field));
            }
        }
        
        // Generate repository class
        var repoType = generateRepository(cls.name, columns);
        Context.defineType(repoType);
        
        // Add helper methods to original class
        fields.push(generateToJson(columns));
        fields.push(generateFromRow(columns));
        
        return fields;
    }
}

Think about:

  • How do you handle circular references between generated types?
  • What happens when the user’s code has errors—how do you report them helpfully?
  • How do you make the generated code visible to IDE completion?

Learning milestones:

  1. Create @:build macro → Modify class fields
  2. Generate new types → Context.defineType
  3. Handle relations → Cross-type generation
  4. Add IDE support → Display hints and documentation

Project 10: Interpreted Language in Haxe

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 4: Expert
  • Knowledge Area: Interpreters / Language Implementation
  • Software or Tool: Haxe
  • Main Book: “Crafting Interpreters” by Robert Nystrom

What you’ll build: A complete interpreter for a simple programming language (like Lox from “Crafting Interpreters”) written entirely in Haxe, that runs on all Haxe targets.

Why it teaches Haxe: Building an interpreter exercises Haxe’s pattern matching, algebraic data types, and cross-platform capabilities. Your interpreter will run in the browser, as a native app, or embedded in a game.

Core challenges you’ll face:

  • Lexer/Scanner → maps to tokenization, Haxe’s regex and string handling
  • Parser → maps to recursive descent, Haxe enums for AST
  • Interpreter → maps to tree-walking evaluation, environment management
  • Standard library → maps to native function calls, FFI

Resources for key challenges:

  • Crafting Interpreters: https://craftinginterpreters.com/
  • Haxe Pattern Matching: https://haxe.org/manual/lf-pattern-matching.html
  • PLY (Parsing framework): https://lib.haxe.org/p/ply/

Key Concepts:

  • Tokenization: “Crafting Interpreters” Ch. 4
  • Recursive Descent Parsing: “Crafting Interpreters” Ch. 6
  • Tree-Walking Interpreter: “Crafting Interpreters” Ch. 7
  • Closures and Scope: “Crafting Interpreters” Ch. 11

Difficulty: Expert Time estimate: 4-6 weeks Prerequisites: Projects 1-3, compiler/interpreter theory

Real world outcome:

# The interpreter compiles to any Haxe target
$ haxe build.hxml -js bin/hlox.js
$ haxe build.hxml -cpp bin/hlox

# Run a script
$ node bin/hlox.js examples/fibonacci.lox
# Or: ./bin/hlox/HLox examples/fibonacci.lox

# fibonacci.lox:
fun fib(n) {
    if (n <= 1) return n;
    return fib(n - 1) + fib(n - 2);
}

for (var i = 0; i < 20; i = i + 1) {
    print fib(i);
}

# Output:
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181

# Interactive REPL:
$ ./bin/hlox/HLox
HLox REPL v1.0
> var greeting = "Hello";
> print greeting + " World!";
Hello World!
> fun double(x) { return x * 2; }
> print double(21);
42
>

Implementation Hints:

Use Haxe enums for the AST (perfect fit!):

enum Expr {
    Literal(value:Dynamic);
    Unary(op:Token, right:Expr);
    Binary(left:Expr, op:Token, right:Expr);
    Grouping(expression:Expr);
    Variable(name:Token);
    Assign(name:Token, value:Expr);
    Call(callee:Expr, paren:Token, args:Array<Expr>);
    // ... more
}

enum Stmt {
    Expression(expr:Expr);
    Print(expr:Expr);
    Var(name:Token, initializer:Null<Expr>);
    Block(statements:Array<Stmt>);
    If(condition:Expr, thenBranch:Stmt, elseBranch:Null<Stmt>);
    While(condition:Expr, body:Stmt);
    Function(name:Token, params:Array<Token>, body:Array<Stmt>);
    Return(keyword:Token, value:Null<Expr>);
}

Pattern matching makes interpretation elegant:

function evaluate(expr:Expr):Dynamic {
    return switch (expr) {
        case Literal(value): value;
        case Unary(op, right):
            var r = evaluate(right);
            switch (op.type) {
                case MINUS: -r;
                case BANG: !isTruthy(r);
                case _: throw "Unknown unary operator";
            }
        case Binary(left, op, right):
            var l = evaluate(left);
            var r = evaluate(right);
            switch (op.type) {
                case PLUS: l + r;
                case MINUS: l - r;
                // ... more operators
            }
        // ... more cases
    }
}

Learning milestones:

  1. Build lexer → Tokenize source code
  2. Build parser → Recursive descent, AST generation
  3. Implement interpreter → Tree-walking evaluation
  4. Add functions and closures → Environment and scope

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: C (for native extensions)
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Virtual Machines / Native Development
  • Software or Tool: HashLink, C compiler
  • Main Book: HashLink Documentation

What you’ll build: A high-performance native application using HashLink (HL), including writing a native C extension that Haxe can call, understanding JIT compilation and garbage collection.

Why it teaches Haxe: HashLink is how professional Haxe games (Dead Cells, Northgard) achieve native performance. Understanding its internals—bytecode, JIT, GC—reveals how Haxe bridges high-level code to native execution.

Core challenges you’ll face:

  • HashLink compilation → maps to bytecode generation, HL format
  • Native extensions → maps to hdll, C FFI, memory management
  • Performance profiling → maps to HL profiler, GC tuning
  • JIT vs interpreted mode → maps to understanding tradeoffs

Resources for key challenges:

  • HashLink GitHub: https://github.com/HaxeFoundation/hashlink
  • HashLink Native: https://hashlink.haxe.org/native-extension.html
  • HashLink Profiler: https://hashlink.haxe.org/profiler.html

Key Concepts:

  • HashLink Bytecode: HashLink documentation
  • Native Extensions: HashLink native extension guide
  • Garbage Collection: HL GC documentation
  • JIT Compilation: HashLink JIT documentation

Difficulty: Advanced Time estimate: 3-4 weeks Prerequisites: Projects 1-5, C programming, memory management

Real world outcome:

# Compile to HashLink bytecode
$ haxe build.hxml -hl bin/app.hl

# Run interpreted (for development)
$ hl bin/app.hl
Running in interpreted mode...
Application running at ~30 FPS

# Run with JIT (for production)
$ hl --jit bin/app.hl
Running with JIT compilation...
Application running at ~60 FPS

# Profile the application
$ hl --profile bin/app.hl
Profile saved to profile.json
# Open in Chrome DevTools

# Compile to native C (maximum performance)
$ haxe build.hxml -hl bin/app.c
$ gcc -O3 bin/app.c -o bin/app_native -lhl
$ ./bin/app_native
Running as native binary...
Application running at ~120 FPS

# Using our native extension:
$ cat native/fast_math.c
HL_PRIM float HL_NAME(fast_sin)(float x) {
    return sinf(x);  // Use native sin
}
DEFINE_PRIM(_F32, fast_sin, _F32);

$ ./bin/app_native
Using native fast_sin: 0.8414709848 (10M calls in 45ms)
Using Haxe Math.sin: 0.8414709848 (10M calls in 180ms)
Native extension is 4x faster!

Implementation Hints:

Creating a native extension in C:

// fast_math.c
#define HL_NAME(n) fast_math_##n
#include <hl.h>
#include <math.h>

// Fast SIMD-accelerated distance calculation
HL_PRIM float HL_NAME(fast_distance)(float x1, float y1, float x2, float y2) {
    float dx = x2 - x1;
    float dy = y2 - y1;
    return sqrtf(dx * dx + dy * dy);
}

DEFINE_PRIM(_F32, fast_distance, _F32 _F32 _F32 _F32);

Calling from Haxe:

// Define the extern
@:hlNative("fast_math")
extern class FastMath {
    static function fast_distance(x1:Float, y1:Float, 
                                   x2:Float, y2:Float):Float;
}

// Use it
var dist = FastMath.fast_distance(0, 0, 3, 4);  // 5.0

Think about:

  • When should you use native extensions vs pure Haxe?
  • How does HashLink’s GC differ from target languages’ GCs?
  • What’s the memory overhead of the HL runtime?

Learning milestones:

  1. Compile to HL bytecode → Understand the HL format
  2. Profile and optimize → Use HL profiler
  3. Write native extension → C FFI, hdll creation
  4. Compile to native C → Maximum performance path

Project 12: Cross-Platform Mobile App

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Mobile Development / Cross-Platform
  • Software or Tool: OpenFL, Lime
  • Main Book: OpenFL Documentation

What you’ll build: A mobile application (utility app, simple game, or productivity tool) that runs on both iOS and Android from a single Haxe codebase using OpenFL/Lime.

Why it teaches Haxe: Mobile development showcases Haxe’s real-world cross-platform power. You’ll deal with touch input, device APIs, app store deployment, and performance on constrained devices.

Core challenges you’ll face:

  • Mobile input → maps to touch, gestures, accelerometer
  • Device APIs → maps to camera, notifications, storage
  • App lifecycle → maps to pause, resume, background states
  • Store deployment → maps to signing, icons, metadata

Resources for key challenges:

  • OpenFL Mobile: https://openfl.org/documentation/setup/android/
  • Lime project.xml: https://lime-documentation.readthedocs.io/
  • Extension library: https://lib.haxe.org/p/extension-admob/

Key Concepts:

  • Mobile Targets: OpenFL Android/iOS setup
  • Touch Input: openfl.events.TouchEvent
  • Device Extensions: lime-extension-*
  • App Signing: Android keystore, iOS provisioning

Difficulty: Advanced Time estimate: 3-4 weeks Prerequisites: Projects 4-6, mobile development basics

Real world outcome:

# Build for Android
$ lime build android -release
$ adb install bin/android/bin/MyApp-release.apk

# Build for iOS (requires macOS)
$ lime build ios -release
$ open bin/ios/MyApp.xcodeproj
# Run on simulator or device

# App features (same code!):
# - Touch-based UI with gestures
# - Camera access (QR code scanner)
# - Local notifications
# - SQLite local storage
# - AdMob integration
# - In-app purchases
# - Push notifications

# Performance on device:
# - 60 FPS animations
# - <50MB memory usage
# - <10MB APK size

Implementation Hints:

project.xml configuration for mobile:

<?xml version="1.0" encoding="utf-8"?>
<project>
    <app title="My Haxe App" package="com.example.myapp" version="1.0.0" />
    
    <window width="0" height="0" fps="60" />
    
    <source path="src" />
    <haxelib name="openfl" />
    <haxelib name="extension-admob" />
    
    <!-- Android specific -->
    <android target-sdk-version="30" />
    <android minimum-sdk-version="21" />
    <android permission="android.permission.CAMERA" />
    
    <!-- iOS specific -->
    <ios deployment="11.0" />
    <ios team-id="XXXXXXXXXX" />
    
    <!-- Icons -->
    <icon path="assets/icons/icon-192.png" size="192" />
    <icon path="assets/icons/icon-144.png" size="144" />
</project>

Handle touch input:

class TouchController {
    public function new(sprite:Sprite) {
        sprite.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
        sprite.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
        sprite.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
    }
    
    function onTouchBegin(e:TouchEvent):Void {
        // e.stageX, e.stageY - touch position
        // e.touchPointID - for multi-touch
    }
}

Learning milestones:

  1. Build for mobile → Android/iOS compilation
  2. Handle touch input → Gestures and multi-touch
  3. Access device APIs → Camera, storage, notifications
  4. Deploy to stores → Signing and publishing

Project 13: DSL with Haxe Macros

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 4: Expert
  • Knowledge Area: Domain-Specific Languages / Metaprogramming
  • Software or Tool: Haxe Macro System
  • Main Book: “Domain-Specific Languages” by Martin Fowler

What you’ll build: A domain-specific language embedded in Haxe (like a query language, state machine definition, or test framework) that compiles to efficient Haxe code at compile time.

Why it teaches Haxe: DSLs demonstrate the full power of Haxe’s macro system. You’re essentially creating a new language syntax that’s checked and compiled by Haxe’s type system.

Core challenges you’ll face:

  • Expression parsing → maps to macro expression trees
  • Custom syntax → maps to @:build, expression macros
  • Type generation → maps to Context.defineType, generating code
  • Error messages → maps to position tracking, helpful diagnostics

Resources for key challenges:

  • Haxe DSL Mode: https://dev.to/viz-x/haxe-dsl-mode-the-hidden-configurable-language-inside-haxe-54hd
  • Haxe Macros in Practice: https://code.haxe.org/category/macros/
  • tink_sql example: https://github.com/tink-lang/tink_sql

Key Concepts:

  • Expression Reification: macro syntax in Haxe
  • Parser Combinators: Custom parsing in macros
  • Type Generation: Building types at compile time
  • DSL Design: “Domain-Specific Languages” by Martin Fowler

Difficulty: Expert Time estimate: 4-6 weeks Prerequisites: Projects 3, 9, deep macro understanding

Real world outcome:

// Define a state machine with our DSL
@:stateMachine
class TrafficLight {
    @:initial
    state Red {
        on Timer => Green;
    }
    
    state Green {
        on Timer => Yellow;
    }
    
    state Yellow {
        on Timer => Red;
        on Emergency => Red;
    }
    
    // Guards
    @:guard("Timer")
    function canTransition():Bool {
        return elapsedTime > minimumDuration;
    }
}

// The macro generates:
// - TrafficLightState enum
// - Transition validation
// - Event handling
// - State history tracking

// Usage (fully type-safe!):
var light = new TrafficLight();
light.currentState;  // TrafficLightState.Red

light.send(Timer);   // Type error if Timer not valid from current state
light.currentState;  // TrafficLightState.Green

light.send(Emergency);  // Compile error: Emergency not valid from Green!
                        // (caught at compile time, not runtime)

Implementation Hints:

Parse custom annotations to build state machine:

class StateMachineMacro {
    macro static function build():Array<Field> {
        var fields = Context.getBuildFields();
        var states:Array<StateInfo> = [];
        
        // Find all @:state annotations
        for (field in fields) {
            if (field.meta.has(":state")) {
                states.push(parseState(field));
            }
        }
        
        // Generate state enum
        var stateEnum = generateStateEnum(states);
        Context.defineType(stateEnum);
        
        // Generate transition methods
        var transitionMethods = generateTransitions(states);
        for (m in transitionMethods) {
            fields.push(m);
        }
        
        return fields;
    }
    
    static function parseState(field:Field):StateInfo {
        // Parse the state definition from field body
        // Extract transitions (on X => Y)
        // Return structured state info
    }
}

Think about:

  • How do you provide good error messages for invalid DSL syntax?
  • How do you make the DSL composable with regular Haxe code?
  • What’s the trade-off between DSL expressiveness and compilation speed?

Learning milestones:

  1. Parse custom syntax → Extract DSL from annotations
  2. Generate types → Enums, classes from DSL
  3. Add type safety → Compile-time validation
  4. Integrate with IDE → Completion, error messages

Project 14: Haxe Compiler Contribution

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: OCaml
  • Alternative Programming Languages: Haxe (for testing)
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 5: Master
  • Knowledge Area: Compiler Development / Open Source
  • Software or Tool: OCaml, Haxe Compiler Source
  • Main Book: “Modern Compiler Implementation in ML” by Andrew Appel

What you’ll build: A contribution to the Haxe compiler itself—fixing a bug, adding a small feature, or improving error messages—by understanding and modifying the OCaml codebase.

Why it teaches Haxe: There’s no deeper understanding than working on the compiler itself. You’ll see how parsing, type inference, code generation, and optimization all work together.

Core challenges you’ll face:

  • OCaml syntax and idioms → maps to functional programming, pattern matching
  • Compiler architecture → maps to phases, AST transformations
  • Type system implementation → maps to unification, inference
  • Code generation → maps to target-specific generators

Resources for key challenges:

  • Haxe Compiler Source: https://github.com/HaxeFoundation/haxe
  • OCaml Tutorial: https://ocaml.org/docs/up-and-running
  • Compiler Architecture: Haxe GitHub wiki

Key Concepts:

  • OCaml Programming: Real World OCaml (book)
  • Compiler Phases: “Modern Compiler Implementation” Ch. 1-5
  • Type Inference: “Types and Programming Languages” Ch. 22
  • Code Generation: “Modern Compiler Implementation” Ch. 7

Difficulty: Master Time estimate: 4-8 weeks Prerequisites: All previous projects, OCaml familiarity

Real world outcome:

# Clone and build the compiler
$ git clone https://github.com/HaxeFoundation/haxe
$ cd haxe
$ make

# Understand the structure
$ ls src/
ast.ml          # Abstract Syntax Tree definitions
typer.ml        # Type checker
genjsgen.ml     # JavaScript code generator
gencpp.ml       # C++ code generator
genhl.ml        # HashLink code generator

# Your contribution: Better error messages for abstract types
# Before:
$ haxe test.hx
test.hx:5: characters 10-15 : Abstract has no @:from

# After your patch:
$ haxe test.hx
test.hx:5: characters 10-15 : Cannot implicitly convert String to UserId
  Hint: Add @:from function to abstract UserId:
    @:from static function fromString(s:String):UserId { ... }

# Submit PR
$ git push origin feature/better-abstract-errors
# PR reviewed and merged!

Implementation Hints:

The compiler is written in OCaml with clear modules:

(* src/core/type.ml - Type definitions *)
type t =
    | TMono of t option ref
    | TEnum of tenum * tparams
    | TInst of tclass * tparams
    | TType of tdef * tparams
    | TFun of tfunc
    | TAnon of tanon
    | TDynamic of t option
    | TLazy of (unit -> t) ref
    | TAbstract of tabstract * tparams

(* src/typing/typer.ml - Type inference *)
let rec unify a b = match (a, b) with
    | TMono r, _ when !r = None -> r := Some b
    | _, TMono r when !r = None -> r := Some a
    | TInst (c1, p1), TInst (c2, p2) when c1 == c2 ->
        List.iter2 unify p1 p2
    (* ... more cases *)

Start with small improvements:

  1. Better error messages
  2. Documentation improvements
  3. Test coverage
  4. Small optimizations

Think about:

  • How does type inference work across multiple files?
  • How are macros evaluated during compilation?
  • How does each code generator handle the same typed AST differently?

Learning milestones:

  1. Build from source → Understand build system
  2. Read compiler code → Navigate the OCaml codebase
  3. Make small change → Fix typo or improve message
  4. Contribute feature → Full PR with tests

Project 15: Production Game with Multiple Targets

  • File: LEARN_HAXE_DEEP_DIVE.md
  • Main Programming Language: Haxe
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 5: Pure Magic (Super Cool)
  • Business Potential: 5. The “Industry Disruptor”
  • Difficulty: Level 4: Expert
  • Knowledge Area: Game Development / Cross-Platform Publishing
  • Software or Tool: HaxeFlixel or Heaps.io, Steam SDK, mobile stores
  • Main Book: Varies by game genre

What you’ll build: A complete, polished game released on Steam (Windows/macOS/Linux), mobile stores (iOS/Android), and web (itch.io)—all from a single Haxe codebase, demonstrating professional-grade cross-platform development.

Why it teaches Haxe: This is the capstone project that proves Haxe mastery. You’ll face every real-world challenge: performance, platform quirks, deployment, and maintenance across multiple stores.

Core challenges you’ll face:

  • Performance across targets → maps to profiling, optimization per platform
  • Platform-specific features → maps to achievements, cloud saves, controllers
  • Store requirements → maps to Steam SDK, App Store guidelines
  • Continuous updates → maps to managing builds, patches, backwards compatibility

Resources for key challenges:

  • Steamworks Haxe: https://lib.haxe.org/p/steamworks/
  • Dead Cells postmortems (Motion Twin)
  • Northgard development talks (Shiro Games)

Key Concepts:

  • Game Polish: Game design and UX
  • Platform SDKs: Steam, iOS, Android integration
  • Release Management: CI/CD, versioning
  • Community Management: Feedback, updates

Difficulty: Expert Time estimate: 3-6 months Prerequisites: All previous projects, game design experience

Real world outcome:

# Build for all platforms from single codebase
$ haxe -lib heaps -lib steamworks -hl bin/game.hl    # Steam
$ lime build android -release                         # Android
$ lime build ios -release                             # iOS
$ lime build html5 -final                             # Web

# Steam release
$ steamcmd +login $STEAM_USER +run_app_build app.vdf
Uploading build... done
Build live on Steam!

# Mobile releases
$ fastlane android deploy
$ fastlane ios release

# Stats after 1 month:
# Steam: 10,000 downloads, 92% positive reviews
# iOS: 50,000 downloads, 4.7 stars
# Android: 100,000 downloads, 4.5 stars
# Web: 500,000 plays on itch.io

# All from ONE CODEBASE!

Implementation Hints:

Architecture for multi-platform game:

// Core game logic (platform-agnostic)
class Game {
    var state:GameState;
    var entities:Array<Entity>;
    
    public function update(dt:Float):Void {
        for (e in entities) e.update(dt);
        Platform.instance.updateAchievements(state);
    }
}

// Platform abstraction
interface IPlatform {
    function saveGame(data:SaveData):Void;
    function loadGame():SaveData;
    function unlockAchievement(id:String):Void;
    function showLeaderboard():Void;
}

// Platform implementations
#if steam
class SteamPlatform implements IPlatform {
    function unlockAchievement(id:String):Void {
        SteamAPI.setAchievement(id);
    }
}
#elseif ios
class IOSPlatform implements IPlatform {
    function unlockAchievement(id:String):Void {
        GameCenter.reportAchievement(id);
    }
}
#elseif android
class AndroidPlatform implements IPlatform {
    function unlockAchievement(id:String):Void {
        GooglePlayGames.unlockAchievement(id);
    }
}
#else
class WebPlatform implements IPlatform {
    function unlockAchievement(id:String):Void {
        LocalStorage.set("achievement_" + id, true);
    }
}
#end

Think about:

  • How do you handle different screen sizes and aspect ratios?
  • How do you manage saves across platforms (Steam Cloud, iCloud, Google Drive)?
  • How do you test on all platforms efficiently?

Learning milestones:

  1. Core game complete → Works on one target
  2. All targets working → Runs everywhere
  3. Platform features integrated → Achievements, saves, etc.
  4. Released and maintained → Live on stores

Project Comparison Table

# Project Difficulty Time Key Skill Fun
1 Multi-Target Hello World 1-2 days Compilation Basics ⭐⭐
2 Type System Explorer ⭐⭐ 1 week Type System ⭐⭐⭐
3 Macro-Powered JSON Parser ⭐⭐⭐ 2-3 weeks Metaprogramming ⭐⭐⭐⭐
4 HaxeFlixel Game ⭐⭐ 3-4 weeks Game Development ⭐⭐⭐⭐⭐
5 Heaps.io 3D Renderer ⭐⭐⭐ 3-4 weeks 3D Graphics ⭐⭐⭐⭐⭐
6 Cross-Platform GUI App ⭐⭐ 2-3 weeks UI Development ⭐⭐⭐
7 Network Protocol ⭐⭐⭐ 3-4 weeks Networking ⭐⭐⭐⭐
8 npm Library ⭐⭐ 2 weeks JS Ecosystem ⭐⭐⭐
9 Build Macro / DI Framework ⭐⭐⭐⭐ 3-4 weeks Advanced Macros ⭐⭐⭐⭐
10 Interpreted Language ⭐⭐⭐⭐ 4-6 weeks Language Design ⭐⭐⭐⭐⭐
11 HashLink Native App ⭐⭐⭐ 3-4 weeks Native Development ⭐⭐⭐⭐
12 Mobile App ⭐⭐⭐ 3-4 weeks Mobile Development ⭐⭐⭐⭐
13 DSL with Macros ⭐⭐⭐⭐ 4-6 weeks DSL Design ⭐⭐⭐⭐⭐
14 Compiler Contribution ⭐⭐⭐⭐⭐ 4-8 weeks Compiler Internals ⭐⭐⭐⭐
15 Production Multi-Platform Game ⭐⭐⭐⭐ 3-6 months Full Stack ⭐⭐⭐⭐⭐

Phase 1: Foundations (2-3 weeks)

Build understanding of Haxe’s unique features:

  1. Project 1: Multi-Target Hello World - Understand compilation
  2. Project 2: Type System Explorer - Master the type system

Phase 2: Practical Applications (4-6 weeks)

Apply Haxe to real-world projects:

  1. Project 4: HaxeFlixel Game - 2D game development
  2. Project 6: Cross-Platform GUI App - Desktop applications
  3. Project 8: npm Library - JavaScript ecosystem

Phase 3: Advanced Features (4-6 weeks)

Unlock Haxe’s power features:

  1. Project 3: Macro-Powered JSON Parser - Learn macros
  2. Project 7: Network Protocol - Cross-platform networking
  3. Project 9: Build Macro / DI Framework - Advanced metaprogramming

Phase 4: Deep Expertise (6-8 weeks)

Master the internals:

  1. Project 5: Heaps.io 3D Renderer - High-performance graphics
  2. Project 11: HashLink Native App - Native development
  3. Project 10: Interpreted Language - Language implementation

Phase 5: Mastery (2-4 months)

Contribute and ship:

  1. Project 12: Mobile App - Mobile development
  2. Project 13: DSL with Macros - Language design
  3. Project 14: Compiler Contribution - Compiler internals
  4. Project 15: Production Multi-Platform Game - Ship it!

Summary

# Project Main Language
1 Multi-Target Hello World Haxe
2 Type System Explorer Haxe
3 Macro-Powered JSON Parser Haxe
4 Cross-Platform Game with HaxeFlixel Haxe
5 Heaps.io 3D Renderer Haxe
6 Cross-Platform GUI Application Haxe
7 Network Protocol Implementation Haxe
8 Haxe-to-JavaScript Library for npm Haxe
9 Compiler Plugin / Build Macro Haxe
10 Interpreted Language in Haxe Haxe
11 HashLink Native Application Haxe/C
12 Cross-Platform Mobile App Haxe
13 DSL with Haxe Macros Haxe
14 Haxe Compiler Contribution OCaml
15 Production Game with Multiple Targets Haxe

Resources

Essential Resources

  • Haxe Manual: https://haxe.org/manual/introduction.html - Official comprehensive guide
  • Haxe API Documentation: https://api.haxe.org/ - Standard library reference
  • Haxe Code Cookbook: https://code.haxe.org/ - Practical recipes

Game Development

  • HaxeFlixel: https://haxeflixel.com/ - 2D game framework
  • Heaps.io: https://heaps.io/ - 2D/3D game engine (Dead Cells)
  • OpenFL: https://openfl.org/ - Flash-like display list

Community

  • Haxe Discord: https://discord.gg/haxe - Active community
  • Haxe Forum: https://community.haxe.org/ - Discussion forum
  • Haxe Summit: https://summit.haxe.org/ - Annual conference

Books and Courses

  • “Haxe Game Development Essentials” by Jeremy McCurdy - Game-focused introduction
  • Haxe Video Course (LinkedIn Learning) - Beginner-friendly video course

Notable Haxe Projects

  • Dead Cells (Motion Twin) - Award-winning roguelike
  • Northgard (Shiro Games) - RTS with 2M+ sales
  • Evoland 2 (Shiro Games) - Action RPG
  • Papers, Please (web port) - Document thriller

Tools

  • VSCode Haxe Extension: https://marketplace.visualstudio.com/items?itemName=nadako.vshaxe
  • HaxeLib: https://lib.haxe.org/ - Package manager
  • HashLink: https://hashlink.haxe.org/ - High-performance VM

Total Estimated Time: 8-12 months of dedicated study

After completion: You’ll understand one of the most unique cross-platform compilation systems in existence. You’ll be able to write code once and deploy to browsers, desktops, consoles, and mobile—all while leveraging powerful compile-time metaprogramming that few other languages can match. These skills translate to game development, enterprise applications, and understanding how modern compilers work at a deep level.