diff --git a/Elternbeirat.Web.Tests/Elternbeirat.Web.Tests.csproj b/Elternbeirat.Web.Tests/Elternbeirat.Web.Tests.csproj
new file mode 100644
index 0000000..bc3d902
--- /dev/null
+++ b/Elternbeirat.Web.Tests/Elternbeirat.Web.Tests.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net10.0
+ enable
+ enable
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Elternbeirat.Web.Tests/RouteSmokeTests.cs b/Elternbeirat.Web.Tests/RouteSmokeTests.cs
new file mode 100644
index 0000000..2de7a4b
--- /dev/null
+++ b/Elternbeirat.Web.Tests/RouteSmokeTests.cs
@@ -0,0 +1,65 @@
+using System.Net;
+using Microsoft.AspNetCore.Mvc.Testing;
+
+namespace Elternbeirat.Web.Tests;
+
+///
+/// Smoke tests: every known route must return 200, unknown routes must return
+/// 404. This catches broken content files, renamed slugs or routing regressions
+/// before a deploy.
+///
+public sealed class RouteSmokeTests : IClassFixture>
+{
+ private readonly WebApplicationFactory _factory;
+
+ public RouteSmokeTests(WebApplicationFactory factory)
+ {
+ _factory = factory;
+ }
+
+ ///
+ /// Every route that a visitor can reach through the navigation, the FAQ hub
+ /// or the news section.
+ ///
+ public static TheoryData KnownRoutes =>
+ [
+ "/",
+ "/vorstandsteam",
+ "/foerderverein",
+ "/faq",
+ "/faq-mensa",
+ "/faq-schliessfach",
+ "/faq-elterneuro",
+ "/faq-elternarbeit",
+ "/downloads",
+ "/kontakt",
+ "/impressum",
+ "/datenschutz",
+ "/beitraege",
+ "/beitraege/neuer-vorstand-gewaehlt",
+ "/beitraege/neue-sporthalle-eroeffnet",
+ ];
+
+ [Theory]
+ [MemberData(nameof(KnownRoutes))]
+ public async Task Known_route_returns_200(string route)
+ {
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync(route);
+
+ Assert.Equal(HttpStatusCode.OK, response.StatusCode);
+ }
+
+ [Theory]
+ [InlineData("/gibt-es-nicht")]
+ [InlineData("/beitraege/gibt-es-nicht")]
+ public async Task Unknown_route_returns_404(string route)
+ {
+ var client = _factory.CreateClient();
+
+ var response = await client.GetAsync(route);
+
+ Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
+ }
+}
diff --git a/Elternbeirat.Web/Elternbeirat.Web.csproj b/Elternbeirat.Web/Elternbeirat.Web.csproj
index 1b92c11..aeae671 100644
--- a/Elternbeirat.Web/Elternbeirat.Web.csproj
+++ b/Elternbeirat.Web/Elternbeirat.Web.csproj
@@ -7,6 +7,12 @@
true
+
+
+
+
+
diff --git a/Elternbeirat.slnx b/Elternbeirat.slnx
index 99c32aa..e50c80f 100644
--- a/Elternbeirat.slnx
+++ b/Elternbeirat.slnx
@@ -1,3 +1,4 @@
+