DevLog 20250805: Divooka Node Graph File Formats
Charles Zhang

Charles Zhang @methodoxdivooka

About: Visual programming for everyone.

Location:
Toronto
Joined:
May 7, 2025

DevLog 20250805: Divooka Node Graph File Formats

Publish Date: Aug 6
1 0

Preamble

When I first envisioned Divooka, I aimed for open source, open file formats, and strong version control friendliness (especially with Git). JSON is verbose and ugly, YAML is perfect but too complex, and formats like CSV/RTS/OBJ are simple and elegant but lack the flexibility needed for complex structures. A custom line-based format seemed like a good middle ground and necessary starting point.

This led to the intention of creating a simple, human-friendly, and easy-to-parse file format - something like TOML. This approach has proven effective in the past; I've parsed similar formats before, and it works well for INI, config, and even Godot scene files.

Canonical TOML Example

# This is a TOML document

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00

[database]
enabled = true
ports = [ 8000, 8001, 8002 ]
data = [ ["delta", "phi"], [3.14] ]
temp_targets = { cpu = 79.5, case = 72.0 }

[servers]

[servers.alpha]
ip = "10.0.0.1"
role = "frontend"

[servers.beta]
ip = "10.0.0.2"
role = "backend"
Enter fullscreen mode Exit fullscreen mode

The only issue I have with TOML is largely aesthetic: it's just not beautiful enough. Objects are too scattered, and it can feel a bit verbose - especially when incorporating type information, as seen in a Godot scene file:

[gd_scene load_steps=2 format=3 uid="uid://dbmf10vsl4g6q"]

[ext_resource type="Script" uid="uid://dcyr50rclg8m1" path="res://scenes/login.gd" id="1_l7r8x"]

[node name="Login" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_l7r8x")

[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -80.0
offset_top = -80.5
offset_right = 80.0
offset_bottom = 80.5
grow_horizontal = 2
grow_vertical = 2

[node name="Label" type="Label" parent="VBoxContainer"]
layout_mode = 2
theme_override_font_sizes/font_size = 46
text = "Login"
horizontal_alignment = 1
Enter fullscreen mode Exit fullscreen mode

The Two Approaches

Divooka Open Standard (Plain Text/Binary Hybrid)

We’ll eventually discuss the broader Divooka Open Standard, but for now, let’s focus specifically on file formats. My original vision was for something like Blender’s .blend format - except in plain text: a sequence of self-contained data blocks that allow easy extension and are powerful enough to store arbitrary payloads.

I imagined blocks for: document properties, nodes, graphs (including connections), payloads, revisions, etc. Some attributes - such as node positions and sizes - are considered auxiliary and handled through "decorators" rather than being part of the core schema. Perhaps I went too far here: the flexibility results in many small structures holding trivial bits of data. On the bright side, once implemented, this approach yields a format that is both human-readable and programmatically digestible. Interpreters uninterested in positional data, for instance, can simply ignore those decorators.

One of the early design decisions was to keep all attributes as strings. The idea was to rely on parsing for interpretation and avoid enforcing types directly. Much like the web, this promotes forward compatibility and long-term document stability. I still stand by this: nothing is easier to parse than plain text.

That said, I made a mistake in implementing everything strictly in this format: the string-based format only makes sense during (de)serialization. Once in memory, the data should be converted into strongly typed structures before any meaningful work is done. Otherwise, everything becomes cluttered with unnecessary boilerplate.

PV1 Neo Document Format (Binary)

PV1 Neo takes a more opinionated, object-oriented approach. Documents contain graphs, which in turn contain nodes and connections. Each of these is represented as a strongly typed object. By default, nodes include layout properties like position and size.

This results in a neat OOP hierarchy where everything is properly defined and serialized. The upside is ease of development - you simply call Serialize() at the top level and the rest follows. However, the downside is that parsing becomes nearly impossible without full knowledge of the exact object types. Any misalignment in type expectations results in binary stream reading errors.

Derivations

Since Divooka graphs can already be represented in text via the Open Standard, I’ve proposed two derived, minimalist formats: MiniParcel and MicroParcel. These are lightweight, CLI-friendly formats designed for shell use. The rationale is that since nodes can represent abstract functions or endpoints, users should be able to manipulate them without relying on a GUI.

Default:
    FileList = GetFiles "{tempFolderPath}"
    FileRenameList = Enhance @FileList !#Rename
    Apply @FileRenameList !MoveFile
Rename:
    FileName = GetOnlyName (GetArgument :0)
    Return (Replace @FileName ":File_Sequence_00(.)" ":File-Sequence-00$1")
Enter fullscreen mode Exit fullscreen mode

Conclusion

As we finalize prototyping and start committing to core design decisions, file format is one area requiring careful long-term thinking. There’s an inherent trade-off between programmability and readability/portability - especially since Divooka documents may eventually hold a vast variety of data.

In the foreseeable future, both formats may coexist. In fact, it might make sense to support both for the long term. As Divooka matures and gains better standardization, I’m hopeful we’ll arrive at a robust format that truly supports the long-term vision.

References

Comments 0 total

    Add comment