Getting assets to generate and compile.
diff --git a/dev/core_generator/lib/src/definition.dart b/dev/core_generator/lib/src/definition.dart
index 88483c6..eb4552d 100644
--- a/dev/core_generator/lib/src/definition.dart
+++ b/dev/core_generator/lib/src/definition.dart
@@ -2,13 +2,12 @@
 import 'dart:io';
 
 import 'package:colorize/colorize.dart';
-// import 'package:core_generator/src/field_type.dart';
 import 'package:core_generator/src/comment.dart';
+import 'package:core_generator/src/configuration.dart';
+import 'package:core_generator/src/cpp_formatter.dart';
 import 'package:core_generator/src/field_type.dart';
 import 'package:core_generator/src/key.dart';
-import 'package:core_generator/src/cpp_formatter.dart';
 import 'package:core_generator/src/property.dart';
-import 'package:core_generator/src/configuration.dart';
 
 String stripExtension(String filename) {
   var index = filename.lastIndexOf('.');
@@ -167,7 +166,10 @@
             property.initialValue ??
             property.type.defaultValue;
         if (initialize != null) {
-          code.write(' = ${property.type.convertCpp(initialize)}');
+          var converted = property.type.convertCpp(initialize);
+          if (converted != null) {
+            code.write(' = $converted');
+          }
         }
         code.write(';');
       }
diff --git a/dev/core_generator/lib/src/field_types/bytes_field_type.dart b/dev/core_generator/lib/src/field_types/bytes_field_type.dart
new file mode 100644
index 0000000..8c2b57c
--- /dev/null
+++ b/dev/core_generator/lib/src/field_types/bytes_field_type.dart
@@ -0,0 +1,22 @@
+import '../field_type.dart';
+
+class BytesFieldType extends FieldType {
+  BytesFieldType()
+      : super(
+          'Bytes',
+          'CoreBytesType',
+          cppName: 'std::vector<uint8_t>',
+          include: '<vector>',
+        );
+
+  @override
+  String get defaultValue => 'std::vector<uint8_t>()';
+
+  @override
+  String get cppGetterName => 'const std::vector<uint8_t>&';
+
+  @override
+  String convertCpp(String value) {
+    return null;
+  }
+}
diff --git a/dev/core_generator/lib/src/field_types/initialize.dart b/dev/core_generator/lib/src/field_types/initialize.dart
index f528437..01c0b2a 100644
--- a/dev/core_generator/lib/src/field_types/initialize.dart
+++ b/dev/core_generator/lib/src/field_types/initialize.dart
@@ -1,12 +1,14 @@
 // All supported field types.
 
 import 'package:core_generator/src/field_type.dart';
+import 'package:core_generator/src/field_types/bytes_field_type.dart';
 
 List<FieldType> fields;
 
 void initializeFields() {
   fields = [
     StringFieldType(),
+    BytesFieldType(),
     UintFieldType(),
     DoubleFieldType(),
     BoolFieldType(),
diff --git a/dev/defs/assets/asset.json b/dev/defs/assets/asset.json
new file mode 100644
index 0000000..0abfc8b
--- /dev/null
+++ b/dev/defs/assets/asset.json
@@ -0,0 +1,39 @@
+{
+  "name": "Asset",
+  "key": {
+    "int": 99,
+    "string": "asset"
+  },
+  "abstract": true,
+  "properties": {
+    "name": {
+      "type": "String",
+      "initialValue": "''",
+      "key": {
+        "int": 203,
+        "string": "name"
+      },
+      "description": "Name of the asset"
+    },
+    "parentId": {
+      "type": "Id",
+      "initialValue": "Core.missingId",
+      "key": {
+        "int": 209,
+        "string": "parentid"
+      },
+      "description": "Id of the parent asset",
+      "runtime": false
+    },
+    "order": {
+      "type": "FractionalIndex",
+      "initialValue": "FractionalIndex.invalid",
+      "key": {
+        "int": 205,
+        "string": "order"
+      },
+      "description": "Order this asset shows up in the assets panel",
+      "runtime": false
+    }
+  }
+}
\ No newline at end of file
diff --git a/dev/defs/assets/drawable_asset.json b/dev/defs/assets/drawable_asset.json
new file mode 100644
index 0000000..97f1013
--- /dev/null
+++ b/dev/defs/assets/drawable_asset.json
@@ -0,0 +1,29 @@
+{
+  "name": "DrawableAsset",
+  "key": {
+    "int": 104,
+    "string": "drawableasset"
+  },
+  "abstract": true,
+  "extends": "assets/file_asset.json",
+  "properties": {
+    "height": {
+      "type": "double",
+      "initialValue": "0",
+      "key": {
+        "int": 207,
+        "string": "height"
+      },
+      "description": "Height of the original asset uploaded"
+    },
+    "width": {
+      "type": "double",
+      "initialValue": "0",
+      "key": {
+        "int": 208,
+        "string": "width"
+      },
+      "description": "Width of the original asset uploaded"
+    }
+  }
+}
\ No newline at end of file
diff --git a/dev/defs/assets/file_asset.json b/dev/defs/assets/file_asset.json
new file mode 100644
index 0000000..5db878a
--- /dev/null
+++ b/dev/defs/assets/file_asset.json
@@ -0,0 +1,30 @@
+{
+  "name": "FileAsset",
+  "key": {
+    "int": 103,
+    "string": "fileasset"
+  },
+  "abstract": true,
+  "extends": "assets/asset.json",
+  "properties": {
+    "assetId": {
+      "type": "uint",
+      "initialValue": "0",
+      "key": {
+        "int": 204,
+        "string": "assetid"
+      },
+      "description": "Id of the asset as stored on the backend"
+    },
+    "size": {
+      "type": "uint",
+      "initialValue": "0",
+      "key": {
+        "int": 211,
+        "string": "size"
+      },
+      "description": "Size of the asset in bytes",
+      "runtime": false
+    }
+  }
+}
\ No newline at end of file
diff --git a/dev/defs/assets/file_asset_contents.json b/dev/defs/assets/file_asset_contents.json
new file mode 100644
index 0000000..e77742a
--- /dev/null
+++ b/dev/defs/assets/file_asset_contents.json
@@ -0,0 +1,19 @@
+{
+  "name": "FileAssetContents",
+  "key": {
+    "int": 106,
+    "string": "file_asset_contents"
+  },
+  "properties": {
+    "bytes": {
+      "type": "Bytes",
+      "initialValue": "[]",
+      "key": {
+        "int": 212,
+        "string": "bytes"
+      },
+      "description": "Byte data of the file.",
+      "coop": false
+    }
+  }
+}
\ No newline at end of file
diff --git a/dev/defs/assets/folder.json b/dev/defs/assets/folder.json
new file mode 100644
index 0000000..d80714a
--- /dev/null
+++ b/dev/defs/assets/folder.json
@@ -0,0 +1,8 @@
+{
+  "name": "Folder",
+  "key": {
+    "int": 102,
+    "string": "folder"
+  },
+  "extends": "assets/asset.json"
+}
\ No newline at end of file
diff --git a/dev/defs/assets/image_asset.json b/dev/defs/assets/image_asset.json
new file mode 100644
index 0000000..6b60274
--- /dev/null
+++ b/dev/defs/assets/image_asset.json
@@ -0,0 +1,8 @@
+{
+  "name": "ImageAsset",
+  "key": {
+    "int": 105,
+    "string": "imageasset"
+  },
+  "extends": "assets/drawable_asset.json"
+}
\ No newline at end of file
diff --git a/dev/defs/shapes/image.json b/dev/defs/shapes/image.json
new file mode 100644
index 0000000..a56cec0
--- /dev/null
+++ b/dev/defs/shapes/image.json
@@ -0,0 +1,21 @@
+{
+  "name": "Image",
+  "key": {
+    "int": 100,
+    "string": "image"
+  },
+  "extends": "drawable.json",
+  "properties": {
+    "assetId": {
+      "type": "Id",
+      "typeRuntime": "uint",
+      "initialValue": "Core.missingId",
+      "initialValueRuntime": "-1",
+      "key": {
+        "int": 206,
+        "string": "assetid"
+      },
+      "description": "Image drawable for an image asset"
+    }
+  }
+}
\ No newline at end of file
diff --git a/dev/generate_core.sh b/dev/generate_core.sh
index 640dfbc..c25ec4d 100755
--- a/dev/generate_core.sh
+++ b/dev/generate_core.sh
@@ -1,6 +1,6 @@
 
 if [[ ! -f "./bin/core_generator" || "$1" == "build" ]]; then
     mkdir -p ./bin
-    dart2native ./core_generator/lib/main.dart -o ./bin/core_generator
+    dart compile exe ./core_generator/lib/main.dart -o ./bin/core_generator
 fi
 ./bin/core_generator
\ No newline at end of file
diff --git a/include/rive/assets/asset.hpp b/include/rive/assets/asset.hpp
new file mode 100644
index 0000000..2b09002
--- /dev/null
+++ b/include/rive/assets/asset.hpp
@@ -0,0 +1,13 @@
+#ifndef _RIVE_ASSET_HPP_
+#define _RIVE_ASSET_HPP_
+#include "rive/generated/assets/asset_base.hpp"
+#include <stdio.h>
+namespace rive
+{
+	class Asset : public AssetBase
+	{
+	public:
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/assets/drawable_asset.hpp b/include/rive/assets/drawable_asset.hpp
new file mode 100644
index 0000000..06660c3
--- /dev/null
+++ b/include/rive/assets/drawable_asset.hpp
@@ -0,0 +1,13 @@
+#ifndef _RIVE_DRAWABLE_ASSET_HPP_
+#define _RIVE_DRAWABLE_ASSET_HPP_
+#include "rive/generated/assets/drawable_asset_base.hpp"
+#include <stdio.h>
+namespace rive
+{
+	class DrawableAsset : public DrawableAssetBase
+	{
+	public:
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/assets/file_asset.hpp b/include/rive/assets/file_asset.hpp
new file mode 100644
index 0000000..50a84b5
--- /dev/null
+++ b/include/rive/assets/file_asset.hpp
@@ -0,0 +1,13 @@
+#ifndef _RIVE_FILE_ASSET_HPP_
+#define _RIVE_FILE_ASSET_HPP_
+#include "rive/generated/assets/file_asset_base.hpp"
+#include <stdio.h>
+namespace rive
+{
+	class FileAsset : public FileAssetBase
+	{
+	public:
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/assets/file_asset_contents.hpp b/include/rive/assets/file_asset_contents.hpp
new file mode 100644
index 0000000..d035621
--- /dev/null
+++ b/include/rive/assets/file_asset_contents.hpp
@@ -0,0 +1,13 @@
+#ifndef _RIVE_FILE_ASSET_CONTENTS_HPP_
+#define _RIVE_FILE_ASSET_CONTENTS_HPP_
+#include "rive/generated/assets/file_asset_contents_base.hpp"
+#include <stdio.h>
+namespace rive
+{
+	class FileAssetContents : public FileAssetContentsBase
+	{
+	public:
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/assets/folder.hpp b/include/rive/assets/folder.hpp
new file mode 100644
index 0000000..e9570b6
--- /dev/null
+++ b/include/rive/assets/folder.hpp
@@ -0,0 +1,13 @@
+#ifndef _RIVE_FOLDER_HPP_
+#define _RIVE_FOLDER_HPP_
+#include "rive/generated/assets/folder_base.hpp"
+#include <stdio.h>
+namespace rive
+{
+	class Folder : public FolderBase
+	{
+	public:
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/assets/image_asset.hpp b/include/rive/assets/image_asset.hpp
new file mode 100644
index 0000000..c3fed2d
--- /dev/null
+++ b/include/rive/assets/image_asset.hpp
@@ -0,0 +1,13 @@
+#ifndef _RIVE_IMAGE_ASSET_HPP_
+#define _RIVE_IMAGE_ASSET_HPP_
+#include "rive/generated/assets/image_asset_base.hpp"
+#include <stdio.h>
+namespace rive
+{
+	class ImageAsset : public ImageAssetBase
+	{
+	public:
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/core/binary_reader.hpp b/include/rive/core/binary_reader.hpp
index f7e8627..8d569ab 100644
--- a/include/rive/core/binary_reader.hpp
+++ b/include/rive/core/binary_reader.hpp
@@ -3,32 +3,34 @@
 #define _RIVE_CORE_BINARY_READER_HPP_
 
 #include <string>
+#include <vector>
 
 namespace rive
 {
 	class BinaryReader
 	{
-    private:
-        uint8_t* m_Position;
-        uint8_t* m_End;
-        bool m_Overflowed;
-        size_t m_Length;
+	private:
+		uint8_t* m_Position;
+		uint8_t* m_End;
+		bool m_Overflowed;
+		size_t m_Length;
 
-        void overflow();
+		void overflow();
 
-    public:
-        BinaryReader(uint8_t* bytes, size_t length);
-        bool didOverflow() const;
-        bool reachedEnd() const;
+	public:
+		BinaryReader(uint8_t* bytes, size_t length);
+		bool didOverflow() const;
+		bool reachedEnd() const;
 
-        size_t lengthInBytes() const;
+		size_t lengthInBytes() const;
 
-        std::string readString();
-        double readFloat64();
-        float readFloat32();
-        uint8_t readByte();
-        uint32_t readUint32();
-        uint64_t readVarUint64(); // Reads a LEB128 encoded uint64_t
+		std::string readString();
+		std::vector<uint8_t> readBytes();
+		double readFloat64();
+		float readFloat32();
+		uint8_t readByte();
+		uint32_t readUint32();
+		uint64_t readVarUint64(); // Reads a LEB128 encoded uint64_t
 	};
 } // namespace rive
 
diff --git a/include/rive/core/field_types/core_bytes_type.hpp b/include/rive/core/field_types/core_bytes_type.hpp
new file mode 100644
index 0000000..b0fb146
--- /dev/null
+++ b/include/rive/core/field_types/core_bytes_type.hpp
@@ -0,0 +1,16 @@
+#ifndef _RIVE_CORE_BYTES_TYPE_HPP_
+#define _RIVE_CORE_BYTES_TYPE_HPP_
+
+#include <vector>
+
+namespace rive
+{
+	class BinaryReader;
+	class CoreBytesType
+	{
+	public:
+		static const int id = 1;
+		static std::vector<uint8_t> deserialize(BinaryReader& reader);
+	};
+} // namespace rive
+#endif
\ No newline at end of file
diff --git a/include/rive/generated/assets/asset_base.hpp b/include/rive/generated/assets/asset_base.hpp
new file mode 100644
index 0000000..a9b5d6e
--- /dev/null
+++ b/include/rive/generated/assets/asset_base.hpp
@@ -0,0 +1,65 @@
+#ifndef _RIVE_ASSET_BASE_HPP_
+#define _RIVE_ASSET_BASE_HPP_
+#include <string>
+#include "rive/core.hpp"
+#include "rive/core/field_types/core_string_type.hpp"
+namespace rive
+{
+	class AssetBase : public Core
+	{
+	protected:
+		typedef Core Super;
+
+	public:
+		static const uint16_t typeKey = 99;
+
+		/// Helper to quickly determine if a core object extends another without
+		/// RTTI at runtime.
+		bool isTypeOf(uint16_t typeKey) const override
+		{
+			switch (typeKey)
+			{
+				case AssetBase::typeKey:
+					return true;
+				default:
+					return false;
+			}
+		}
+
+		uint16_t coreType() const override { return typeKey; }
+
+		static const uint16_t namePropertyKey = 203;
+
+	private:
+		std::string m_Name = "";
+	public:
+		inline const std::string& name() const { return m_Name; }
+		void name(std::string value)
+		{
+			if (m_Name == value)
+			{
+				return;
+			}
+			m_Name = value;
+			nameChanged();
+		}
+
+		void copy(const AssetBase& object) { m_Name = object.m_Name; }
+
+		bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
+		{
+			switch (propertyKey)
+			{
+				case namePropertyKey:
+					m_Name = CoreStringType::deserialize(reader);
+					return true;
+			}
+			return false;
+		}
+
+	protected:
+		virtual void nameChanged() {}
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/generated/assets/drawable_asset_base.hpp b/include/rive/generated/assets/drawable_asset_base.hpp
new file mode 100644
index 0000000..4a498bb
--- /dev/null
+++ b/include/rive/generated/assets/drawable_asset_base.hpp
@@ -0,0 +1,88 @@
+#ifndef _RIVE_DRAWABLE_ASSET_BASE_HPP_
+#define _RIVE_DRAWABLE_ASSET_BASE_HPP_
+#include "rive/assets/file_asset.hpp"
+#include "rive/core/field_types/core_double_type.hpp"
+namespace rive
+{
+	class DrawableAssetBase : public FileAsset
+	{
+	protected:
+		typedef FileAsset Super;
+
+	public:
+		static const uint16_t typeKey = 104;
+
+		/// Helper to quickly determine if a core object extends another without
+		/// RTTI at runtime.
+		bool isTypeOf(uint16_t typeKey) const override
+		{
+			switch (typeKey)
+			{
+				case DrawableAssetBase::typeKey:
+				case FileAssetBase::typeKey:
+				case AssetBase::typeKey:
+					return true;
+				default:
+					return false;
+			}
+		}
+
+		uint16_t coreType() const override { return typeKey; }
+
+		static const uint16_t heightPropertyKey = 207;
+		static const uint16_t widthPropertyKey = 208;
+
+	private:
+		float m_Height = 0.0f;
+		float m_Width = 0.0f;
+	public:
+		inline float height() const { return m_Height; }
+		void height(float value)
+		{
+			if (m_Height == value)
+			{
+				return;
+			}
+			m_Height = value;
+			heightChanged();
+		}
+
+		inline float width() const { return m_Width; }
+		void width(float value)
+		{
+			if (m_Width == value)
+			{
+				return;
+			}
+			m_Width = value;
+			widthChanged();
+		}
+
+		void copy(const DrawableAssetBase& object)
+		{
+			m_Height = object.m_Height;
+			m_Width = object.m_Width;
+			FileAsset::copy(object);
+		}
+
+		bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
+		{
+			switch (propertyKey)
+			{
+				case heightPropertyKey:
+					m_Height = CoreDoubleType::deserialize(reader);
+					return true;
+				case widthPropertyKey:
+					m_Width = CoreDoubleType::deserialize(reader);
+					return true;
+			}
+			return FileAsset::deserialize(propertyKey, reader);
+		}
+
+	protected:
+		virtual void heightChanged() {}
+		virtual void widthChanged() {}
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/generated/assets/file_asset_base.hpp b/include/rive/generated/assets/file_asset_base.hpp
new file mode 100644
index 0000000..26c18df
--- /dev/null
+++ b/include/rive/generated/assets/file_asset_base.hpp
@@ -0,0 +1,69 @@
+#ifndef _RIVE_FILE_ASSET_BASE_HPP_
+#define _RIVE_FILE_ASSET_BASE_HPP_
+#include "rive/assets/asset.hpp"
+#include "rive/core/field_types/core_uint_type.hpp"
+namespace rive
+{
+	class FileAssetBase : public Asset
+	{
+	protected:
+		typedef Asset Super;
+
+	public:
+		static const uint16_t typeKey = 103;
+
+		/// Helper to quickly determine if a core object extends another without
+		/// RTTI at runtime.
+		bool isTypeOf(uint16_t typeKey) const override
+		{
+			switch (typeKey)
+			{
+				case FileAssetBase::typeKey:
+				case AssetBase::typeKey:
+					return true;
+				default:
+					return false;
+			}
+		}
+
+		uint16_t coreType() const override { return typeKey; }
+
+		static const uint16_t assetIdPropertyKey = 204;
+
+	private:
+		int m_AssetId = 0;
+	public:
+		inline int assetId() const { return m_AssetId; }
+		void assetId(int value)
+		{
+			if (m_AssetId == value)
+			{
+				return;
+			}
+			m_AssetId = value;
+			assetIdChanged();
+		}
+
+		void copy(const FileAssetBase& object)
+		{
+			m_AssetId = object.m_AssetId;
+			Asset::copy(object);
+		}
+
+		bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
+		{
+			switch (propertyKey)
+			{
+				case assetIdPropertyKey:
+					m_AssetId = CoreUintType::deserialize(reader);
+					return true;
+			}
+			return Asset::deserialize(propertyKey, reader);
+		}
+
+	protected:
+		virtual void assetIdChanged() {}
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/generated/assets/file_asset_contents_base.hpp b/include/rive/generated/assets/file_asset_contents_base.hpp
new file mode 100644
index 0000000..6e66b35
--- /dev/null
+++ b/include/rive/generated/assets/file_asset_contents_base.hpp
@@ -0,0 +1,69 @@
+#ifndef _RIVE_FILE_ASSET_CONTENTS_BASE_HPP_
+#define _RIVE_FILE_ASSET_CONTENTS_BASE_HPP_
+#include <vector>
+#include "rive/core.hpp"
+#include "rive/core/field_types/core_bytes_type.hpp"
+namespace rive
+{
+	class FileAssetContentsBase : public Core
+	{
+	protected:
+		typedef Core Super;
+
+	public:
+		static const uint16_t typeKey = 106;
+
+		/// Helper to quickly determine if a core object extends another without
+		/// RTTI at runtime.
+		bool isTypeOf(uint16_t typeKey) const override
+		{
+			switch (typeKey)
+			{
+				case FileAssetContentsBase::typeKey:
+					return true;
+				default:
+					return false;
+			}
+		}
+
+		uint16_t coreType() const override { return typeKey; }
+
+		static const uint16_t bytesPropertyKey = 212;
+
+	private:
+		std::vector<uint8_t> m_Bytes;
+	public:
+		inline const std::vector<uint8_t>& bytes() const { return m_Bytes; }
+		void bytes(std::vector<uint8_t> value)
+		{
+			if (m_Bytes == value)
+			{
+				return;
+			}
+			m_Bytes = value;
+			bytesChanged();
+		}
+
+		Core* clone() const override;
+		void copy(const FileAssetContentsBase& object)
+		{
+			m_Bytes = object.m_Bytes;
+		}
+
+		bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
+		{
+			switch (propertyKey)
+			{
+				case bytesPropertyKey:
+					m_Bytes = CoreBytesType::deserialize(reader);
+					return true;
+			}
+			return false;
+		}
+
+	protected:
+		virtual void bytesChanged() {}
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/generated/assets/folder_base.hpp b/include/rive/generated/assets/folder_base.hpp
new file mode 100644
index 0000000..09b3962
--- /dev/null
+++ b/include/rive/generated/assets/folder_base.hpp
@@ -0,0 +1,36 @@
+#ifndef _RIVE_FOLDER_BASE_HPP_
+#define _RIVE_FOLDER_BASE_HPP_
+#include "rive/assets/asset.hpp"
+namespace rive
+{
+	class FolderBase : public Asset
+	{
+	protected:
+		typedef Asset Super;
+
+	public:
+		static const uint16_t typeKey = 102;
+
+		/// Helper to quickly determine if a core object extends another without
+		/// RTTI at runtime.
+		bool isTypeOf(uint16_t typeKey) const override
+		{
+			switch (typeKey)
+			{
+				case FolderBase::typeKey:
+				case AssetBase::typeKey:
+					return true;
+				default:
+					return false;
+			}
+		}
+
+		uint16_t coreType() const override { return typeKey; }
+
+		Core* clone() const override;
+
+	protected:
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/generated/assets/image_asset_base.hpp b/include/rive/generated/assets/image_asset_base.hpp
new file mode 100644
index 0000000..f0bf068
--- /dev/null
+++ b/include/rive/generated/assets/image_asset_base.hpp
@@ -0,0 +1,38 @@
+#ifndef _RIVE_IMAGE_ASSET_BASE_HPP_
+#define _RIVE_IMAGE_ASSET_BASE_HPP_
+#include "rive/assets/drawable_asset.hpp"
+namespace rive
+{
+	class ImageAssetBase : public DrawableAsset
+	{
+	protected:
+		typedef DrawableAsset Super;
+
+	public:
+		static const uint16_t typeKey = 105;
+
+		/// Helper to quickly determine if a core object extends another without
+		/// RTTI at runtime.
+		bool isTypeOf(uint16_t typeKey) const override
+		{
+			switch (typeKey)
+			{
+				case ImageAssetBase::typeKey:
+				case DrawableAssetBase::typeKey:
+				case FileAssetBase::typeKey:
+				case AssetBase::typeKey:
+					return true;
+				default:
+					return false;
+			}
+		}
+
+		uint16_t coreType() const override { return typeKey; }
+
+		Core* clone() const override;
+
+	protected:
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/generated/component_base.hpp b/include/rive/generated/component_base.hpp
index 02bb97e..b08927b 100644
--- a/include/rive/generated/component_base.hpp
+++ b/include/rive/generated/component_base.hpp
@@ -35,7 +35,6 @@
 	private:
 		std::string m_Name = "";
 		int m_ParentId = 0;
-
 	public:
 		inline const std::string& name() const { return m_Name; }
 		void name(std::string value)
diff --git a/include/rive/generated/core_registry.hpp b/include/rive/generated/core_registry.hpp
index 5b8a86c..485b1cb 100644
--- a/include/rive/generated/core_registry.hpp
+++ b/include/rive/generated/core_registry.hpp
@@ -41,6 +41,12 @@
 #include "rive/animation/transition_trigger_condition.hpp"
 #include "rive/animation/transition_value_condition.hpp"
 #include "rive/artboard.hpp"
+#include "rive/assets/asset.hpp"
+#include "rive/assets/drawable_asset.hpp"
+#include "rive/assets/file_asset.hpp"
+#include "rive/assets/file_asset_contents.hpp"
+#include "rive/assets/folder.hpp"
+#include "rive/assets/image_asset.hpp"
 #include "rive/backboard.hpp"
 #include "rive/bones/bone.hpp"
 #include "rive/bones/cubic_weight.hpp"
@@ -74,6 +80,7 @@
 #include "rive/shapes/cubic_mirrored_vertex.hpp"
 #include "rive/shapes/cubic_vertex.hpp"
 #include "rive/shapes/ellipse.hpp"
+#include "rive/shapes/image.hpp"
 #include "rive/shapes/paint/fill.hpp"
 #include "rive/shapes/paint/gradient_stop.hpp"
 #include "rive/shapes/paint/linear_gradient.hpp"
@@ -217,6 +224,8 @@
 					return new Polygon();
 				case StarBase::typeKey:
 					return new Star();
+				case ImageBase::typeKey:
+					return new Image();
 				case CubicDetachedVertexBase::typeKey:
 					return new CubicDetachedVertex();
 				case DrawRulesBase::typeKey:
@@ -237,6 +246,12 @@
 					return new Tendon();
 				case CubicWeightBase::typeKey:
 					return new CubicWeight();
+				case FolderBase::typeKey:
+					return new Folder();
+				case ImageAssetBase::typeKey:
+					return new ImageAsset();
+				case FileAssetContentsBase::typeKey:
+					return new FileAssetContents();
 			}
 			return nullptr;
 		}
@@ -253,6 +268,9 @@
 				case AnimationBase::namePropertyKey:
 					object->as<AnimationBase>()->name(value);
 					break;
+				case AssetBase::namePropertyKey:
+					object->as<AssetBase>()->name(value);
+					break;
 			}
 		}
 		static void setUint(Core* object, int propertyKey, int value)
@@ -393,6 +411,9 @@
 				case PolygonBase::pointsPropertyKey:
 					object->as<PolygonBase>()->points(value);
 					break;
+				case ImageBase::assetIdPropertyKey:
+					object->as<ImageBase>()->assetId(value);
+					break;
 				case DrawRulesBase::drawTargetIdPropertyKey:
 					object->as<DrawRulesBase>()->drawTargetId(value);
 					break;
@@ -417,6 +438,9 @@
 				case CubicWeightBase::outIndicesPropertyKey:
 					object->as<CubicWeightBase>()->outIndices(value);
 					break;
+				case FileAssetBase::assetIdPropertyKey:
+					object->as<FileAssetBase>()->assetId(value);
+					break;
 			}
 		}
 		static void setDouble(Core* object, int propertyKey, float value)
@@ -666,6 +690,12 @@
 				case TendonBase::tyPropertyKey:
 					object->as<TendonBase>()->ty(value);
 					break;
+				case DrawableAssetBase::heightPropertyKey:
+					object->as<DrawableAssetBase>()->height(value);
+					break;
+				case DrawableAssetBase::widthPropertyKey:
+					object->as<DrawableAssetBase>()->width(value);
+					break;
 			}
 		}
 		static void setBool(Core* object, int propertyKey, bool value)
@@ -748,6 +778,16 @@
 					break;
 			}
 		}
+		static void
+		setBytes(Core* object, int propertyKey, std::vector<uint8_t> value)
+		{
+			switch (propertyKey)
+			{
+				case FileAssetContentsBase::bytesPropertyKey:
+					object->as<FileAssetContentsBase>()->bytes(value);
+					break;
+			}
+		}
 		static std::string getString(Core* object, int propertyKey)
 		{
 			switch (propertyKey)
@@ -758,6 +798,8 @@
 					return object->as<StateMachineComponentBase>()->name();
 				case AnimationBase::namePropertyKey:
 					return object->as<AnimationBase>()->name();
+				case AssetBase::namePropertyKey:
+					return object->as<AssetBase>()->name();
 			}
 			return "";
 		}
@@ -857,6 +899,8 @@
 					return object->as<ClippingShapeBase>()->fillRule();
 				case PolygonBase::pointsPropertyKey:
 					return object->as<PolygonBase>()->points();
+				case ImageBase::assetIdPropertyKey:
+					return object->as<ImageBase>()->assetId();
 				case DrawRulesBase::drawTargetIdPropertyKey:
 					return object->as<DrawRulesBase>()->drawTargetId();
 				case WeightBase::valuesPropertyKey:
@@ -873,6 +917,8 @@
 					return object->as<CubicWeightBase>()->outValues();
 				case CubicWeightBase::outIndicesPropertyKey:
 					return object->as<CubicWeightBase>()->outIndices();
+				case FileAssetBase::assetIdPropertyKey:
+					return object->as<FileAssetBase>()->assetId();
 			}
 			return 0;
 		}
@@ -1046,6 +1092,10 @@
 					return object->as<TendonBase>()->tx();
 				case TendonBase::tyPropertyKey:
 					return object->as<TendonBase>()->ty();
+				case DrawableAssetBase::heightPropertyKey:
+					return object->as<DrawableAssetBase>()->height();
+				case DrawableAssetBase::widthPropertyKey:
+					return object->as<DrawableAssetBase>()->width();
 			}
 			return 0.0f;
 		}
@@ -1112,6 +1162,15 @@
 			}
 			return 0;
 		}
+		static std::vector<uint8_t> getBytes(Core* object, int propertyKey)
+		{
+			switch (propertyKey)
+			{
+				case FileAssetContentsBase::bytesPropertyKey:
+					return object->as<FileAssetContentsBase>()->bytes();
+			}
+			return std::vector<uint8_t>();
+		}
 		static int propertyFieldId(int propertyKey)
 		{
 			switch (propertyKey)
@@ -1119,6 +1178,7 @@
 				case ComponentBase::namePropertyKey:
 				case StateMachineComponentBase::namePropertyKey:
 				case AnimationBase::namePropertyKey:
+				case AssetBase::namePropertyKey:
 					return CoreStringType::id;
 				case ComponentBase::parentIdPropertyKey:
 				case DrawTargetBase::drawableIdPropertyKey:
@@ -1164,6 +1224,7 @@
 				case ClippingShapeBase::sourceIdPropertyKey:
 				case ClippingShapeBase::fillRulePropertyKey:
 				case PolygonBase::pointsPropertyKey:
+				case ImageBase::assetIdPropertyKey:
 				case DrawRulesBase::drawTargetIdPropertyKey:
 				case WeightBase::valuesPropertyKey:
 				case WeightBase::indicesPropertyKey:
@@ -1172,6 +1233,7 @@
 				case CubicWeightBase::inIndicesPropertyKey:
 				case CubicWeightBase::outValuesPropertyKey:
 				case CubicWeightBase::outIndicesPropertyKey:
+				case FileAssetBase::assetIdPropertyKey:
 					return CoreUintType::id;
 				case ConstraintBase::strengthPropertyKey:
 				case DistanceConstraintBase::distancePropertyKey:
@@ -1252,6 +1314,8 @@
 				case TendonBase::yyPropertyKey:
 				case TendonBase::txPropertyKey:
 				case TendonBase::tyPropertyKey:
+				case DrawableAssetBase::heightPropertyKey:
+				case DrawableAssetBase::widthPropertyKey:
 					return CoreDoubleType::id;
 				case TransformComponentConstraintBase::offsetPropertyKey:
 				case TransformComponentConstraintBase::doesCopyPropertyKey:
@@ -1276,6 +1340,8 @@
 				case SolidColorBase::colorValuePropertyKey:
 				case GradientStopBase::colorValuePropertyKey:
 					return CoreColorType::id;
+				case FileAssetContentsBase::bytesPropertyKey:
+					return CoreBytesType::id;
 				default:
 					return -1;
 			}
diff --git a/include/rive/generated/shapes/image_base.hpp b/include/rive/generated/shapes/image_base.hpp
new file mode 100644
index 0000000..ba3b163
--- /dev/null
+++ b/include/rive/generated/shapes/image_base.hpp
@@ -0,0 +1,75 @@
+#ifndef _RIVE_IMAGE_BASE_HPP_
+#define _RIVE_IMAGE_BASE_HPP_
+#include "rive/core/field_types/core_uint_type.hpp"
+#include "rive/drawable.hpp"
+namespace rive
+{
+	class ImageBase : public Drawable
+	{
+	protected:
+		typedef Drawable Super;
+
+	public:
+		static const uint16_t typeKey = 100;
+
+		/// Helper to quickly determine if a core object extends another without
+		/// RTTI at runtime.
+		bool isTypeOf(uint16_t typeKey) const override
+		{
+			switch (typeKey)
+			{
+				case ImageBase::typeKey:
+				case DrawableBase::typeKey:
+				case NodeBase::typeKey:
+				case TransformComponentBase::typeKey:
+				case WorldTransformComponentBase::typeKey:
+				case ContainerComponentBase::typeKey:
+				case ComponentBase::typeKey:
+					return true;
+				default:
+					return false;
+			}
+		}
+
+		uint16_t coreType() const override { return typeKey; }
+
+		static const uint16_t assetIdPropertyKey = 206;
+
+	private:
+		int m_AssetId = -1;
+	public:
+		inline int assetId() const { return m_AssetId; }
+		void assetId(int value)
+		{
+			if (m_AssetId == value)
+			{
+				return;
+			}
+			m_AssetId = value;
+			assetIdChanged();
+		}
+
+		Core* clone() const override;
+		void copy(const ImageBase& object)
+		{
+			m_AssetId = object.m_AssetId;
+			Drawable::copy(object);
+		}
+
+		bool deserialize(uint16_t propertyKey, BinaryReader& reader) override
+		{
+			switch (propertyKey)
+			{
+				case assetIdPropertyKey:
+					m_AssetId = CoreUintType::deserialize(reader);
+					return true;
+			}
+			return Drawable::deserialize(propertyKey, reader);
+		}
+
+	protected:
+		virtual void assetIdChanged() {}
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/include/rive/shapes/image.hpp b/include/rive/shapes/image.hpp
new file mode 100644
index 0000000..c74c802
--- /dev/null
+++ b/include/rive/shapes/image.hpp
@@ -0,0 +1,14 @@
+#ifndef _RIVE_IMAGE_HPP_
+#define _RIVE_IMAGE_HPP_
+#include "rive/generated/shapes/image_base.hpp"
+#include <stdio.h>
+namespace rive
+{
+	class Image : public ImageBase
+	{
+	public:
+		void draw(Renderer* renderer) override;
+	};
+} // namespace rive
+
+#endif
\ No newline at end of file
diff --git a/src/core/binary_reader.cpp b/src/core/binary_reader.cpp
index 0596549..153c9ba 100644
--- a/src/core/binary_reader.cpp
+++ b/src/core/binary_reader.cpp
@@ -59,6 +59,19 @@
 	return std::string(rawValue.data(), length);
 }
 
+std::vector<uint8_t> BinaryReader::readBytes()
+{
+	uint64_t length = readVarUint64();
+	if (didOverflow())
+	{
+		return std::vector<uint8_t>();
+	}
+
+	uint8_t* start = m_Position;
+	m_Position += length;
+	return std::vector<uint8_t>(start, start + length);
+}
+
 double BinaryReader::readFloat64()
 {
 	double value;
diff --git a/src/core/field_types/core_bytes_type.cpp b/src/core/field_types/core_bytes_type.cpp
new file mode 100644
index 0000000..b35ddd3
--- /dev/null
+++ b/src/core/field_types/core_bytes_type.cpp
@@ -0,0 +1,9 @@
+#include "rive/core/field_types/core_bytes_type.hpp"
+#include "rive/core/binary_reader.hpp"
+
+using namespace rive;
+
+std::vector<uint8_t> CoreBytesType::deserialize(BinaryReader& reader)
+{
+	return reader.readBytes();
+}
\ No newline at end of file
diff --git a/src/generated/assets/file_asset_contents_base.cpp b/src/generated/assets/file_asset_contents_base.cpp
new file mode 100644
index 0000000..9e0ae9b
--- /dev/null
+++ b/src/generated/assets/file_asset_contents_base.cpp
@@ -0,0 +1,11 @@
+#include "rive/generated/assets/file_asset_contents_base.hpp"
+#include "rive/assets/file_asset_contents.hpp"
+
+using namespace rive;
+
+Core* FileAssetContentsBase::clone() const
+{
+	auto cloned = new FileAssetContents();
+	cloned->copy(*this);
+	return cloned;
+}
diff --git a/src/generated/assets/folder_base.cpp b/src/generated/assets/folder_base.cpp
new file mode 100644
index 0000000..3e05a32
--- /dev/null
+++ b/src/generated/assets/folder_base.cpp
@@ -0,0 +1,11 @@
+#include "rive/generated/assets/folder_base.hpp"
+#include "rive/assets/folder.hpp"
+
+using namespace rive;
+
+Core* FolderBase::clone() const
+{
+	auto cloned = new Folder();
+	cloned->copy(*this);
+	return cloned;
+}
diff --git a/src/generated/assets/image_asset_base.cpp b/src/generated/assets/image_asset_base.cpp
new file mode 100644
index 0000000..bc0d4cd
--- /dev/null
+++ b/src/generated/assets/image_asset_base.cpp
@@ -0,0 +1,11 @@
+#include "rive/generated/assets/image_asset_base.hpp"
+#include "rive/assets/image_asset.hpp"
+
+using namespace rive;
+
+Core* ImageAssetBase::clone() const
+{
+	auto cloned = new ImageAsset();
+	cloned->copy(*this);
+	return cloned;
+}
diff --git a/src/generated/shapes/image_base.cpp b/src/generated/shapes/image_base.cpp
new file mode 100644
index 0000000..519694d
--- /dev/null
+++ b/src/generated/shapes/image_base.cpp
@@ -0,0 +1,11 @@
+#include "rive/generated/shapes/image_base.hpp"
+#include "rive/shapes/image.hpp"
+
+using namespace rive;
+
+Core* ImageBase::clone() const
+{
+	auto cloned = new Image();
+	cloned->copy(*this);
+	return cloned;
+}
diff --git a/src/shapes/image.cpp b/src/shapes/image.cpp
new file mode 100644
index 0000000..dee6734
--- /dev/null
+++ b/src/shapes/image.cpp
@@ -0,0 +1,11 @@
+#include "rive/shapes/image.hpp"
+
+using namespace rive;
+
+void Image::draw(Renderer* renderer)
+{
+	if (renderOpacity() == 0.0f)
+	{
+		return;
+	}
+}
\ No newline at end of file