diff --git a/components/Helpers/src/OSVersion.cs b/components/Helpers/src/OSVersion.cs
new file mode 100644
index 00000000..26a04627
--- /dev/null
+++ b/components/Helpers/src/OSVersion.cs
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace CommunityToolkit.WinUI.Helpers;
+
+/// 
+/// Defines Operating System version
+/// 
+public struct OSVersion
+{
+    /// 
+    /// Value describing major version
+    /// 
+    public ushort Major;
+
+    /// 
+    /// Value describing minor version
+    /// 
+    public ushort Minor;
+
+    /// 
+    /// Value describing build
+    /// 
+    public ushort Build;
+
+    /// 
+    /// Value describing revision
+    /// 
+    public ushort Revision;
+
+    /// 
+    /// Converts OSVersion to string
+    /// 
+    /// Major.Minor.Build.Revision as a string
+    public override readonly string ToString()
+        => $"{Major}.{Minor}.{Build}.{Revision}";
+}
diff --git a/components/Helpers/src/ObjectStorage/ApplicationDataStorageHelper.cs b/components/Helpers/src/ObjectStorage/ApplicationDataStorageHelper.cs
new file mode 100644
index 00000000..2912716d
--- /dev/null
+++ b/components/Helpers/src/ObjectStorage/ApplicationDataStorageHelper.cs
@@ -0,0 +1,344 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using CommunityToolkit.Common.Helpers;
+using Windows.Storage;
+using Windows.System;
+using CommunityToolkit.Helpers;
+
+namespace CommunityToolkit.WinUI.Helpers.ObjectStorage;
+
+/// 
+/// Storage helper for files and folders living in Windows.Storage.ApplicationData storage endpoints.
+/// 
+/// The data store to interact with.
+/// Serializer for converting stored values. Defaults to .
+public partial class ApplicationDataStorageHelper(ApplicationData appData, IObjectSerializer? objectSerializer = null) : IFileStorageHelper, ISettingsStorageHelper
+{
+    /// 
+    /// Gets the settings container.
+    /// 
+    public ApplicationDataContainer Settings => AppData.LocalSettings;
+
+    /// 
+    ///  Gets the storage folder.
+    /// 
+    public StorageFolder Folder => AppData.LocalFolder;
+
+    /// 
+    /// Gets the storage host.
+    /// 
+    protected ApplicationData AppData { get; } = appData ?? throw new ArgumentNullException(nameof(appData));
+
+    /// 
+    /// Gets the serializer for converting stored values.
+    /// 
+    protected IObjectSerializer Serializer { get; } = objectSerializer ?? new SystemSerializer();
+
+    /// 
+    /// Get a new instance using ApplicationData.Current and the provided serializer.
+    /// 
+    /// Serializer for converting stored values. Defaults to .
+    /// A new instance of ApplicationDataStorageHelper.
+    public static ApplicationDataStorageHelper GetCurrent(IObjectSerializer? objectSerializer = null)
+    {
+        var appData = ApplicationData.Current;
+        return new ApplicationDataStorageHelper(appData, objectSerializer);
+    }
+
+#if !HAS_UNO
+    /// 
+    /// Get a new instance using the ApplicationData for the provided user and serializer.
+    /// 
+    /// App data user owner.
+    /// Serializer for converting stored values. Defaults to .
+    /// A new instance of ApplicationDataStorageHelper.
+    public static async Task GetForUserAsync(User user, IObjectSerializer? objectSerializer = null)
+    {
+        var appData = await ApplicationData.GetForUserAsync(user);
+        return new ApplicationDataStorageHelper(appData, objectSerializer);
+    }
+#endif
+
+    /// 
+    /// Determines whether a setting already exists.
+    /// 
+    /// Key of the setting (that contains object).
+    /// True if a value exists.
+    public bool KeyExists(string key)
+    {
+        return Settings.Values.ContainsKey(key);
+    }
+
+    /// 
+    /// Retrieves a single item by its key.
+    /// 
+    /// Type of object retrieved.
+    /// Key of the object.
+    /// Default value of the object.
+    /// The TValue object.
+    public T? Read(string key, T? @default = default)
+    {
+        if (Settings.Values.TryGetValue(key, out var valueObj) && valueObj is string valueString)
+        {
+            return Serializer.Deserialize(valueString);
+        }
+
+        return @default;
+    }
+
+    /// 
+    public bool TryRead(string key, out T? value)
+    {
+        if (Settings.Values.TryGetValue(key, out var valueObj) && valueObj is string valueString)
+        {
+            value = Serializer.Deserialize(valueString);
+            return true;
+        }
+
+        value = default;
+        return false;
+    }
+
+    /// 
+    public void Save(string key, T value)
+    {
+        Settings.Values[key] = Serializer.Serialize(value);
+    }
+
+    /// 
+    public bool TryDelete(string key)
+    {
+        return Settings.Values.Remove(key);
+    }
+
+    /// 
+    public void Clear()
+    {
+        Settings.Values.Clear();
+    }
+
+    /// 
+    /// Determines whether a setting already exists in composite.
+    /// 
+    /// Key of the composite (that contains settings).
+    /// Key of the setting (that contains object).
+    /// True if a value exists.
+    public bool KeyExists(string compositeKey, string key)
+    {
+        if (TryRead(compositeKey, out ApplicationDataCompositeValue? composite) && composite != null)
+        {
+            return composite.ContainsKey(key);
+        }
+
+        return false;
+    }
+
+    /// 
+    /// Attempts to retrieve a single item by its key in composite.
+    /// 
+    /// Type of object retrieved.
+    /// Key of the composite (that contains settings).
+    /// Key of the object.
+    /// The value of the object retrieved.
+    /// The T object.
+    public bool TryRead(string compositeKey, string key, out T? value)
+    {
+        if (TryRead(compositeKey, out ApplicationDataCompositeValue? composite) && composite != null)
+        {
+            string compositeValue = (string)composite[key];
+            if (compositeValue != null)
+            {
+                value = Serializer.Deserialize(compositeValue);
+                return true;
+            }
+        }
+
+        value = default;
+        return false;
+    }
+
+    /// 
+    /// Retrieves a single item by its key in composite.
+    /// 
+    /// Type of object retrieved.
+    /// Key of the composite (that contains settings).
+    /// Key of the object.
+    /// Default value of the object.
+    /// The T object.
+    public T? Read(string compositeKey, string key, T? @default = default)
+    {
+        if (TryRead(compositeKey, out ApplicationDataCompositeValue? composite) && composite != null)
+        {
+            if (composite.TryGetValue(key, out var valueObj) && valueObj is string value)
+            {
+                return Serializer.Deserialize(value);
+            }
+        }
+
+        return @default;
+    }
+
+    /// 
+    /// Saves a group of items by its key in a composite.
+    /// This method should be considered for objects that do not exceed 8k bytes during the lifetime of the application
+    /// and for groups of settings which need to be treated in an atomic way.
+    /// 
+    /// Type of object saved.
+    /// Key of the composite (that contains settings).
+    /// Objects to save.
+    public void Save(string compositeKey, IDictionary values)
+    {
+        if (TryRead(compositeKey, out ApplicationDataCompositeValue? composite) && composite != null)
+        {
+            foreach (KeyValuePair setting in values)
+            {
+                var serializedValue = Serializer.Serialize(setting.Value) ?? string.Empty;
+                if (composite.ContainsKey(setting.Key))
+                {
+                    composite[setting.Key] = serializedValue;
+                }
+                else
+                {
+                    composite.Add(setting.Key, serializedValue);
+                }
+            }
+        }
+        else
+        {
+            composite = [];
+            foreach (KeyValuePair setting in values)
+            {
+                var serializedValue = Serializer.Serialize(setting.Value) ?? string.Empty;
+                composite.Add(setting.Key, serializedValue);
+            }
+
+            Settings.Values[compositeKey] = composite;
+        }
+    }
+
+    /// 
+    /// Deletes a single item by its key in composite.
+    /// 
+    /// Key of the composite (that contains settings).
+    /// Key of the object.
+    /// A boolean indicator of success.
+    public bool TryDelete(string compositeKey, string key)
+    {
+        if (TryRead(compositeKey, out ApplicationDataCompositeValue? composite) && composite != null)
+        {
+            return composite.Remove(key);
+        }
+
+        return false;
+    }
+
+    /// 
+    public Task ReadFileAsync(string filePath, T? @default = default)
+    {
+        return ReadFileAsync(Folder, filePath, @default);
+    }
+
+    /// 
+    public Task> ReadFolderAsync(string folderPath)
+    {
+        return ReadFolderAsync(Folder, folderPath);
+    }
+
+    /// 
+    public Task CreateFileAsync(string filePath, T value)
+    {
+        return CreateFileAsync(Folder, filePath, value);
+    }
+
+    /// 
+    public Task CreateFolderAsync(string folderPath)
+    {
+        return CreateFolderAsync(Folder, folderPath);
+    }
+
+    /// 
+    public Task TryDeleteItemAsync(string itemPath)
+    {
+        return TryDeleteItemAsync(Folder, itemPath);
+    }
+
+    /// 
+    public Task TryRenameItemAsync(string itemPath, string newName)
+    {
+        return TryRenameItemAsync(Folder, itemPath, newName);
+    }
+
+    private async Task ReadFileAsync(StorageFolder folder, string filePath, T? @default = default)
+    {
+        string value = await StorageFileHelper.ReadTextFromFileAsync(folder, NormalizePath(filePath));
+        return (value != null) ? Serializer.Deserialize(value) : @default;
+    }
+
+    private async Task> ReadFolderAsync(StorageFolder folder, string folderPath)
+    {
+        var targetFolder = await folder.GetFolderAsync(NormalizePath(folderPath));
+        var items = await targetFolder.GetItemsAsync();
+
+        return items.Select((item) =>
+        {
+            var itemType = item.IsOfType(StorageItemTypes.File) ? DirectoryItemType.File
+                : item.IsOfType(StorageItemTypes.Folder) ? DirectoryItemType.Folder
+                : DirectoryItemType.None;
+
+            return (itemType, item.Name);
+        });
+    }
+
+    private async Task CreateFileAsync(StorageFolder folder, string filePath, T value)
+    {
+        var serializedValue = Serializer.Serialize(value)?.ToString() ?? string.Empty;
+        return await StorageFileHelper.WriteTextToFileAsync(folder, serializedValue, NormalizePath(filePath), CreationCollisionOption.ReplaceExisting);
+    }
+
+    private async Task CreateFolderAsync(StorageFolder folder, string folderPath)
+    {
+        await folder.CreateFolderAsync(NormalizePath(folderPath), CreationCollisionOption.OpenIfExists);
+    }
+
+    private async Task TryDeleteItemAsync(StorageFolder folder, string itemPath)
+    {
+        try
+        {
+            var item = await folder.GetItemAsync(NormalizePath(itemPath));
+            await item.DeleteAsync();
+            return true;
+        }
+        catch
+        {
+            return false;
+        }
+    }
+
+    private async Task TryRenameItemAsync(StorageFolder folder, string itemPath, string newName)
+    {
+        try
+        {
+            var item = await folder.GetItemAsync(NormalizePath(itemPath));
+            await item.RenameAsync(newName, NameCollisionOption.FailIfExists);
+            return true;
+        }
+        catch
+        {
+            return false;
+        }
+    }
+
+    private string NormalizePath(string path)
+    {
+        var directoryName = Path.GetDirectoryName(path) ?? string.Empty;
+        var fileName = Path.GetFileName(path);
+        return Path.Combine(directoryName, fileName);
+    }
+}
diff --git a/components/Helpers/src/StorageFileHelper.cs b/components/Helpers/src/StorageFileHelper.cs
new file mode 100644
index 00000000..d40b9e41
--- /dev/null
+++ b/components/Helpers/src/StorageFileHelper.cs
@@ -0,0 +1,747 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using Windows.ApplicationModel;
+using Windows.Storage;
+using Windows.Storage.Search;
+using Windows.Storage.Streams;
+
+namespace CommunityToolkit.WinUI.Helpers;
+
+/// 
+/// This class provides static helper methods for .
+/// 
+public static class StorageFileHelper
+{
+    /// 
+    /// Saves a string value to a  in application local folder/>.
+    /// 
+    /// 
+    /// The  value to save to the file.
+    /// 
+    /// 
+    /// The  name for the file.
+    /// 
+    /// 
+    /// The creation collision options. Default is ReplaceExisting.
+    /// 
+    /// 
+    /// The saved  containing the text.
+    /// 
+    /// 
+    /// Exception thrown if the file location or file name are null or empty.
+    /// 
+    public static Task WriteTextToLocalFileAsync(
+        string text,
+        string fileName,
+        CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = ApplicationData.Current.LocalFolder;
+        return folder.WriteTextToFileAsync(text, fileName, options);
+    }
+
+    /// 
+    /// Saves a string value to a  in application local cache folder/>.
+    /// 
+    /// 
+    /// The  value to save to the file.
+    /// 
+    /// 
+    /// The  name for the file.
+    /// 
+    /// 
+    /// The creation collision options. Default is ReplaceExisting.
+    /// 
+    /// 
+    /// The saved  containing the text.
+    /// 
+    /// 
+    /// Exception thrown if the file location or file name are null or empty.
+    /// 
+    public static Task WriteTextToLocalCacheFileAsync(
+        string text,
+        string fileName,
+        CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = ApplicationData.Current.LocalCacheFolder;
+        return folder.WriteTextToFileAsync(text, fileName, options);
+    }
+
+#if !HAS_UNO
+    /// 
+    /// Saves a string value to a  in well known folder/>.
+    /// 
+    /// 
+    /// The well known folder ID to use.
+    /// 
+    /// 
+    /// The  value to save to the file.
+    /// 
+    /// 
+    /// The  name for the file.
+    /// 
+    /// 
+    /// The creation collision options. Default is ReplaceExisting.
+    /// 
+    /// 
+    /// The saved  containing the text.
+    /// 
+    /// 
+    /// Exception thrown if the file location or file name are null or empty.
+    /// 
+    public static Task WriteTextToKnownFolderFileAsync(
+        KnownFolderId knownFolderId,
+        string text,
+        string fileName,
+        CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = GetFolderFromKnownFolderId(knownFolderId);
+        return folder.WriteTextToFileAsync(text, fileName, options);
+    }
+#endif
+
+    /// 
+    /// Saves a string value to a  in the given .
+    /// 
+    /// 
+    /// The  to save the file in.
+    /// 
+    /// 
+    /// The  value to save to the file.
+    /// 
+    /// 
+    /// The  name for the file.
+    /// 
+    /// 
+    /// The creation collision options. Default is ReplaceExisting.
+    /// 
+    /// 
+    /// The saved  containing the text.
+    /// 
+    /// 
+    /// Exception thrown if the file location or file name are null or empty.
+    /// 
+    public static async Task WriteTextToFileAsync(
+        this StorageFolder fileLocation,
+        string text,
+        string fileName,
+        CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+    {
+        if (fileLocation == null)
+        {
+            throw new ArgumentNullException(nameof(fileLocation));
+        }
+
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var storageFile = await fileLocation.CreateFileAsync(fileName, options);
+        await FileIO.WriteTextAsync(storageFile, text);
+
+        return storageFile;
+    }
+
+    /// 
+    /// Saves an array of bytes to a  to application local folder/>.
+    /// 
+    /// 
+    /// The  array to save to the file.
+    /// 
+    /// 
+    /// The  name for the file.
+    /// 
+    /// 
+    /// The creation collision options. Default is ReplaceExisting.
+    /// 
+    /// 
+    /// The saved  containing the bytes.
+    /// 
+    /// 
+    /// Exception thrown if the file location or file name are null or empty.
+    /// 
+    public static Task WriteBytesToLocalFileAsync(
+        byte[] bytes,
+        string fileName,
+        CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = ApplicationData.Current.LocalFolder;
+        return folder.WriteBytesToFileAsync(bytes, fileName, options);
+    }
+
+    /// 
+    /// Saves an array of bytes to a  to application local cache folder/>.
+    /// 
+    /// 
+    /// The  array to save to the file.
+    /// 
+    /// 
+    /// The  name for the file.
+    /// 
+    /// 
+    /// The creation collision options. Default is ReplaceExisting.
+    /// 
+    /// 
+    /// The saved  containing the bytes.
+    /// 
+    /// 
+    /// Exception thrown if the file location or file name are null or empty.
+    /// 
+    public static Task WriteBytesToLocalCacheFileAsync(
+        byte[] bytes,
+        string fileName,
+        CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = ApplicationData.Current.LocalCacheFolder;
+        return folder.WriteBytesToFileAsync(bytes, fileName, options);
+    }
+
+#if !HAS_UNO
+    /// 
+    /// Saves an array of bytes to a  to well known folder/>.
+    /// 
+    /// 
+    /// The well known folder ID to use.
+    /// 
+    /// 
+    /// The  array to save to the file.
+    /// 
+    /// 
+    /// The  name for the file.
+    /// 
+    /// 
+    /// The creation collision options. Default is ReplaceExisting.
+    /// 
+    /// 
+    /// The saved  containing the bytes.
+    /// 
+    /// 
+    /// Exception thrown if the file location or file name are null or empty.
+    /// 
+    public static Task WriteBytesToKnownFolderFileAsync(
+        KnownFolderId knownFolderId,
+        byte[] bytes,
+        string fileName,
+        CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = GetFolderFromKnownFolderId(knownFolderId);
+        return folder.WriteBytesToFileAsync(bytes, fileName, options);
+    }
+#endif
+
+    /// 
+    /// Saves an array of bytes to a  in the given .
+    /// 
+    /// 
+    /// The  to save the file in.
+    /// 
+    /// 
+    /// The  array to save to the file.
+    /// 
+    /// 
+    /// The  name for the file.
+    /// 
+    /// 
+    /// The creation collision options. Default is ReplaceExisting.
+    /// 
+    /// 
+    /// The saved  containing the bytes.
+    /// 
+    /// 
+    /// Exception thrown if the file location or file name are null or empty.
+    /// 
+    public static async Task WriteBytesToFileAsync(
+        this StorageFolder fileLocation,
+        byte[] bytes,
+        string fileName,
+        CreationCollisionOption options = CreationCollisionOption.ReplaceExisting)
+    {
+        if (fileLocation == null)
+        {
+            throw new ArgumentNullException(nameof(fileLocation));
+        }
+
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var storageFile = await fileLocation.CreateFileAsync(fileName, options);
+        await FileIO.WriteBytesAsync(storageFile, bytes);
+
+        return storageFile;
+    }
+
+    /// 
+    /// Gets a string value from a  located in the application installation folder.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  value.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static Task ReadTextFromPackagedFileAsync(string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = Package.Current.InstalledLocation;
+        return folder.ReadTextFromFileAsync(fileName);
+    }
+
+    /// 
+    /// Gets a string value from a  located in the application local cache folder.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  value.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static Task ReadTextFromLocalCacheFileAsync(string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = ApplicationData.Current.LocalCacheFolder;
+        return folder.ReadTextFromFileAsync(fileName);
+    }
+
+    /// 
+    /// Gets a string value from a  located in the application local folder.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  value.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static Task ReadTextFromLocalFileAsync(string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = ApplicationData.Current.LocalFolder;
+        return folder.ReadTextFromFileAsync(fileName);
+    }
+
+#if !HAS_UNO
+    /// 
+    /// Gets a string value from a  located in a well known folder.
+    /// 
+    /// 
+    /// The well known folder ID to use.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  value.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static Task ReadTextFromKnownFoldersFileAsync(
+        KnownFolderId knownFolderId,
+        string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = GetFolderFromKnownFolderId(knownFolderId);
+        return folder.ReadTextFromFileAsync(fileName);
+    }
+#endif
+
+    /// 
+    /// Gets a string value from a  located in the given .
+    /// 
+    /// 
+    /// The  to save the file in.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  value.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static async Task ReadTextFromFileAsync(
+        this StorageFolder fileLocation,
+        string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var file = await fileLocation.GetFileAsync(fileName);
+        return await FileIO.ReadTextAsync(file);
+    }
+
+#if !HAS_UNO
+    /// 
+    /// Gets an array of bytes from a  located in the application installation folder.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  array.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static Task ReadBytesFromPackagedFileAsync(string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = Package.Current.InstalledLocation;
+        return folder.ReadBytesFromFileAsync(fileName);
+    }
+
+    /// 
+    /// Gets an array of bytes from a  located in the application local cache folder.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  array.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static Task ReadBytesFromLocalCacheFileAsync(string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = ApplicationData.Current.LocalCacheFolder;
+        return folder.ReadBytesFromFileAsync(fileName);
+    }
+
+    /// 
+    /// Gets an array of bytes from a  located in the application local folder.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  array.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static Task ReadBytesFromLocalFileAsync(string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = ApplicationData.Current.LocalFolder;
+        return folder.ReadBytesFromFileAsync(fileName);
+    }
+
+    /// 
+    /// Gets an array of bytes from a  located in a well known folder.
+    /// 
+    /// 
+    /// The well known folder ID to use.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  array.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static Task ReadBytesFromKnownFoldersFileAsync(
+        KnownFolderId knownFolderId,
+        string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var folder = GetFolderFromKnownFolderId(knownFolderId);
+        return folder.ReadBytesFromFileAsync(fileName);
+    }
+
+    /// 
+    /// Gets an array of bytes from a  located in the given .
+    /// 
+    /// 
+    /// The  to save the file in.
+    /// 
+    /// 
+    /// The relative  file path.
+    /// 
+    /// 
+    /// The stored  array.
+    /// 
+    /// 
+    /// Exception thrown if the  is null or empty.
+    /// 
+    public static async Task ReadBytesFromFileAsync(
+        this StorageFolder fileLocation,
+        string fileName)
+    {
+        if (string.IsNullOrWhiteSpace(fileName))
+        {
+            throw new ArgumentNullException(nameof(fileName));
+        }
+
+        var file = await fileLocation.GetFileAsync(fileName).AsTask().ConfigureAwait(false);
+        return await file.ReadBytesAsync();
+    }
+
+    /// 
+    /// Gets an array of bytes from a .
+    /// 
+    /// 
+    /// The .
+    /// 
+    /// 
+    /// The stored  array.
+    /// 
+    public static async Task ReadBytesAsync(this StorageFile file)
+    {
+        if (file == null)
+        {
+            throw new ArgumentNullException(nameof(file));
+        }
+
+        using (IRandomAccessStream stream = await file.OpenReadAsync())
+        {
+            using (var reader = new DataReader(stream.GetInputStreamAt(0)))
+            {
+                await reader.LoadAsync((uint)stream.Size);
+                var bytes = new byte[stream.Size];
+                reader.ReadBytes(bytes);
+                return bytes;
+            }
+        }
+    }
+#endif
+
+    /// 
+    /// Gets a value indicating whether a file exists in the current folder.
+    /// 
+    /// 
+    /// The  to look for the file in.
+    /// 
+    /// 
+    /// The  filename of the file to search for. Must include the file extension and is not case-sensitive.
+    /// 
+    /// 
+    /// The , indicating if the subfolders should also be searched through.
+    /// 
+    /// 
+    /// true if the file exists; otherwise, false.
+    /// 
+    public static Task FileExistsAsync(this StorageFolder folder, string fileName, bool isRecursive = false)
+#if HAS_UNO
+        => FileExistsInFolderAsync(folder, fileName);
+#else
+        => isRecursive
+            ? FileExistsInSubtreeAsync(folder, fileName)
+            : FileExistsInFolderAsync(folder, fileName);
+#endif
+
+    /// 
+    /// Gets a value indicating whether a filename is correct or not using the Storage feature.
+    /// 
+    /// The filename to test. Must include the file extension and is not case-sensitive.
+    /// true if the filename is valid; otherwise, false.
+    public static bool IsFileNameValid(string fileName)
+    {
+        var illegalChars = Path.GetInvalidFileNameChars();
+        return fileName.All(c => !illegalChars.Contains(c));
+    }
+
+    /// 
+    /// Gets a value indicating whether a file path is correct or not using the Storage feature.
+    /// 
+    /// The file path to test. Must include the file extension and is not case-sensitive.
+    /// true if the file path is valid; otherwise, false.
+    public static bool IsFilePathValid(string filePath)
+    {
+        var illegalChars = Path.GetInvalidPathChars();
+        return filePath.All(c => !illegalChars.Contains(c));
+    }
+
+    /// 
+    /// Gets a value indicating whether a file exists in the current folder.
+    /// 
+    /// 
+    /// The  to look for the file in.
+    /// 
+    /// 
+    /// The  filename of the file to search for. Must include the file extension and is not case-sensitive.
+    /// 
+    /// 
+    /// true if the file exists; otherwise, false.
+    /// 
+    internal static async Task FileExistsInFolderAsync(StorageFolder folder, string fileName)
+    {
+        var item = await folder.TryGetItemAsync(fileName).AsTask().ConfigureAwait(false);
+        return item != null && item.IsOfType(StorageItemTypes.File);
+    }
+
+#if !HAS_UNO
+    /// 
+    /// Gets a value indicating whether a file exists in the current folder or in one of its subfolders.
+    /// 
+    /// 
+    /// The  to look for the file in.
+    /// 
+    /// 
+    /// The  filename of the file to search for. Must include the file extension and is not case-sensitive.
+    /// 
+    /// 
+    /// true if the file exists; otherwise, false.
+    /// 
+    /// 
+    /// Exception thrown if the  contains a quotation mark.
+    /// 
+    internal static async Task FileExistsInSubtreeAsync(StorageFolder rootFolder, string fileName)
+    {
+        if (fileName.IndexOf('"') >= 0)
+        {
+            throw new ArgumentException(nameof(fileName));
+        }
+
+        var options = new QueryOptions
+        {
+            FolderDepth = FolderDepth.Deep,
+            UserSearchFilter = $"filename:=\"{fileName}\"" // “:=” is the exact-match operator
+        };
+
+        var files = await rootFolder.CreateFileQueryWithOptions(options).GetFilesAsync().AsTask().ConfigureAwait(false);
+        return files.Count > 0;
+    }
+
+    /// 
+    /// Returns a  from a 
+    /// 
+    /// Folder Id
+    /// The 
+    internal static StorageFolder GetFolderFromKnownFolderId(KnownFolderId knownFolderId)
+    {
+        StorageFolder workingFolder;
+
+        switch (knownFolderId)
+        {
+            case KnownFolderId.AppCaptures:
+                workingFolder = KnownFolders.AppCaptures;
+                break;
+            case KnownFolderId.CameraRoll:
+                workingFolder = KnownFolders.CameraRoll;
+                break;
+            case KnownFolderId.DocumentsLibrary:
+                workingFolder = KnownFolders.DocumentsLibrary;
+                break;
+            case KnownFolderId.HomeGroup:
+                workingFolder = KnownFolders.HomeGroup;
+                break;
+            case KnownFolderId.MediaServerDevices:
+                workingFolder = KnownFolders.MediaServerDevices;
+                break;
+            case KnownFolderId.MusicLibrary:
+                workingFolder = KnownFolders.MusicLibrary;
+                break;
+            case KnownFolderId.Objects3D:
+                workingFolder = KnownFolders.Objects3D;
+                break;
+            case KnownFolderId.PicturesLibrary:
+                workingFolder = KnownFolders.PicturesLibrary;
+                break;
+            case KnownFolderId.Playlists:
+                workingFolder = KnownFolders.Playlists;
+                break;
+            case KnownFolderId.RecordedCalls:
+                workingFolder = KnownFolders.RecordedCalls;
+                break;
+            case KnownFolderId.RemovableDevices:
+                workingFolder = KnownFolders.RemovableDevices;
+                break;
+            case KnownFolderId.SavedPictures:
+                workingFolder = KnownFolders.SavedPictures;
+                break;
+            case KnownFolderId.VideosLibrary:
+                workingFolder = KnownFolders.VideosLibrary;
+                break;
+            default:
+                throw new ArgumentOutOfRangeException(nameof(knownFolderId), knownFolderId, null);
+        }
+
+        return workingFolder;
+    }
+#endif
+}
diff --git a/components/Helpers/src/SystemInformation.cs b/components/Helpers/src/SystemInformation.cs
new file mode 100644
index 00000000..56891ad9
--- /dev/null
+++ b/components/Helpers/src/SystemInformation.cs
@@ -0,0 +1,435 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Threading.Tasks;
+using CommunityToolkit.Common.Helpers;
+using Microsoft.UI.Xaml;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.Security.ExchangeActiveSyncProvisioning;
+using Windows.System;
+using Windows.System.Profile;
+using Windows.System.UserProfile;
+using Windows.UI.Core;
+using CommunityToolkit.WinUI.Helpers;
+using CommunityToolkit.Common;
+using CommunityToolkit.WinUI.Helpers.ObjectStorage;
+
+namespace CommunityToolkit.WinUI.Helpers;
+
+/// 
+/// This class provides info about the app and the system.
+/// 
+public sealed class SystemInformation
+{
+    /// 
+    /// The  instance used to save and retrieve application settings.
+    /// 
+    private readonly ApplicationDataStorageHelper _settingsStorage = ApplicationDataStorageHelper.GetCurrent();
+
+    /// 
+    /// The starting time of the current application session (since app launch or last move to foreground).
+    /// 
+    private DateTime _sessionStart;
+
+    /// 
+    /// Initializes a new instance of the  class.
+    /// 
+    private SystemInformation()
+    {
+        ApplicationName = Package.Current.DisplayName;
+        ApplicationVersion = Package.Current.Id.Version;
+
+#if !HAS_UNO
+        try
+        {
+            Culture = GlobalizationPreferences.Languages.Count > 0 ? new CultureInfo(GlobalizationPreferences.Languages[0]) : null;
+        }
+        catch
+        {
+            Culture = null;
+        }
+#endif
+
+        DeviceFamily = AnalyticsInfo.VersionInfo.DeviceFamily;
+
+#if !HAS_UNO
+        ulong version = ulong.Parse(AnalyticsInfo.VersionInfo.DeviceFamilyVersion);
+
+        OperatingSystemVersion = new OSVersion
+        {
+            Major = (ushort)((version & 0xFFFF000000000000L) >> 48),
+            Minor = (ushort)((version & 0x0000FFFF00000000L) >> 32),
+            Build = (ushort)((version & 0x00000000FFFF0000L) >> 16),
+            Revision = (ushort)(version & 0x000000000000FFFFL)
+        };
+
+        OperatingSystemArchitecture = Package.Current.Id.Architecture;
+#endif
+
+        EasClientDeviceInformation deviceInfo = new();
+
+        OperatingSystem = deviceInfo.OperatingSystem;
+        DeviceManufacturer = deviceInfo.SystemManufacturer;
+        DeviceModel = deviceInfo.SystemProductName;
+        IsFirstRun = DetectIfFirstUse();
+        (IsAppUpdated, PreviousVersionInstalled) = DetectIfAppUpdated();
+        FirstUseTime = DetectFirstUseTime();
+        FirstVersionInstalled = DetectFirstVersionInstalled();
+
+        InitializeValuesSetWithTrackAppUse();
+    }
+
+    /// 
+    /// Gets the unique instance of .
+    /// 
+    public static SystemInformation Instance { get; } = new();
+
+    /// 
+    /// Gets the application's name.
+    /// 
+    public string ApplicationName { get; }
+
+    /// 
+    /// Gets the application's version.
+    /// 
+    public PackageVersion ApplicationVersion { get; }
+
+#if !HAS_UNO
+    /// 
+    /// Gets the user's most preferred culture.
+    /// 
+    public CultureInfo? Culture { get; }
+#endif
+
+    /// 
+    /// Gets the device's family.
+    /// 
+    /// Common values include:
+    /// 
+    /// - "Windows.Desktop"+    ///
- "Windows.Mobile"+    ///
- "Windows.Xbox"+    ///
- "Windows.Holographic"+    ///
- "Windows.Team"+    ///
- "Windows.IoT"+    ///
+    /// 
+    /// Prepare your code for other values.
+    /// 
+    public string DeviceFamily { get; }
+
+    /// 
+    /// Gets the operating system's name.
+    /// 
+    public string OperatingSystem { get; }
+
+#if !HAS_UNO
+    /// 
+    /// Gets the operating system's version.
+    /// 
+    public OSVersion OperatingSystemVersion { get; }
+
+    /// 
+    /// Gets the processor architecture.
+    /// 
+    public Windows.System.ProcessorArchitecture OperatingSystemArchitecture { get; }
+#endif
+
+    /// 
+    /// Gets the available memory.
+    /// 
+    public static float AvailableMemory => (float)MemoryManager.AppMemoryUsageLimit / 1024 / 1024;
+
+    /// 
+    /// Gets the device's model.
+    /// Will be empty if the model couldn't be determined (For example: when running in a virtual machine).
+    /// 
+    public string DeviceModel { get; }
+
+    /// 
+    /// Gets the device's manufacturer.
+    /// Will be empty if the manufacturer couldn't be determined (For example: when running in a virtual machine).
+    /// 
+    public string DeviceManufacturer { get; }
+
+    /// 
+    /// Gets a value indicating whether the app is being used for the first time since it was installed.
+    /// Use this to tell if you should do or display something different for the app's first use.
+    /// 
+    public bool IsFirstRun { get; }
+
+    /// 
+    /// Gets a value indicating whether the app is being used for the first time since being upgraded from an older version.
+    /// Use this to tell if you should display details about what has changed.
+    /// 
+    public bool IsAppUpdated { get; }
+
+    /// 
+    /// Gets the first version of the app that was installed.
+    /// This will be the current version if a previous version of the app was installed before accessing this property.
+    /// 
+    public PackageVersion FirstVersionInstalled { get; }
+
+    /// 
+    /// Gets the previous version of the app that was installed.
+    /// This will be the current version if a previous version of the app was installed
+    /// before using  or if the app is not updated.
+    /// 
+    public PackageVersion PreviousVersionInstalled { get; }
+
+    /// 
+    /// Gets the DateTime (in UTC) when the app was launched for the first time.
+    /// 
+    public DateTime FirstUseTime { get; }
+
+    /// 
+    /// Gets the DateTime (in UTC) when the app was last launched, not including this instance.
+    /// Will be  if  has not been called yet.
+    /// 
+    public DateTime LastLaunchTime { get; private set; }
+
+    /// 
+    /// Gets the number of times the app has been launched.
+    /// Will be 0 if  has not been called yet.
+    /// 
+    public long LaunchCount { get; private set; }
+
+    /// 
+    /// Gets the number of times the app has been launched.
+    /// Will be 0 if  has not been called yet.
+    /// 
+    public long TotalLaunchCount { get; private set; }
+
+    /// 
+    /// Gets the DateTime (in UTC) that this instance of the app was launched.
+    /// Will be  if  has not been called yet.
+    /// 
+    public DateTime LaunchTime { get; private set; }
+
+    /// 
+    /// Gets the DateTime (in UTC) when the launch count was last reset.
+    /// Will be  if  has not been called yet.
+    /// 
+    public DateTime LastResetTime { get; private set; }
+
+    /// 
+    /// Gets the length of time this instance of the app has been running.
+    /// Will be  if  has not been called yet.
+    /// 
+    public TimeSpan AppUptime
+    {
+        get
+        {
+            if (LaunchCount > 0)
+            {
+                var subSessionLength = DateTime.UtcNow.Subtract(_sessionStart).Ticks;
+                var uptimeSoFar = _settingsStorage.Read(nameof(AppUptime));
+
+                return new(uptimeSoFar + subSessionLength);
+            }
+
+            return TimeSpan.MinValue;
+        }
+    }
+
+    /// 
+    /// Adds to the record of how long the app has been running.
+    /// Use this to optionally include time spent in background tasks or extended execution.
+    /// 
+    /// The amount to time to add
+    public void AddToAppUptime(TimeSpan duration)
+    {
+        var uptimeSoFar = _settingsStorage.Read(nameof(AppUptime));
+
+        _settingsStorage.Save(nameof(AppUptime), uptimeSoFar + duration.Ticks);
+    }
+
+    /// 
+    /// Resets the launch count.
+    /// 
+    public void ResetLaunchCount()
+    {
+        LastResetTime = DateTime.UtcNow;
+        LaunchCount = 0;
+
+        _settingsStorage.Save(nameof(LastResetTime), LastResetTime.ToFileTimeUtc());
+        _settingsStorage.Save(nameof(LaunchCount), LaunchCount);
+    }
+
+    /// 
+    /// Tracks information about the app's launch.
+    /// 
+    /// Details about the launch request and process.
+    /// The XamlRoot object from your visual tree.
+    public void TrackAppUse(IActivatedEventArgs args, XamlRoot? xamlRoot = null)
+    {
+        if (args.PreviousExecutionState is ApplicationExecutionState.ClosedByUser or ApplicationExecutionState.NotRunning)
+        {
+            LaunchCount = _settingsStorage.Read(nameof(LaunchCount)) + 1;
+            TotalLaunchCount = _settingsStorage.Read(nameof(TotalLaunchCount)) + 1;
+
+            // In case we upgraded the properties, make TotalLaunchCount is correct
+            if (TotalLaunchCount < LaunchCount)
+            {
+                TotalLaunchCount = LaunchCount;
+            }
+
+            _settingsStorage.Save(nameof(LaunchCount), LaunchCount);
+            _settingsStorage.Save(nameof(TotalLaunchCount), TotalLaunchCount);
+
+            LaunchTime = DateTime.UtcNow;
+
+            var lastLaunch = _settingsStorage.Read(nameof(LastLaunchTime));
+
+            LastLaunchTime = lastLaunch != 0
+                ? DateTime.FromFileTimeUtc(lastLaunch)
+                : LaunchTime;
+
+            _settingsStorage.Save(nameof(LastLaunchTime), LaunchTime.ToFileTimeUtc());
+            _settingsStorage.Save(nameof(AppUptime), 0L);
+
+            var lastResetTime = _settingsStorage.Read(nameof(LastResetTime));
+
+            LastResetTime = lastResetTime != 0
+                ? DateTime.FromFileTimeUtc(lastResetTime)
+                : DateTime.MinValue;
+        }
+
+        if (xamlRoot != null)
+        {
+            void XamlRoot_Changed(XamlRoot sender, XamlRootChangedEventArgs e)
+            {
+                UpdateVisibility(sender.IsHostVisible);
+            }
+
+            xamlRoot.Changed -= XamlRoot_Changed;
+            xamlRoot.Changed += XamlRoot_Changed;
+        }
+        else
+        {
+            void App_VisibilityChanged(CoreWindow sender, VisibilityChangedEventArgs e)
+            {
+                UpdateVisibility(e.Visible);
+            }
+
+            var windowForCurrentThread = CoreWindow.GetForCurrentThread();
+            if (windowForCurrentThread != null)
+            {
+                windowForCurrentThread.VisibilityChanged -= App_VisibilityChanged;
+                windowForCurrentThread.VisibilityChanged += App_VisibilityChanged;
+            }
+        }
+    }
+
+    private void UpdateVisibility(bool visible)
+    {
+        if (visible)
+        {
+            _sessionStart = DateTime.UtcNow;
+        }
+        else
+        {
+            var subSessionLength = DateTime.UtcNow.Subtract(_sessionStart).Ticks;
+            var uptimeSoFar = _settingsStorage.Read(nameof(AppUptime));
+
+            _settingsStorage.Save(nameof(AppUptime), uptimeSoFar + subSessionLength);
+        }
+    }
+
+    private bool DetectIfFirstUse()
+    {
+        if (_settingsStorage.KeyExists(nameof(IsFirstRun)))
+        {
+            return false;
+        }
+
+        _settingsStorage.Save(nameof(IsFirstRun), true);
+
+        return true;
+    }
+
+    private (bool IsUpdated, PackageVersion PreviousVersion) DetectIfAppUpdated()
+    {
+        var currentVersion = ApplicationVersion.ToFormattedString();
+
+        // If the "currentVersion" key does not exist, it means that this is the first time this method
+        // is ever called. That is, this is either the first time the app has been launched, or the first
+        // time a previously existing app has run this method (or has run it after a new update of the app).
+        // In this case, save the current version and report the same version as previous version installed.
+        if (!_settingsStorage.KeyExists(nameof(currentVersion)))
+        {
+            _settingsStorage.Save(nameof(currentVersion), currentVersion);
+        }
+        else
+        {
+            var previousVersion = _settingsStorage.Read(nameof(currentVersion));
+
+            // There are two possible cases if the "currentVersion" key exists:
+            //   1) The previous version is different than the current one. This means that the application
+            //      has been updated since the last time this method was called. We can overwrite the saved
+            //      setting for "currentVersion" to bring that value up to date, and return its old value.
+            //   2) The previous version matches the current one: the app has just been reopened without updates.
+            //      In this case we have nothing to do and just return the previous version installed to be the same.
+            if (currentVersion != previousVersion && previousVersion != null)
+            {
+                _settingsStorage.Save(nameof(currentVersion), currentVersion);
+                return (true, previousVersion.ToPackageVersion());
+            }
+        }
+
+        return (false, currentVersion.ToPackageVersion());
+    }
+
+    private DateTime DetectFirstUseTime()
+    {
+        if (_settingsStorage.KeyExists(nameof(FirstUseTime)))
+        {
+            var firstUse = _settingsStorage.Read(nameof(FirstUseTime));
+
+            return DateTime.FromFileTimeUtc(firstUse);
+        }
+
+        DateTime utcNow = DateTime.UtcNow;
+
+        _settingsStorage.Save(nameof(FirstUseTime), utcNow.ToFileTimeUtc());
+
+        return utcNow;
+    }
+
+    private PackageVersion DetectFirstVersionInstalled()
+    {
+        var firstVersionInstalled = _settingsStorage.Read(nameof(FirstVersionInstalled));
+        if (firstVersionInstalled != null)
+        {
+            return firstVersionInstalled.ToPackageVersion();
+        }
+
+        _settingsStorage.Save(nameof(FirstVersionInstalled), ApplicationVersion.ToFormattedString());
+
+        return ApplicationVersion;
+    }
+
+    private void InitializeValuesSetWithTrackAppUse()
+    {
+        LaunchTime = DateTime.MinValue;
+        LaunchCount = 0;
+        TotalLaunchCount = 0;
+        LastLaunchTime = DateTime.MinValue;
+        LastResetTime = DateTime.MinValue;
+    }
+
+    /// 
+    /// Launches the store app so the user can leave a review.
+    /// 
+    /// A  representing the asynchronous operation.
+    /// This method needs to be called from your UI thread.
+    public static Task LaunchStoreForReviewAsync()
+    {
+        return Launcher.LaunchUriAsync(new Uri(string.Format("ms-windows-store://review/?PFN={0}", Package.Current.Id.FamilyName))).AsTask();
+    }
+}