(this TBuilder builder)
+ where TBuilder : IHostApplicationBuilder {
+ builder.Services.AddHealthChecks()
+ // Add a default liveness check to ensure app is responsive
+ .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]);
+
+ return builder;
+ }
+
+ public static WebApplication MapDefaultEndpoints(this WebApplication app) {
+ // Adding health checks endpoints to applications in non-development environments has security implications.
+ // See https://aka.ms/dotnet/aspire/healthchecks for details before enabling these endpoints in non-development environments.
+ if (app.Environment.IsDevelopment()) {
+ // All health checks must pass for app to be considered ready to accept traffic after starting
+ app.MapHealthChecks("/health");
+
+ // Only health checks tagged with the "live" tag must pass for app to be considered alive
+ app.MapHealthChecks("/alive", new HealthCheckOptions {
+ Predicate = r => r.Tags.Contains("live")
+ });
+ }
+
+ return app;
+ }
+}
\ No newline at end of file
diff --git a/src/Portfolio.Shared/Portfolio.Shared.csproj b/src/Portfolio.Shared/Portfolio.Shared.csproj
new file mode 100644
index 0000000..6a8950a
--- /dev/null
+++ b/src/Portfolio.Shared/Portfolio.Shared.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net9.0
+ enable
+ enable
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Portfolio.Web/Components/App.razor b/src/Portfolio.Web/Components/App.razor
new file mode 100644
index 0000000..939e292
--- /dev/null
+++ b/src/Portfolio.Web/Components/App.razor
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Portfolio.Web/Components/Layout/MainLayout.razor b/src/Portfolio.Web/Components/Layout/MainLayout.razor
new file mode 100644
index 0000000..e3b2918
--- /dev/null
+++ b/src/Portfolio.Web/Components/Layout/MainLayout.razor
@@ -0,0 +1,23 @@
+@inherits LayoutComponentBase
+
+
+
+
+
+
+
+
+ @Body
+
+
+
+
+
+ An unhandled error has occurred.
+
Reload
+
🗙
+
\ No newline at end of file
diff --git a/src/Portfolio.Web/Components/Layout/MainLayout.razor.css b/src/Portfolio.Web/Components/Layout/MainLayout.razor.css
new file mode 100644
index 0000000..38d1f25
--- /dev/null
+++ b/src/Portfolio.Web/Components/Layout/MainLayout.razor.css
@@ -0,0 +1,98 @@
+.page {
+ position: relative;
+ display: flex;
+ flex-direction: column;
+}
+
+main {
+ flex: 1;
+}
+
+.sidebar {
+ background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
+}
+
+.top-row {
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #d6d5d5;
+ justify-content: flex-end;
+ height: 3.5rem;
+ display: flex;
+ align-items: center;
+}
+
+ .top-row ::deep a, .top-row ::deep .btn-link {
+ white-space: nowrap;
+ margin-left: 1.5rem;
+ text-decoration: none;
+ }
+
+ .top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
+ text-decoration: underline;
+ }
+
+ .top-row ::deep a:first-child {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+
+@media (max-width: 640.98px) {
+ .top-row {
+ justify-content: space-between;
+ }
+
+ .top-row ::deep a, .top-row ::deep .btn-link {
+ margin-left: 0;
+ }
+}
+
+@media (min-width: 641px) {
+ .page {
+ flex-direction: row;
+ }
+
+ .sidebar {
+ width: 250px;
+ height: 100vh;
+ position: sticky;
+ top: 0;
+ }
+
+ .top-row {
+ position: sticky;
+ top: 0;
+ z-index: 1;
+ }
+
+ .top-row.auth ::deep a:first-child {
+ flex: 1;
+ text-align: right;
+ width: 0;
+ }
+
+ .top-row, article {
+ padding-left: 2rem !important;
+ padding-right: 1.5rem !important;
+ }
+}
+
+#blazor-error-ui {
+ color-scheme: light only;
+ background: lightyellow;
+ bottom: 0;
+ box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
+ box-sizing: border-box;
+ display: none;
+ left: 0;
+ padding: 0.6rem 1.25rem 0.7rem 1.25rem;
+ position: fixed;
+ width: 100%;
+ z-index: 1000;
+}
+
+ #blazor-error-ui .dismiss {
+ cursor: pointer;
+ position: absolute;
+ right: 0.75rem;
+ top: 0.5rem;
+ }
diff --git a/src/Portfolio.Web/Components/Layout/NavMenu.razor b/src/Portfolio.Web/Components/Layout/NavMenu.razor
new file mode 100644
index 0000000..0b37b9d
--- /dev/null
+++ b/src/Portfolio.Web/Components/Layout/NavMenu.razor
@@ -0,0 +1,29 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Portfolio.Web/Components/Layout/NavMenu.razor.css b/src/Portfolio.Web/Components/Layout/NavMenu.razor.css
new file mode 100644
index 0000000..a2aeace
--- /dev/null
+++ b/src/Portfolio.Web/Components/Layout/NavMenu.razor.css
@@ -0,0 +1,105 @@
+.navbar-toggler {
+ appearance: none;
+ cursor: pointer;
+ width: 3.5rem;
+ height: 2.5rem;
+ color: white;
+ position: absolute;
+ top: 0.5rem;
+ right: 1rem;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+ background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
+}
+
+.navbar-toggler:checked {
+ background-color: rgba(255, 255, 255, 0.5);
+}
+
+.top-row {
+ min-height: 3.5rem;
+ background-color: rgba(0,0,0,0.4);
+}
+
+.navbar-brand {
+ font-size: 1.1rem;
+}
+
+.bi {
+ display: inline-block;
+ position: relative;
+ width: 1.25rem;
+ height: 1.25rem;
+ margin-right: 0.75rem;
+ top: -1px;
+ background-size: cover;
+}
+
+.bi-house-door-fill-nav-menu {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
+}
+
+.bi-plus-square-fill-nav-menu {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
+}
+
+.bi-list-nested-nav-menu {
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
+}
+
+.nav-item {
+ font-size: 0.9rem;
+ padding-bottom: 0.5rem;
+}
+
+ .nav-item:first-of-type {
+ padding-top: 1rem;
+ }
+
+ .nav-item:last-of-type {
+ padding-bottom: 1rem;
+ }
+
+ .nav-item ::deep .nav-link {
+ color: #d7d7d7;
+ background: none;
+ border: none;
+ border-radius: 4px;
+ height: 3rem;
+ display: flex;
+ align-items: center;
+ line-height: 3rem;
+ width: 100%;
+ }
+
+.nav-item ::deep a.active {
+ background-color: rgba(255,255,255,0.37);
+ color: white;
+}
+
+.nav-item ::deep .nav-link:hover {
+ background-color: rgba(255,255,255,0.1);
+ color: white;
+}
+
+.nav-scrollable {
+ display: none;
+}
+
+.navbar-toggler:checked ~ .nav-scrollable {
+ display: block;
+}
+
+@media (min-width: 641px) {
+ .navbar-toggler {
+ display: none;
+ }
+
+ .nav-scrollable {
+ /* Never collapse the sidebar for wide screens */
+ display: block;
+
+ /* Allow sidebar to scroll for tall menus */
+ height: calc(100vh - 3.5rem);
+ overflow-y: auto;
+ }
+}
diff --git a/src/Portfolio.Web/Components/Pages/Counter.razor b/src/Portfolio.Web/Components/Pages/Counter.razor
new file mode 100644
index 0000000..15c11c3
--- /dev/null
+++ b/src/Portfolio.Web/Components/Pages/Counter.razor
@@ -0,0 +1,19 @@
+@page "/counter"
+@rendermode InteractiveServer
+
+Counter
+
+Counter
+
+Current count: @currentCount
+
+Click me
+
+@code {
+ private int currentCount = 0;
+
+ private void IncrementCount() {
+ currentCount++;
+ }
+
+}
\ No newline at end of file
diff --git a/src/Portfolio.Web/Components/Pages/Error.razor b/src/Portfolio.Web/Components/Pages/Error.razor
new file mode 100644
index 0000000..06de831
--- /dev/null
+++ b/src/Portfolio.Web/Components/Pages/Error.razor
@@ -0,0 +1,35 @@
+@page "/Error"
+@using System.Diagnostics
+
+Error
+
+Error.
+An error occurred while processing your request.
+
+@if (ShowRequestId) {
+
+ Request ID: @RequestId
+
+}
+
+Development Mode
+
+ Swapping to Development environment will display more detailed information about the error that occurred.
+
+
+ The Development environment shouldn't be enabled for deployed applications.
+ It can result in displaying sensitive information from exceptions to end users.
+ For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
+ and restarting the app.
+
+
+@code{
+ [CascadingParameter] private HttpContext? HttpContext { get; set; }
+
+ private string? RequestId { get; set; }
+ private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
+
+ protected override void OnInitialized() =>
+ RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
+
+}
\ No newline at end of file
diff --git a/src/Portfolio.Web/Components/Pages/Home.razor b/src/Portfolio.Web/Components/Pages/Home.razor
new file mode 100644
index 0000000..dfcdf75
--- /dev/null
+++ b/src/Portfolio.Web/Components/Pages/Home.razor
@@ -0,0 +1,7 @@
+@page "/"
+
+Home
+
+Hello, world!
+
+Welcome to your new app.
\ No newline at end of file
diff --git a/src/Portfolio.Web/Components/Pages/Weather.razor b/src/Portfolio.Web/Components/Pages/Weather.razor
new file mode 100644
index 0000000..f8204c6
--- /dev/null
+++ b/src/Portfolio.Web/Components/Pages/Weather.razor
@@ -0,0 +1,61 @@
+@page "/weather"
+@attribute [StreamRendering]
+
+Weather
+
+Weather
+
+This component demonstrates showing data.
+
+@if (forecasts == null) {
+
+ Loading...
+
+}
+else {
+
+
+
+ Date
+ Temp. (C)
+ Temp. (F)
+ Summary
+
+
+
+ @foreach (var forecast in forecasts) {
+
+ @forecast.Date.ToShortDateString()
+ @forecast.TemperatureC
+ @forecast.TemperatureF
+ @forecast.Summary
+
+ }
+
+
+}
+
+@code {
+ private WeatherForecast[]? forecasts;
+
+ protected override async Task OnInitializedAsync() {
+ // Simulate asynchronous loading to demonstrate streaming rendering
+ await Task.Delay(500);
+
+ var startDate = DateOnly.FromDateTime(DateTime.Now);
+ var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
+ forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast {
+ Date = startDate.AddDays(index),
+ TemperatureC = Random.Shared.Next(-20, 55),
+ Summary = summaries[Random.Shared.Next(summaries.Length)]
+ }).ToArray();
+ }
+
+ private class WeatherForecast {
+ public DateOnly Date { get; set; }
+ public int TemperatureC { get; set; }
+ public string? Summary { get; set; }
+ public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
+ }
+
+}
\ No newline at end of file
diff --git a/src/Portfolio.Web/Components/Routes.razor b/src/Portfolio.Web/Components/Routes.razor
new file mode 100644
index 0000000..ae94e9e
--- /dev/null
+++ b/src/Portfolio.Web/Components/Routes.razor
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Portfolio.Web/Components/_Imports.razor b/src/Portfolio.Web/Components/_Imports.razor
new file mode 100644
index 0000000..0822e89
--- /dev/null
+++ b/src/Portfolio.Web/Components/_Imports.razor
@@ -0,0 +1,10 @@
+@using System.Net.Http
+@using System.Net.Http.Json
+@using Microsoft.AspNetCore.Components.Forms
+@using Microsoft.AspNetCore.Components.Routing
+@using Microsoft.AspNetCore.Components.Web
+@using static Microsoft.AspNetCore.Components.Web.RenderMode
+@using Microsoft.AspNetCore.Components.Web.Virtualization
+@using Microsoft.JSInterop
+@using Portfolio.Web
+@using Portfolio.Web.Components
\ No newline at end of file
diff --git a/src/Portfolio.Web/Dockerfile b/src/Portfolio.Web/Dockerfile
new file mode 100644
index 0000000..a857689
--- /dev/null
+++ b/src/Portfolio.Web/Dockerfile
@@ -0,0 +1,30 @@
+FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base
+USER $APP_UID
+WORKDIR /app
+EXPOSE 8080
+EXPOSE 8081
+
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
+ARG BUILD_CONFIGURATION=Release
+WORKDIR /src
+
+COPY ["src/Portfolio.Shared/Portfolio.Shared.csproj", "./Portfolio.Shared/"]
+RUN dotnet restore "Portfolio.Shared/Portfolio.Shared.csproj"
+
+COPY ["src/Portfolio.Web/Portfolio.Web.csproj", "./Portfolio.Web/"]
+RUN dotnet restore "Portfolio.Web/Portfolio.Web.csproj"
+
+COPY ["src/Portfolio.Shared/", "./Portfolio.Shared/"]
+COPY ["src/Portfolio.Web", "./Portfolio.Web/"]
+
+WORKDIR "/src/Portfolio.Web"
+RUN dotnet build "Portfolio.Web.csproj" -c $BUILD_CONFIGURATION -o /app/build
+
+FROM build AS publish
+ARG BUILD_CONFIGURATION=Release
+RUN dotnet publish "Portfolio.Web.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
+
+FROM base AS final
+WORKDIR /app
+COPY --from=publish /app/publish .
+ENTRYPOINT ["dotnet", "Portfolio.Web.dll"]
diff --git a/src/Portfolio.Web/Portfolio.Web.csproj b/src/Portfolio.Web/Portfolio.Web.csproj
new file mode 100644
index 0000000..92326bb
--- /dev/null
+++ b/src/Portfolio.Web/Portfolio.Web.csproj
@@ -0,0 +1,67 @@
+
+
+
+ net9.0
+ enable
+ enable
+ Linux
+
+
+
+
+ .dockerignore
+
+
+
+
+
+
+
+
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.min.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.min.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.rtl.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.rtl.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.rtl.min.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-grid.rtl.min.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.min.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.min.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.rtl.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.rtl.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.rtl.min.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-reboot.rtl.min.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.min.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.min.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.rtl.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.rtl.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.rtl.min.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap-utilities.rtl.min.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap.min.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap.min.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap.rtl.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap.rtl.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap.rtl.min.css" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\css\bootstrap.rtl.min.css.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.bundle.js" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.bundle.js.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.bundle.min.js" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.bundle.min.js.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.esm.js" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.esm.js.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.esm.min.js" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.esm.min.js.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.js" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.js.map" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.min.js" />
+ <_ContentIncludedByDefault Remove="wwwroot\lib\bootstrap\dist\js\bootstrap.min.js.map" />
+
+
+
diff --git a/src/Portfolio.Web/Program.cs b/src/Portfolio.Web/Program.cs
new file mode 100644
index 0000000..d82cbbf
--- /dev/null
+++ b/src/Portfolio.Web/Program.cs
@@ -0,0 +1,29 @@
+using Portfolio.Web.Components;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+builder.Services.AddRazorComponents()
+ .AddInteractiveServerComponents();
+
+builder.AddServiceDefaults();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (!app.Environment.IsDevelopment()) {
+ app.UseExceptionHandler("/Error", createScopeForErrors: true);
+ // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
+ app.UseHsts();
+}
+
+app.UseHttpsRedirection();
+app.MapDefaultEndpoints();
+
+app.UseAntiforgery();
+
+app.MapStaticAssets();
+app.MapRazorComponents()
+ .AddInteractiveServerRenderMode();
+
+app.Run();
\ No newline at end of file
diff --git a/src/Portfolio.Web/Properties/launchSettings.json b/src/Portfolio.Web/Properties/launchSettings.json
new file mode 100644
index 0000000..168993b
--- /dev/null
+++ b/src/Portfolio.Web/Properties/launchSettings.json
@@ -0,0 +1,23 @@
+{
+ "$schema": "https://json.schemastore.org/launchsettings.json",
+ "profiles": {
+ "http": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "http://localhost:5075",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ },
+ "https": {
+ "commandName": "Project",
+ "dotnetRunMessages": true,
+ "launchBrowser": false,
+ "applicationUrl": "https://localhost:7202;http://localhost:5075",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+ }
diff --git a/src/Portfolio.Web/appsettings.Development.json b/src/Portfolio.Web/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/src/Portfolio.Web/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/src/Portfolio.Web/appsettings.json b/src/Portfolio.Web/appsettings.json
new file mode 100644
index 0000000..10f68b8
--- /dev/null
+++ b/src/Portfolio.Web/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/Portfolio.Web/wwwroot/app.css b/src/Portfolio.Web/wwwroot/app.css
new file mode 100644
index 0000000..e69de29
diff --git a/src/Portfolio.Web/wwwroot/favicon.png b/src/Portfolio.Web/wwwroot/favicon.png
new file mode 100644
index 0000000..a1dc44a
--- /dev/null
+++ b/src/Portfolio.Web/wwwroot/favicon.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e265ac0f2dda1e5dfa65b1adf330722bb3ef7789115283604d8cd19f098f1f08
+size 1148