Initial TafsirQuran app with Gitea CI/CD deploy to k3s.
build-and-deploy / deploy (push) Successful in 10m50s

Blazor UI + ASP.NET API + Postgres; push to main builds images and rolls out namespace tafsirquran.
This commit is contained in:
2026-10-09 21:50:37 +03:30
commit 7f06856f45
124 changed files with 4729 additions and 0 deletions
+24
View File
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#1f6b4a" />
<meta name="description" content="تفسیر قرآن کریم — صوت و متن" />
<base href="/" />
<link rel="manifest" href="manifest.webmanifest" />
<link rel="apple-touch-icon" href="icons/icon-192.png" />
<link rel="stylesheet" href="_content/TafsirQuran.UI/css/app.css" />
<link rel="stylesheet" href="@Assets["app.css"]" />
<HeadOutlet @rendermode="InteractiveServer" />
</head>
<body>
<TafsirQuran.UI.Routes @rendermode="InteractiveServer" />
<script src="_framework/blazor.web.js"></script>
<script src="_content/TafsirQuran.UI/js/app.js"></script>
<script src="service-worker-register.js"></script>
</body>
</html>
@@ -0,0 +1,9 @@
@inherits LayoutComponentBase
@Body
<div id="blazor-error-ui" data-nosnippet>
An unhandled error has occurred.
<a href="." class="reload">Reload</a>
<span class="dismiss">🗙</span>
</div>
@@ -0,0 +1,20 @@
#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;
}
@@ -0,0 +1,36 @@
@page "/Error"
@using System.Diagnostics
<PageTitle>Error</PageTitle>
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
@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;
}
@@ -0,0 +1,12 @@
@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 TafsirQuran.UI
@using TafsirQuran.UI.Layout
@using TafsirQuran.Web
@using TafsirQuran.Web.Components
+30
View File
@@ -0,0 +1,30 @@
using TafsirQuran.UI;
using TafsirQuran.UI.Services;
using TafsirQuran.Web.Components;
var builder = WebApplication.CreateBuilder(args);
var apiBase = builder.Configuration["ApiBaseAddress"] ?? "http://localhost:5080/";
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddTafsirUi(apiBase);
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
}
// HTTP NodePort / reverse-proxy; do not force HTTPS redirect in cluster.
app.UseAntiforgery();
app.UseStaticFiles();
app.MapStaticAssets();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddAdditionalAssemblies(typeof(TafsirQuran.UI.Routes).Assembly);
app.Run();
@@ -0,0 +1,23 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5299",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:7169;http://localhost:5299",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\TafsirQuran.UI\TafsirQuran.UI.csproj" />
<ProjectReference Include="..\TafsirQuran.Shared\TafsirQuran.Shared.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
+10
View File
@@ -0,0 +1,10 @@
{
"ApiBaseAddress": "http://localhost:5080/",
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
+2
View File
@@ -0,0 +1,2 @@
/* Host-level overrides kept minimal; main styles live in TafsirQuran.UI */
html, body { min-height: 100%; }
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

@@ -0,0 +1,25 @@
{
"name": "تفسیر قرآن",
"short_name": "تفسیر قرآن",
"description": "شنیدن تفسیر قرآن کریم",
"start_url": "/",
"display": "standalone",
"background_color": "#f3efe6",
"theme_color": "#1f6b4a",
"dir": "rtl",
"lang": "fa",
"icons": [
{
"src": "icons/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any maskable"
},
{
"src": "icons/icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any maskable"
}
]
}
@@ -0,0 +1,5 @@
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/service-worker.js').catch(() => {});
});
}
@@ -0,0 +1,25 @@
const CACHE = 'tafsirquran-static-v1';
const ASSETS = [
'/',
'/manifest.webmanifest',
'/_content/TafsirQuran.UI/css/app.css',
'/_content/TafsirQuran.UI/js/app.js'
];
self.addEventListener('install', (event) => {
event.waitUntil(caches.open(CACHE).then((cache) => cache.addAll(ASSETS)).then(() => self.skipWaiting()));
});
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((keys) => Promise.all(keys.filter((k) => k !== CACHE).map((k) => caches.delete(k)))).then(() => self.clients.claim())
);
});
self.addEventListener('fetch', (event) => {
const req = event.request;
if (req.method !== 'GET') return;
event.respondWith(
caches.match(req).then((cached) => cached || fetch(req).catch(() => caches.match('/')))
);
});