Is it possible to make something like HTML in roblox? Or save UI into a datastore and then load it back

Hello! I was wondering if it was possible to “use” html in roblox, for example: I want to make a custom UI designing thing that saves in a datastore, and i want to use tags like they use in html for positioning, style etc…

An example would be:
A button becomes: <button properties="BackgroundTransparency=1;, 47, 0, 68)"> Button text here </button>
A label becomes: <label properties="...">Label text here</label>

If it is possible, please tell me how, 'cause this would make things a lot easier. Also if there is a different way to save UI designs etc… that would help too.


html is not created to “style” things, it is simply to “layout things”, I think what you are looking for is something similar to css, a combination of html + css, for this, there are libraries like Roact, Fusion, which are quite similar to that.

Fusion: Fusion
Roact: Roact: The Ultimate UI Framework

Extra: I’m not sure if something like html is possible to be created in luau, even if it was, I see it a bit useless / impractical.

1 Like

Yeah but im looking for this just so i could save UI designs in a datastore, if i use those libraries, can they be saved in a datastore? By them i mean their code and then that code be re used on a client that loads back their UI that they saved.


Yes, you could save your GUI design to a datastore.

How would it be possible to achieve it? I would simply obtain all the properties of the gui in a table by converting these properties to a string, so I could save that table in a datastore for later with some code, interpret that table of properties to code and be able to create that gui.

1 Like

So something like this:

local savedGui = {
      [1] = {
           ["type"] = "Label",
           ["Position"] = "pos, pos, pos, pos"

for _, obj in pairs(savedGui) do
     local newObj =["type"])
     for option, val in pairs(obj) do
           if not (option == "type") then
                 newObj:GetAttribute(option) = value
    newObj.Parent = script.Parent

Yep, that would work, now you have to create something that can create the gui based on that data table, But yeah you get the idea :slight_smile:


I edited my reply with code that should work in creating the gui object


You can mimic a webpage in Roblox using the various UI instances, properties & functions/events.


You need to parse it into an AST then generate the GUI from there.

Note: I added fake type annotations to make this easier to understand

The AST would look something like this. A Node represents an instance for your GUI generating function to create.

-- AST
local Tree = {
    -- An Example Node
        Type: string = "???"
        Parent: Node = ???
        Children: Array<Node> = {}
        Properties: Dictionary<string, ???> = {}

You would check for <type key=value> and </type> and get it’s type and the parent node and fill in those fields.

From there you get a temporary Dictionary<string,string> where you put the key part of key=value as the index and the value part as the value.

You would then go through the temporary Dictionary and copy everything to a new Dictionary while parsing and constructing objects from Values like

You then put that Dictionary into the Node’s Properties field.

After that you insert your finished Node into the Children Array of the parent Node

When you have parsed it all you feed the AST to a function that turns it into a GUI.

tl;dr Look into Parsing, Abstract Syntax Trees and how XML parsers work.


If you don’t want to enter the possible properties manually for saving you can get the API-Dump.json from Roblox Client Tracker with HttpService. This allows you to easily get the possible properties from an instance’s ClassName.


Okay so final, I’ve made something like this

local test = "<TextLabel properties='BackgroundTransparency=1;TextScaled=true;TextColor3=255,0,0;Size=1,0,1,0;Position=0,0,0,0' text='TEXT'> <TextButton style='' text='TEXT'>"

local parts = string.split(test, "<", ">")

for _, a in pairs(parts) do
	if (a ~= "") then
		local lbl =, " ")[1])
		lbl.Visible = false
		lbl.Parent =
		lbl.Text = string.gsub(string.gsub(string.split(string.split(a, " ")[3], "=")[2], ">", ""), "'", "")
		local stringProperties = string.gsub(string.gsub(string.split(a, " ")[2], "properties=", ""), "'", "")
		local tableProperties = string.split(stringProperties, ";")
		for _, option in pairs(tableProperties) do
			local optionVals = string.split(option, "=")
			if (optionVals[1] == "Size") then
				local sizes = string.split(optionVals[2], ",")
				lbl.Size =[1], sizes[2], sizes[3], sizes[4])
			elseif (optionVals[1] == "Position") then
				local positions = string.split(optionVals[2], ",")
				lbl.Position =[1], positions[2], positions[3], positions[4])
			elseif (string.find(optionVals[1], "Color3"))  then
					local colors = string.split(optionVals[2], ",")
					lbl[optionVals[1]] =[1], colors[2], colors[3])
					lbl[optionVals[1]] = optionVals[2]
		lbl.Visible = true

It works perfectly.

Credits to @linuxisnotanos and myself lol.