diff --git a/app/MindWork AI Studio/Components/Blocks/Changelog.Logs.cs b/app/MindWork AI Studio/Components/Blocks/Changelog.Logs.cs
index 775386d1..0a166d69 100644
--- a/app/MindWork AI Studio/Components/Blocks/Changelog.Logs.cs	
+++ b/app/MindWork AI Studio/Components/Blocks/Changelog.Logs.cs	
@@ -13,6 +13,7 @@ public partial class Changelog
     
     public static readonly Log[] LOGS = 
     [
+        new (159, "v0.6.3, build 159 (2024-07-03 18:26 UTC)", "v0.6.3.md"),
         new (158, "v0.6.2, build 158 (2024-07-01 18:03 UTC)", "v0.6.2.md"),
         new (157, "v0.6.1, build 157 (2024-06-30 19:00 UTC)", "v0.6.1.md"),
         new (156, "v0.6.0, build 156 (2024-06-30 12:49 UTC)", "v0.6.0.md"),
diff --git a/app/MindWork AI Studio/Components/Pages/Chat.razor.cs b/app/MindWork AI Studio/Components/Pages/Chat.razor.cs
index 53c22aa0..08275bd1 100644
--- a/app/MindWork AI Studio/Components/Pages/Chat.razor.cs	
+++ b/app/MindWork AI Studio/Components/Pages/Chat.razor.cs	
@@ -101,7 +101,7 @@ public partial class Chat : ComponentBase
         // Use the selected provider to get the AI response.
         // By awaiting this line, we wait for the entire
         // content to be streamed.
-        await aiText.CreateFromProviderAsync(this.selectedProvider.UsedProvider.CreateProvider(this.selectedProvider.InstanceName), this.JsRuntime, this.SettingsManager, this.selectedProvider.Model, this.chatThread);
+        await aiText.CreateFromProviderAsync(this.selectedProvider.UsedProvider.CreateProvider(this.selectedProvider.InstanceName, this.selectedProvider.Hostname), this.JsRuntime, this.SettingsManager, this.selectedProvider.Model, this.chatThread);
         
         // Disable the stream state:
         this.isStreaming = false;
diff --git a/app/MindWork AI Studio/Components/Pages/Settings.razor b/app/MindWork AI Studio/Components/Pages/Settings.razor
index fdc51e4b..2a9414e4 100644
--- a/app/MindWork AI Studio/Components/Pages/Settings.razor	
+++ b/app/MindWork AI Studio/Components/Pages/Settings.razor	
@@ -1,4 +1,5 @@
 @page "/settings"
+@using AIStudio.Provider
 
 Settings
 
@@ -11,7 +12,7 @@
                 
                 
                 
-                
+                
             
             
                 #
@@ -24,12 +25,20 @@
                 @context.Num
                 @context.InstanceName
                 @context.UsedProvider
-                @context.Model
+                
+                    @if(context.UsedProvider is not Providers.SELF_HOSTED)
+                        @context.Model
+                    else
+                        @("as selected by provider")
+                
                 
-                    
+                    
+                        Open Dashboard
+                    
+                    
                         Edit
                     
-                    
+                    
                         Delete
                     
                 
diff --git a/app/MindWork AI Studio/Components/Pages/Settings.razor.cs b/app/MindWork AI Studio/Components/Pages/Settings.razor.cs
index 13b06844..e6df7480 100644
--- a/app/MindWork AI Studio/Components/Pages/Settings.razor.cs	
+++ b/app/MindWork AI Studio/Components/Pages/Settings.razor.cs	
@@ -50,6 +50,8 @@ public partial class Settings : ComponentBase
             { x => x.DataInstanceName, provider.InstanceName },
             { x => x.DataProvider, provider.UsedProvider },
             { x => x.DataModel, provider.Model },
+            { x => x.DataHostname, provider.Hostname },
+            { x => x.IsSelfHosted, provider.IsSelfHosted },
             { x => x.IsEditing, true },
         };
 
@@ -81,7 +83,7 @@ public partial class Settings : ComponentBase
         if (dialogResult.Canceled)
             return;
         
-        var providerInstance = provider.UsedProvider.CreateProvider(provider.InstanceName);
+        var providerInstance = provider.UsedProvider.CreateProvider(provider.InstanceName, provider.Hostname);
         var deleteSecretResponse = await this.SettingsManager.DeleteAPIKey(this.JsRuntime, providerInstance);
         if(deleteSecretResponse.Success)
         {
@@ -89,6 +91,15 @@ public partial class Settings : ComponentBase
             await this.SettingsManager.StoreSettings();
         }
     }
+    
+    private string GetProviderDashboardURL(Providers provider) => provider switch
+    {
+        Providers.OPEN_AI => "https://platform.openai.com/usage",
+        Providers.MISTRAL => "https://console.mistral.ai/usage/",
+        Providers.ANTHROPIC => "https://console.anthropic.com/settings/plans",
+        
+        _ => string.Empty,
+    };
 
     #endregion
 }
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/Providers.cs b/app/MindWork AI Studio/Provider/Providers.cs
index 6c8326f2..db99cc3e 100644
--- a/app/MindWork AI Studio/Provider/Providers.cs	
+++ b/app/MindWork AI Studio/Provider/Providers.cs	
@@ -1,6 +1,7 @@
 using AIStudio.Provider.Anthropic;
 using AIStudio.Provider.Mistral;
 using AIStudio.Provider.OpenAI;
+using AIStudio.Provider.SelfHosted;
 
 namespace AIStudio.Provider;
 
@@ -10,9 +11,12 @@ namespace AIStudio.Provider;
 public enum Providers
 {
     NONE,
+    
     OPEN_AI,
     ANTHROPIC,
     MISTRAL,
+    
+    SELF_HOSTED,
 }
 
 /// 
@@ -27,11 +31,14 @@ public static class ExtensionsProvider
     /// The human-readable name of the provider.
     public static string ToName(this Providers provider) => provider switch
     {
+        Providers.NONE => "No provider selected",
+        
         Providers.OPEN_AI => "OpenAI",
         Providers.ANTHROPIC => "Anthropic",
         Providers.MISTRAL => "Mistral",
         
-        Providers.NONE => "No provider selected",
+        Providers.SELF_HOSTED => "Self-hosted",
+        
         _ => "Unknown",
     };
 
@@ -40,13 +47,16 @@ public static class ExtensionsProvider
     /// 
     /// The provider value.
     /// The used instance name.
+    /// The hostname of the provider.
     /// The provider instance.
-    public static IProvider CreateProvider(this Providers provider, string instanceName) => provider switch
+    public static IProvider CreateProvider(this Providers provider, string instanceName, string hostname = "http://localhost:1234") => provider switch
     {
         Providers.OPEN_AI => new ProviderOpenAI { InstanceName = instanceName },
         Providers.ANTHROPIC => new ProviderAnthropic { InstanceName = instanceName },
         Providers.MISTRAL => new ProviderMistral { InstanceName = instanceName },
         
+        Providers.SELF_HOSTED => new ProviderSelfHosted(hostname) { InstanceName = instanceName },
+        
         _ => new NoProvider(),
     };
 }
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/SelfHosted/ChatRequest.cs b/app/MindWork AI Studio/Provider/SelfHosted/ChatRequest.cs
new file mode 100644
index 00000000..74b3f089
--- /dev/null
+++ b/app/MindWork AI Studio/Provider/SelfHosted/ChatRequest.cs	
@@ -0,0 +1,16 @@
+namespace AIStudio.Provider.SelfHosted;
+
+/// 
+/// The chat request model.
+/// 
+/// Which model to use for chat completion.
+/// The chat messages.
+/// Whether to stream the chat completion.
+/// The maximum number of tokens to generate.
+public readonly record struct ChatRequest(
+    string Model,
+    IList Messages,
+    bool Stream,
+    
+    int MaxTokens
+);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/SelfHosted/Message.cs b/app/MindWork AI Studio/Provider/SelfHosted/Message.cs
new file mode 100644
index 00000000..e4ecc70a
--- /dev/null
+++ b/app/MindWork AI Studio/Provider/SelfHosted/Message.cs	
@@ -0,0 +1,8 @@
+namespace AIStudio.Provider.SelfHosted;
+
+/// 
+/// Chat message model.
+/// 
+/// The text content of the message.
+/// The role of the message.
+public readonly record struct Message(string Content, string Role);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/SelfHosted/ModelsResponse.cs b/app/MindWork AI Studio/Provider/SelfHosted/ModelsResponse.cs
new file mode 100644
index 00000000..8ea8fb57
--- /dev/null
+++ b/app/MindWork AI Studio/Provider/SelfHosted/ModelsResponse.cs	
@@ -0,0 +1,5 @@
+namespace AIStudio.Provider.SelfHosted;
+
+public readonly record struct ModelsResponse(string Object, Model[] Data);
+
+public readonly record struct Model(string Id, string Object, string OwnedBy);
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs
new file mode 100644
index 00000000..82a458e3
--- /dev/null
+++ b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs	
@@ -0,0 +1,162 @@
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Text.Json;
+
+using AIStudio.Chat;
+using AIStudio.Provider.OpenAI;
+using AIStudio.Settings;
+
+namespace AIStudio.Provider.SelfHosted;
+
+public sealed class ProviderSelfHosted(string hostname) : BaseProvider($"{hostname}/v1/"), IProvider
+{
+    private static readonly JsonSerializerOptions JSON_SERIALIZER_OPTIONS = new()
+    {
+        PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower,
+    };
+
+    #region Implementation of IProvider
+
+    public string Id => "Self-hosted";
+    
+    public string InstanceName { get; set; } = "Self-hosted";
+    
+    public async IAsyncEnumerable StreamChatCompletion(IJSRuntime jsRuntime, SettingsManager settings, Provider.Model chatModel, ChatThread chatThread, [EnumeratorCancellation] CancellationToken token = default)
+    {
+        // Prepare the system prompt:
+        var systemPrompt = new Message
+        {
+            Role = "system",
+            Content = chatThread.SystemPrompt,
+        };
+        
+        // Prepare the OpenAI HTTP chat request:
+        var providerChatRequest = JsonSerializer.Serialize(new ChatRequest
+        {
+            Model = (await this.GetTextModels(jsRuntime, settings, token: token)).First().Id,
+            
+            // Build the messages:
+            // - First of all the system prompt
+            // - Then none-empty user and AI messages
+            Messages = [systemPrompt, ..chatThread.Blocks.Where(n => n.ContentType is ContentType.TEXT && !string.IsNullOrWhiteSpace((n.Content as ContentText)?.Text)).Select(n => new Message
+            {
+                Role = n.Role switch
+                {
+                    ChatRole.USER => "user",
+                    ChatRole.AI => "assistant",
+                    ChatRole.SYSTEM => "system",
+
+                    _ => "user",
+                },
+
+                Content = n.Content switch
+                {
+                    ContentText text => text.Text,
+                    _ => string.Empty,
+                }
+            }).ToList()],
+            
+            // Right now, we only support streaming completions:
+            Stream = true,
+            MaxTokens = -1,
+        }, JSON_SERIALIZER_OPTIONS);
+
+        // Build the HTTP post request:
+        var request = new HttpRequestMessage(HttpMethod.Post, "chat/completions");
+        
+        // Set the content:
+        request.Content = new StringContent(providerChatRequest, Encoding.UTF8, "application/json");
+        
+        // Send the request with the ResponseHeadersRead option.
+        // This allows us to read the stream as soon as the headers are received.
+        // This is important because we want to stream the responses.
+        var response = await this.httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token);
+        
+        // Open the response stream:
+        var providerStream = await response.Content.ReadAsStreamAsync(token);
+        
+        // Add a stream reader to read the stream, line by line:
+        var streamReader = new StreamReader(providerStream);
+        
+        // Read the stream, line by line:
+        while(!streamReader.EndOfStream)
+        {
+            // Check if the token is cancelled:
+            if(token.IsCancellationRequested)
+                yield break;
+            
+            // Read the next line:
+            var line = await streamReader.ReadLineAsync(token);
+            
+            // Skip empty lines:
+            if(string.IsNullOrWhiteSpace(line))
+                continue;
+            
+            // Skip lines that do not start with "data: ". Regard
+            // to the specification, we only want to read the data lines:
+            if(!line.StartsWith("data: ", StringComparison.InvariantCulture))
+                continue;
+
+            // Check if the line is the end of the stream:
+            if (line.StartsWith("data: [DONE]", StringComparison.InvariantCulture))
+                yield break;
+
+            ResponseStreamLine providerResponse;
+            try
+            {
+                // We know that the line starts with "data: ". Hence, we can
+                // skip the first 6 characters to get the JSON data after that.
+                var jsonData = line[6..];
+                
+                // Deserialize the JSON data:
+                providerResponse = JsonSerializer.Deserialize(jsonData, JSON_SERIALIZER_OPTIONS);
+            }
+            catch
+            {
+                // Skip invalid JSON data:
+                continue;
+            }    
+            
+            // Skip empty responses:
+            if(providerResponse == default || providerResponse.Choices.Count == 0)
+                continue;
+            
+            // Yield the response:
+            yield return providerResponse.Choices[0].Delta.Content;
+        }
+    }
+
+    #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
+    /// 
+    public async IAsyncEnumerable StreamImageCompletion(IJSRuntime jsRuntime, SettingsManager settings, Provider.Model imageModel, string promptPositive, string promptNegative = FilterOperator.String.Empty, ImageURL referenceImageURL = default, [EnumeratorCancellation] CancellationToken token = default)
+    {
+        yield break;
+    }
+    #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
+
+
+    public async Task> GetTextModels(IJSRuntime jsRuntime, SettingsManager settings, string? apiKeyProvisional = null, CancellationToken token = default)
+    {
+        var request = new HttpRequestMessage(HttpMethod.Get, "models");
+        var response = await this.httpClient.SendAsync(request, token);
+        if(!response.IsSuccessStatusCode)
+            return [];
+
+        var modelResponse = await response.Content.ReadFromJsonAsync(token);
+        if (modelResponse.Data.Length > 1)
+            Console.WriteLine("Warning: multiple models found; using the first one.");
+        
+        var firstModel = modelResponse.Data.First();
+        return [ new Provider.Model(firstModel.Id) ];
+    }
+
+    #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
+    /// 
+    public Task> GetImageModels(IJSRuntime jsRuntime, SettingsManager settings, string? apiKeyProvisional = null, CancellationToken token = default)
+    {
+        return Task.FromResult(Enumerable.Empty());
+    }
+    #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
+
+    #endregion
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Settings/Data.cs b/app/MindWork AI Studio/Settings/Data.cs
index 8052c271..8ce5120b 100644
--- a/app/MindWork AI Studio/Settings/Data.cs	
+++ b/app/MindWork AI Studio/Settings/Data.cs	
@@ -9,7 +9,7 @@ public sealed class Data
     /// The version of the settings file. Allows us to upgrade the settings
     /// when a new version is available.
     /// 
-    public Version Version { get; init; } = Version.V1;
+    public Version Version { get; init; } = Version.V2;
 
     /// 
     /// List of configured providers.
diff --git a/app/MindWork AI Studio/Settings/Provider.cs b/app/MindWork AI Studio/Settings/Provider.cs
index d1f6194a..48133267 100644
--- a/app/MindWork AI Studio/Settings/Provider.cs	
+++ b/app/MindWork AI Studio/Settings/Provider.cs	
@@ -9,8 +9,10 @@ namespace AIStudio.Settings;
 /// The provider's ID.
 /// The provider's instance name. Useful for multiple instances of the same provider, e.g., to distinguish between different OpenAI API keys.
 /// The provider used.
+/// Whether the provider is self-hosted.
+/// The hostname of the provider. Useful for self-hosted providers.
 /// The LLM model to use for chat.
-public readonly record struct Provider(uint Num, string Id, string InstanceName, Providers UsedProvider, Model Model)
+public readonly record struct Provider(uint Num, string Id, string InstanceName, Providers UsedProvider, Model Model, bool IsSelfHosted = false, string Hostname = "http://localhost:1234")
 {
     #region Overrides of ValueType
 
@@ -21,6 +23,9 @@ public readonly record struct Provider(uint Num, string Id, string InstanceName,
     /// A string that represents the current provider in a human-readable format.
     public override string ToString()
     {
+        if(this.IsSelfHosted)
+            return $"{this.InstanceName} ({this.UsedProvider.ToName()}, {this.Hostname}, {this.Model})";
+
         return $"{this.InstanceName} ({this.UsedProvider.ToName()}, {this.Model})";
     }
 
diff --git a/app/MindWork AI Studio/Settings/ProviderDialog.razor b/app/MindWork AI Studio/Settings/ProviderDialog.razor
index 62fdad3b..82bb5fc1 100644
--- a/app/MindWork AI Studio/Settings/ProviderDialog.razor	
+++ b/app/MindWork AI Studio/Settings/ProviderDialog.razor	
@@ -4,6 +4,53 @@
 
     
         
+            
+                @* ReSharper disable once CSharpWarnings::CS8974 *@
+                
+                    @foreach (Providers provider in Enum.GetValues(typeof(Providers)))
+                    {
+                        @provider
+                    }
+                
+                Create account
+            
+            
+            @* ReSharper disable once CSharpWarnings::CS8974 *@
+            
+            
+            
+
+            
+                Load
+                
+                    @foreach (var model in this.availableModels)
+                    {
+                        @model
+                    }
+                
+            
+
             @* ReSharper disable once CSharpWarnings::CS8974 *@
             
             
-            @* ReSharper disable once CSharpWarnings::CS8974 *@
-            
-                @foreach (Providers provider in Enum.GetValues(typeof(Providers)))
-                {
-                    @provider
-                }
-            
-            
-            @* ReSharper disable once CSharpWarnings::CS8974 *@
-            
-
-            
-                Reload
-                
-                    @foreach (var model in this.availableModels)
-                    {
-                        @model
-                    }
-                
-            
-            
         
 
         @if (this.dataIssues.Any())
diff --git a/app/MindWork AI Studio/Settings/ProviderDialog.razor.cs b/app/MindWork AI Studio/Settings/ProviderDialog.razor.cs
index 012930b5..3febabcb 100644
--- a/app/MindWork AI Studio/Settings/ProviderDialog.razor.cs	
+++ b/app/MindWork AI Studio/Settings/ProviderDialog.razor.cs	
@@ -32,6 +32,18 @@ public partial class ProviderDialog : ComponentBase
     [Parameter]
     public string DataInstanceName { get; set; } = string.Empty;
     
+    /// 
+    /// The chosen hostname for self-hosted providers.
+    /// 
+    [Parameter]
+    public string DataHostname { get; set; } = string.Empty;
+    
+    /// 
+    /// Is this provider self-hosted?
+    /// 
+    [Parameter]
+    public bool IsSelfHosted { get; set; }
+    
     /// 
     /// The provider to use.
     /// 
@@ -99,7 +111,8 @@ public partial class ProviderDialog : ComponentBase
                 this.dataAPIKey = requestedSecret.Secret;
                 
                 // Now, we try to load the list of available models:
-                await this.ReloadModels();
+                if(this.DataProvider is not Providers.SELF_HOSTED)
+                    await this.ReloadModels();
             }
             else
             {
@@ -142,6 +155,8 @@ public partial class ProviderDialog : ComponentBase
             InstanceName = this.DataInstanceName,
             UsedProvider = this.DataProvider,
             Model = this.DataModel,
+            IsSelfHosted = this.DataProvider is Providers.SELF_HOSTED,
+            Hostname = this.DataHostname,
         };
         
         // We need to instantiate the provider to store the API key:
@@ -169,33 +184,49 @@ public partial class ProviderDialog : ComponentBase
     
     private string? ValidatingModel(Model model)
     {
+        if(this.DataProvider is Providers.SELF_HOSTED)
+            return null;
+        
         if (model == default)
             return "Please select a model.";
         
         return null;
     }
     
-    [GeneratedRegex("^[a-zA-Z0-9 ]+$")]
+    [GeneratedRegex(@"^[a-zA-Z0-9\-_. ]+$")]
     private static partial Regex InstanceNameRegex();
     
+    private static readonly string[] RESERVED_NAMES = { "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" };
+    
     private string? ValidatingInstanceName(string instanceName)
     {
-        if(string.IsNullOrWhiteSpace(instanceName))
+        if (string.IsNullOrWhiteSpace(instanceName))
             return "Please enter an instance name.";
         
-        if(instanceName.StartsWith(' '))
-            return "The instance name must not start with a space.";
+        if (instanceName.StartsWith(' ') || instanceName.StartsWith('.'))
+            return "The instance name must not start with a space or a dot.";
         
-        if(instanceName.EndsWith(' '))
-            return "The instance name must not end with a space.";
+        if (instanceName.EndsWith(' ') || instanceName.EndsWith('.'))
+            return "The instance name must not end with a space or a dot.";
+        
+        if (instanceName.StartsWith('-') || instanceName.StartsWith('_'))
+            return "The instance name must not start with a hyphen or an underscore.";
+        
+        if (instanceName.Length > 255)
+            return "The instance name must not exceed 255 characters.";
         
-        // The instance name must only contain letters, numbers, and spaces:
         if (!InstanceNameRegex().IsMatch(instanceName))
-            return "The instance name must only contain letters, numbers, and spaces.";
+            return "The instance name must only contain letters, numbers, spaces, hyphens, underscores, and dots.";
         
-        if(instanceName.Contains("  "))
+        if (instanceName.Contains("  "))
             return "The instance name must not contain consecutive spaces.";
         
+        if (RESERVED_NAMES.Contains(instanceName.ToUpperInvariant()))
+            return "This name is reserved and cannot be used.";
+        
+        if (instanceName.Any(c => Path.GetInvalidFileNameChars().Contains(c)))
+            return "The instance name contains invalid characters.";
+        
         // The instance name must be unique:
         var lowerInstanceName = instanceName.ToLowerInvariant();
         if (lowerInstanceName != this.dataEditingPreviousInstanceName && this.UsedInstanceNames.Contains(lowerInstanceName))
@@ -206,6 +237,9 @@ public partial class ProviderDialog : ComponentBase
     
     private string? ValidatingAPIKey(string apiKey)
     {
+        if(this.DataProvider is Providers.SELF_HOSTED)
+            return null;
+        
         if(!string.IsNullOrWhiteSpace(this.dataAPIKeyStorageIssue))
             return this.dataAPIKeyStorageIssue;
 
@@ -215,13 +249,28 @@ public partial class ProviderDialog : ComponentBase
         return null;
     }
 
-    private void Cancel() => this.MudDialog.Cancel();
+    private string? ValidatingHostname(string hostname)
+    {
+        if(this.DataProvider != Providers.SELF_HOSTED)
+            return null;
+        
+        if(string.IsNullOrWhiteSpace(hostname))
+            return "Please enter a hostname, e.g., http://localhost:1234";
+        
+        if(!hostname.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase) && !hostname.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
+            return "The hostname must start with either http:// or https://";
 
-    private bool CanLoadModels => !string.IsNullOrWhiteSpace(this.dataAPIKey) && this.DataProvider != Providers.NONE && !string.IsNullOrWhiteSpace(this.DataInstanceName);
+        if(!Uri.TryCreate(hostname, UriKind.Absolute, out _))
+            return "The hostname is not a valid HTTP(S) URL.";
+        
+        return null;
+    }
+
+    private void Cancel() => this.MudDialog.Cancel();
     
     private async Task ReloadModels()
     {
-        var provider = this.DataProvider.CreateProvider(this.DataInstanceName);
+        var provider = this.DataProvider.CreateProvider("temp");
         if(provider is NoProvider)
             return;
 
@@ -233,4 +282,19 @@ public partial class ProviderDialog : ComponentBase
         this.availableModels.Clear();
         this.availableModels.AddRange(orderedModels);
     }
+    
+    private bool CanLoadModels => !string.IsNullOrWhiteSpace(this.dataAPIKey) && this.DataProvider != Providers.NONE && this.DataProvider != Providers.SELF_HOSTED;
+    
+    private bool IsCloudProvider => this.DataProvider is not Providers.SELF_HOSTED;
+    
+    private bool IsSelfHostedOrNone => this.DataProvider is Providers.SELF_HOSTED or Providers.NONE;
+
+    private string GetProviderCreationURL() => this.DataProvider switch
+    {
+        Providers.OPEN_AI => "https://platform.openai.com/signup",
+        Providers.MISTRAL => "https://console.mistral.ai/",
+        Providers.ANTHROPIC => "https://console.anthropic.com/dashboard",
+        
+        _ => string.Empty,
+    };
 }
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Settings/SettingsManager.cs b/app/MindWork AI Studio/Settings/SettingsManager.cs
index 4353056e..4a5d2991 100644
--- a/app/MindWork AI Studio/Settings/SettingsManager.cs	
+++ b/app/MindWork AI Studio/Settings/SettingsManager.cs	
@@ -103,7 +103,7 @@ public sealed class SettingsManager
         if(loadedConfiguration is null)
             return;
         
-        this.ConfigurationData = loadedConfiguration;
+        this.ConfigurationData = SettingsMigrations.Migrate(loadedConfiguration);
     }
 
     /// 
diff --git a/app/MindWork AI Studio/Settings/SettingsMigrations.cs b/app/MindWork AI Studio/Settings/SettingsMigrations.cs
new file mode 100644
index 00000000..e5783787
--- /dev/null
+++ b/app/MindWork AI Studio/Settings/SettingsMigrations.cs	
@@ -0,0 +1,39 @@
+namespace AIStudio.Settings;
+
+public static class SettingsMigrations
+{
+    public static Data Migrate(Data previousData)
+    {
+        switch (previousData.Version)
+        {
+            case Version.V1:
+                return MigrateFromV1(previousData);
+            
+            default:
+                Console.WriteLine("No migration needed.");
+                return previousData;
+        }
+    }
+
+    private static Data MigrateFromV1(Data previousData)
+    {
+        //
+        // Summary:
+        // In v1 we had no self-hosted providers. Thus, we had no hostnames.
+        //
+
+        Console.WriteLine("Migrating from v1 to v2...");
+        return new()
+        {
+            Version = Version.V2,
+            
+            Providers = previousData.Providers.Select(provider => provider with { IsSelfHosted = false, Hostname = "" }).ToList(),
+            
+            EnableSpellchecking = previousData.EnableSpellchecking,
+            IsSavingEnergy = previousData.IsSavingEnergy,
+            NextProviderNum = previousData.NextProviderNum,
+            ShortcutSendBehavior = previousData.ShortcutSendBehavior,
+            UpdateBehavior = previousData.UpdateBehavior,
+        };
+    }
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Settings/Version.cs b/app/MindWork AI Studio/Settings/Version.cs
index 047289ea..04e54efd 100644
--- a/app/MindWork AI Studio/Settings/Version.cs	
+++ b/app/MindWork AI Studio/Settings/Version.cs	
@@ -7,5 +7,7 @@ namespace AIStudio.Settings;
 public enum Version
 {
     UNKNOWN,
+    
     V1,
+    V2,
 }
\ No newline at end of file
diff --git a/app/MindWork AI Studio/wwwroot/changelog/v0.6.3.md b/app/MindWork AI Studio/wwwroot/changelog/v0.6.3.md
new file mode 100644
index 00000000..71c29aec
--- /dev/null
+++ b/app/MindWork AI Studio/wwwroot/changelog/v0.6.3.md	
@@ -0,0 +1,8 @@
+# v0.6.3, build 159 (2024-07-03 18:26 UTC)
+- Added possibility to configure a self-hosted or local provider.
+- Added settings migration processor to handle settings migration from previous versions.
+- Added links to create an account for the selected provider in the provider dialog.
+- Added links to each provider's dashboard to the settings page.
+- Added self-hosted and local providers.
+- Improved instance name validation.
+- Optimized the provider dialog: changed the layout to improve usability.
\ No newline at end of file
diff --git a/metadata.txt b/metadata.txt
index 887fb2dc..6d8edecc 100644
--- a/metadata.txt
+++ b/metadata.txt
@@ -1,9 +1,9 @@
-0.6.2
-2024-07-01 18:08:01 UTC
-158
+0.6.3
+2024-07-03 18:26:31 UTC
+159
 8.0.206 (commit bb12410699)
 8.0.6 (commit 3b8b000a0e)
 1.79.0 (commit 129f3b996)
 6.20.0
 1.6.1
-c86a9e32c12, release
+ac6748e9eb5, release
diff --git a/runtime/Cargo.lock b/runtime/Cargo.lock
index a60a30a8..24bdacd5 100644
--- a/runtime/Cargo.lock
+++ b/runtime/Cargo.lock
@@ -2313,7 +2313,7 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 
 [[package]]
 name = "mindwork-ai-studio"
-version = "0.6.2"
+version = "0.6.3"
 dependencies = [
  "arboard",
  "flexi_logger",
diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml
index c4da1020..cb4728b8 100644
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "mindwork-ai-studio"
-version = "0.6.2"
+version = "0.6.3"
 edition = "2021"
 description = "MindWork AI Studio"
 authors = ["Thorsten Sommer"]
diff --git a/runtime/tauri.conf.json b/runtime/tauri.conf.json
index 590d1c7c..07af8486 100644
--- a/runtime/tauri.conf.json
+++ b/runtime/tauri.conf.json
@@ -6,7 +6,7 @@
   },
   "package": {
     "productName": "MindWork AI Studio",
-	"version": "0.6.2"
+	"version": "0.6.3"
   },
   "tauri": {
     "allowlist": {