refactor: move Tailwind CSS to wwwroot/css/, remove wwwroot/lib - #1
Conversation
- Output tailwind.css to wwwroot/css/ instead of wwwroot root - Remove empty wwwroot/lib/ (stale Bootstrap libman directory) - Update package.json scripts, Web.csproj, App.razor link paths Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add startup guard that detects empty Auth0:Domain or Auth0:ClientId and throws a clear InvalidOperationException with instructions for setting user secrets, rather than the cryptic ArgumentException from deep in the OpenIdConnect middleware. Also add Auth0 placeholder keys to appsettings.Development.json to document which secrets are required. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Browsers cannot process PostCSS/Tailwind directives in app.css (@import tailwindcss, @theme inline, @apply, @custom-variant). The compiled tailwind.css already includes all styles, custom properties, dark mode variants, and color theme overrides. Removing the duplicate app.css link fixes styling and theme toggles. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Without @rendermode InteractiveServer, Blazor renders NavMenu as static SSR. @OnClick events are silently ignored in static SSR — no SignalR connection exists. This caused the dark mode toggle and color theme buttons to do nothing. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add text-primary to .nav-link base style so all nav links respond to color theme changes (not just the brand NavLink) - Track _isDark bool in NavMenu; read initial state from DOM on first render via JS interop; swap icon between moon and sun on toggle Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add html:not(.dark) body.theme-* rules that shift --color-canvas and --color-surface to the 50/100 tint of each theme color in light mode: blue → blue-50 / blue-100 red → rose-50 / rose-100 green → green-50 / green-100 yellow → yellow-50 / yellow-100 Dark mode is unaffected; the :not(.dark) guard ensures html.dark's dark canvas values always win. This makes the color theme circles visually change the whole page, not just primary-colored elements. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Blazor 8 enhanced navigation patches the DOM from server-rendered HTML,
which strips JS-added classes on <html> and <body> on every page
transition. Fix by:
- Extracting applyTheme() function
- Calling it on initial load (existing behaviour)
- Listening to document 'enhancedload' event (fired by Blazor after
each enhanced navigation) to re-apply dark + color theme classes
- Defensive remove('dark') in light-mode branch
- Dedup theme class removal before re-adding
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- NavMenu: add _currentTheme state (default: theme-blue), ThemeBtnClass() shows ring-2+scale-110 on selected button; reads colorTheme from localStorage in OnAfterRenderAsync; SetTheme() updates C# + JS state - app.css: add dark-mode per-theme canvas/surface CSS vars so nav/footer bg-surface renders themed dark blue/red/green/yellow instead of gray - App.razor: MutationObserver guards html/body class attrs as backstop; listen to both enhancedload and blazor:navigated events; fix localStorage update order in toggleDark/setTheme to prevent observer race condition Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Create wwwroot/js/theme.js: window.themeManager with 12 methods, 4 colors × 2 brightness = 8 themes stored as 'theme-blue-light' etc. Uses STORAGE_KEY 'tailwind-color-theme', calls initialize() on load. - Rewrite app.css: full OKLCH primary-50..950 palettes for all 8 themes on :root.theme-* selectors. @theme inline exposes primary-* as Tailwind utilities. Semantic tokens (canvas/surface/content/muted/edge) derived from primary shades per theme. :root fallback prevents FOUC. - Update App.razor: IIFE migrates old localStorage keys (colorTheme + darkMode) to unified 'tailwind-color-theme'. Applies theme class to <html> immediately. Removes MutationObserver and old window.setTheme/ toggleDark globals. Adds <script src='js/theme.js'> before blazor.web.js. - Update NavMenu.razor: nav uses bg-primary-400 (always colored). Links, brand, hamburger, controls use text-primary-50 / bg-primary-300. Theme select values are 'blue'/'red'/etc. (not 'theme-blue'). C# fields changed to _currentColor + _currentBrightness; JS interop uses themeManager methods. Dark toggle shows SVG sun/moon icons. Reads back brightness after toggle for robustness. - Update MainLayout.razor: footer uses bg-primary-800 text-primary-50 border-primary-700 so it is always richly colored in all themes/modes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- NavMenu: inject NavigationManager, subscribe LocationChanged to re-sync _currentColor and _currentBrightness from JS on every page navigation; implement IDisposable to unsubscribe and prevent memory leaks - MainLayout: change footer from bg-primary-800/border-primary-700 to bg-primary-400/border-primary-500 to match nav bar color Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The IIFE was placed at the bottom of <body>, so the browser rendered all page content in light mode before the script ran. Moving it to the very top of <head> (before stylesheet links) ensures the theme class is on <html> when the browser first calculates CSS — dark mode now applies from the first paint with zero flash. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…avigation - Extract applyThemeFromStorage() helper in the IIFE so it can be reused - Add MutationObserver on <html> element: if Blazor's DOM reconciliation strips the theme class (because server renders <html lang='en'> without classes), the observer immediately re-applies from localStorage - Add 100ms delayed retry in enhancedload handler to catch any post-navigation DOM patching that occurs after the initial event fires - Disconnect any previous _themeObserver before creating a new one (prevents duplicate observers if the IIFE is re-executed) - Keep blazor:navigated listener as belt-and-suspenders Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Session log (2026-04-17): - Summarizes theme persistence bug fixes - Documents three resolved issues - Lists commit SHAs Orchestration log: - Details implementation phases - Documents verification results - Confirms user validation Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Captures all patterns from the Tailwind migration: - Anti-FOUC IIFE placement in <head> before stylesheets - Unified localStorage key (tailwind-color-theme) - Old split-key migration shim (colorTheme + darkMode) - Blazor enhanced-navigation re-application hooks - MutationObserver guard against DOM reconciliation - themeManager JS object coordination - Footer/nav color consistency pattern - Anti-patterns Source: feature/tailwind-migration, commits 8105239 4c41df0 c56ac47 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- routing.md: new Skills section maps theme/Tailwind work to the skill - legolas/charter.md: standing instruction to read skill before any theme/FOUC/localStorage task Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR shifts the Web UI styling stack fully to Tailwind (including theme persistence across Blazor enhanced navigation), removes stale Bootstrap static assets, and adds Auth0 role-claim normalization plus a set of bUnit/unit tests with coverage configuration.
Changes:
- Move Tailwind source/compiled CSS under
src/Web/wwwroot/css/, add Tailwind build scripts + MSBuild hook, and remove Bootstrap assets fromwwwroot/lib/. - Add theme persistence implementation (head IIFE +
themeManagerJS + NavMenu controls) and restyle multiple Razor pages to Tailwind utilities. - Introduce Auth0 role-claim expansion/normalization (
RoleClaimsHelper) and add unit/bUnit coverage + new tests.
Reviewed changes
Copilot reviewed 40 out of 92 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit.Tests/Unit.Tests.csproj | Enables coverage/thresholding and adds bUnit + coverlet dependencies. |
| tests/Unit.Tests/Testing/TestAuthorizationService.cs | Test IAuthorizationService to support AuthorizeView behaviors in bUnit. |
| tests/Unit.Tests/Security/RoleClaimsHelperTests.cs | Unit coverage for role claim type parsing/expansion/deduplication. |
| tests/Unit.Tests/ResultTests.cs | Unit coverage for Result/Result<T> helpers and conversions. |
| tests/Unit.Tests/Features/UserManagement/ProfileTests.cs | bUnit tests for the new Profile page rendering/fallbacks. |
| tests/Unit.Tests/Components/RazorSmokeTests.cs | Broad smoke coverage for key components/pages under Tailwind + auth scenarios. |
| tests/Unit.Tests/Components/Layout/NavMenuTests.cs | bUnit coverage for nav auth gating + JS theme interactions. |
| src/Web/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.min.css | Removes Bootstrap static asset (part of wwwroot/lib cleanup). |
| src/Web/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.rtl.css | Removes Bootstrap static asset (part of wwwroot/lib cleanup). |
| src/Web/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css | Removes Bootstrap static asset (part of wwwroot/lib cleanup). |
| src/Web/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css | Removes Bootstrap static asset (part of wwwroot/lib cleanup). |
| src/Web/wwwroot/js/theme.js | Adds window.themeManager for theme storage + DOM class application. |
| src/Web/wwwroot/css/tailwind.css | Adds generated Tailwind output in the new wwwroot/css/ location. |
| src/Web/wwwroot/css/app.css | Adds Tailwind v4 “CSS-first” input with @source, theme tokens, and component styles. |
| src/Web/wwwroot/app.css | Removes the old root-level CSS (Bootstrap-era styles). |
| src/Web/appsettings.Development.json | Adds Auth0 config placeholders for local dev discoverability. |
| src/Web/Web.csproj | Adds an MSBuild target to build Tailwind via npm run tw:build. |
| src/Web/Security/RoleClaimsHelper.cs | Adds role claim type selection + role expansion/deduplication utilities. |
| src/Web/Properties/AssemblyInfo.cs | Adds InternalsVisibleTo for unit test access. |
| src/Web/Program.cs | Adds Auth0 config guard + OIDC token validation hook to normalize role claims. |
| src/Web/Features/UserManagement/Profile.razor | Adds an authenticated Profile page showing identity/roles/claims. |
| src/Web/Features/UserManagement/ManageRoles.razor | Restyles Manage Roles page from Bootstrap to Tailwind. |
| src/Web/Features/BlogPosts/List/Index.razor | Restyles list/table + alerts/buttons from Bootstrap to Tailwind. |
| src/Web/Features/BlogPosts/Edit/Edit.razor | Restyles edit form + alerts/buttons from Bootstrap to Tailwind. |
| src/Web/Features/BlogPosts/Delete/ConfirmDeleteDialog.razor | Replaces Bootstrap modal with Tailwind overlay/dialog. |
| src/Web/Features/BlogPosts/Create/Create.razor | Restyles create form + alerts/buttons from Bootstrap to Tailwind. |
| src/Web/Components/Pages/Weather.razor | Restyles sample Weather page table and copy. |
| src/Web/Components/Pages/Counter.razor | Restyles sample Counter page button and copy. |
| src/Web/Components/Layout/ReconnectModal.razor.css | Updates reconnect modal to use theme CSS variables instead of hardcoded colors. |
| src/Web/Components/Layout/NavMenu.razor.css | Removes old Bootstrap/sidebar nav CSS. |
| src/Web/Components/Layout/NavMenu.razor | Replaces sidebar nav with top nav + theme controls + mobile menu. |
| src/Web/Components/Layout/MainLayout.razor.css | Removes old layout CSS tied to sidebar/Bootstrap layout. |
| src/Web/Components/Layout/MainLayout.razor | Reworks layout wrapper, spacing, and footer styling for Tailwind. |
| src/Web/Components/App.razor | Updates CSS/script links + adds head script for theme persistence/anti-FOUC. |
| package.json | Adds Tailwind CLI build/watch scripts and devDependencies. |
| aspire.config.json | Adds Aspire app host path configuration. |
| .squad/skills/blazor-tailwind-theme-persistence/SKILL.md | Documents the theme persistence approach as a reusable Squad skill. |
| .squad/routing.md | Adds routing guidance to inject the theme persistence skill for relevant work. |
| .squad/orchestration-log/2026-04-17T21:36:35Z-copilot-theme-fix.md | Captures orchestration steps taken for theme persistence fixes. |
| .squad/log/2026-04-17T21:36:35Z-theme-fix-complete.md | Records completion summary for theme persistence fixes. |
| .squad/agents/sam/history.md | Documents Auth0 configuration guard rationale and changes. |
| .squad/agents/legolas/history.md | Records Tailwind migration and CSS folder restructure learnings. |
| .squad/agents/legolas/charter.md | Adds instruction to read the theme persistence skill for relevant tasks. |
| .squad/agents/aragorn/history.md | Adds Tailwind migration skill review notes. |
| .idea/.idea.MyBlog/.idea/vcs.xml | Adds Rider/IDEA project configuration (should not be tracked). |
| .idea/.idea.MyBlog/.idea/misc.xml | Adds Rider/IDEA project configuration (should not be tracked). |
| .idea/.idea.MyBlog/.idea/indexLayout.xml | Adds Rider/IDEA project configuration (should not be tracked). |
| .idea/.idea.MyBlog/.idea/encodings.xml | Adds Rider/IDEA project configuration (should not be tracked). |
| .idea/.idea.MyBlog/.idea/dataSources.xml | Adds Rider/IDEA datasource config (contains credentials — must not be tracked). |
| .idea/.idea.MyBlog/.idea/.gitignore | Adds Rider/IDEA-local ignore file (directory should be ignored at repo root instead). |
| .gitignore | Ignores node_modules and Tailwind output (and currently does not ignore .idea/). |
Files not reviewed (6)
- .idea/.idea.MyBlog/.idea/.gitignore: Language not supported
- .idea/.idea.MyBlog/.idea/dataSources.xml: Language not supported
- .idea/.idea.MyBlog/.idea/encodings.xml: Language not supported
- .idea/.idea.MyBlog/.idea/indexLayout.xml: Language not supported
- .idea/.idea.MyBlog/.idea/misc.xml: Language not supported
- .idea/.idea.MyBlog/.idea/vcs.xml: Language not supported
| var existingOnTokenValidated = options.Events.OnTokenValidated; | ||
| options.Events.OnTokenValidated = async context => | ||
| { | ||
| await existingOnTokenValidated(context); | ||
|
|
There was a problem hiding this comment.
existingOnTokenValidated may be null (the default for OpenIdConnectEvents.OnTokenValidated). Calling await existingOnTokenValidated(context) will throw a NullReferenceException during sign-in. Guard for null (or default to Task.CompletedTask) before awaiting, then run AddRoleClaims.
| <data-source source="LOCAL" name="mongodb" uuid="1a564bcc-fc25-4ef0-a675-3bccecb8960c"> | ||
| <driver-ref>mongo.4</driver-ref> | ||
| <synchronize>true</synchronize> | ||
| <jdbc-driver>com.dbschema.MongoJdbcDriver</jdbc-driver> | ||
| <jdbc-url>mongodb://admin:jmr1sZxmTA3JAZ0J2QpJs4@localhost:32795/?authSource=admin&authMechanism=SCRAM-SHA-256</jdbc-url> | ||
| <jdbc-additional-properties> | ||
| <property name="aspireResourceId" value="mongodb-rkpqnkpt" /> | ||
| </jdbc-additional-properties> | ||
| <working-dir>$ProjectFileDir$</working-dir> | ||
| </data-source> | ||
| <data-source source="LOCAL" name="redis" uuid="075bb980-ed17-416f-aade-b9c8a4868f26"> | ||
| <driver-ref>redis</driver-ref> | ||
| <synchronize>true</synchronize> | ||
| <jdbc-driver>jdbc.RedisDriver</jdbc-driver> | ||
| <jdbc-url>jdbc:redis://3GtSRC0bKuYcbGKadc81Bp@localhost:32796?ssl=true</jdbc-url> | ||
| <jdbc-additional-properties> | ||
| <property name="aspireResourceId" value="redis-hwmycsny" /> | ||
| </jdbc-additional-properties> | ||
| <working-dir>$ProjectFileDir$</working-dir> | ||
| </data-source> |
There was a problem hiding this comment.
This file contains hard-coded credentials/connection strings (e.g., MongoDB user+password in jdbc-url). These should not be committed. Remove this file from the repo history and rotate the exposed credentials; also add .idea/ (or at least .idea/**/dataSources*.xml) to .gitignore.
| <data-source source="LOCAL" name="mongodb" uuid="1a564bcc-fc25-4ef0-a675-3bccecb8960c"> | |
| <driver-ref>mongo.4</driver-ref> | |
| <synchronize>true</synchronize> | |
| <jdbc-driver>com.dbschema.MongoJdbcDriver</jdbc-driver> | |
| <jdbc-url>mongodb://admin:jmr1sZxmTA3JAZ0J2QpJs4@localhost:32795/?authSource=admin&authMechanism=SCRAM-SHA-256</jdbc-url> | |
| <jdbc-additional-properties> | |
| <property name="aspireResourceId" value="mongodb-rkpqnkpt" /> | |
| </jdbc-additional-properties> | |
| <working-dir>$ProjectFileDir$</working-dir> | |
| </data-source> | |
| <data-source source="LOCAL" name="redis" uuid="075bb980-ed17-416f-aade-b9c8a4868f26"> | |
| <driver-ref>redis</driver-ref> | |
| <synchronize>true</synchronize> | |
| <jdbc-driver>jdbc.RedisDriver</jdbc-driver> | |
| <jdbc-url>jdbc:redis://3GtSRC0bKuYcbGKadc81Bp@localhost:32796?ssl=true</jdbc-url> | |
| <jdbc-additional-properties> | |
| <property name="aspireResourceId" value="redis-hwmycsny" /> | |
| </jdbc-additional-properties> | |
| <working-dir>$ProjectFileDir$</working-dir> | |
| </data-source> |
| { | ||
| "name": "myblog", | ||
| "private": true, | ||
| "scripts": { | ||
| "tw:build": "npx @tailwindcss/cli -i ./src/Web/wwwroot/css/app.css -o ./src/Web/wwwroot/css/tailwind.css --minify", |
There was a problem hiding this comment.
The PR metadata says this change is about moving Tailwind output/removing wwwroot/lib, but this PR also introduces Auth0 role-claim normalization, new Profile page + theme persistence JS, and substantial new unit/bUnit tests + coverage settings. Please update the PR title/description to match the scope, or split into separate PRs to keep reviews focused.
| <!-- Build Tailwind CSS (skip on CI environments where npm is not installed) --> | ||
| <Target Name="BuildTailwind" BeforeTargets="Build" Condition="'$(CI)' != 'true'"> | ||
| <Exec Command="npm run tw:build" WorkingDirectory="$(MSBuildProjectDirectory)/../.." /> | ||
| </Target> |
There was a problem hiding this comment.
The Tailwind build target runs on every local build of the Web project. Since tests/Unit.Tests references src/Web/Web.csproj, dotnet test will also trigger npm run tw:build locally, which can fail or slow tests on machines without Node/npm. Consider gating this behind an explicit MSBuild property (opt-in), checking for npm availability, or limiting it to publish/dev builds rather than all builds.
| <div class="grid gap-6 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.35fr)]"> | ||
| <section class="card p-6"> | ||
| <div class="flex flex-col items-center gap-4 text-center sm:flex-row sm:items-start sm:text-left"> |
There was a problem hiding this comment.
Profile.razor uses the CSS class card, but there is no .card definition in the Tailwind input (wwwroot/css/app.css) or generated output (tailwind.css). With Bootstrap removed, these sections won’t get the intended styling. Replace card with explicit Tailwind utility classes (e.g., rounded + shadow + bg-surface + border).
| <section class="card overflow-hidden"> | ||
| <div class="border-b border-primary-200 px-6 py-4 dark:border-primary-800"> |
There was a problem hiding this comment.
This second card usage has the same issue: card isn’t defined anywhere in the Tailwind CSS pipeline, so this section will render unstyled. Please replace with Tailwind utility classes or add a .card component style in wwwroot/css/app.css.
| <data-source source="LOCAL" name="mongodb" uuid="1a564bcc-fc25-4ef0-a675-3bccecb8960c"> | ||
| <driver-ref>mongo.4</driver-ref> | ||
| <synchronize>true</synchronize> | ||
| <jdbc-driver>com.dbschema.MongoJdbcDriver</jdbc-driver> | ||
| <jdbc-url>mongodb://admin:jmr1sZxmTA3JAZ0J2QpJs4@localhost:32795/?authSource=admin&authMechanism=SCRAM-SHA-256</jdbc-url> | ||
| <jdbc-additional-properties> | ||
| <property name="aspireResourceId" value="mongodb-rkpqnkpt" /> | ||
| </jdbc-additional-properties> | ||
| <working-dir>$ProjectFileDir$</working-dir> | ||
| </data-source> | ||
| <data-source source="LOCAL" name="redis" uuid="075bb980-ed17-416f-aade-b9c8a4868f26"> | ||
| <driver-ref>redis</driver-ref> | ||
| <synchronize>true</synchronize> | ||
| <jdbc-driver>jdbc.RedisDriver</jdbc-driver> | ||
| <jdbc-url>jdbc:redis://3GtSRC0bKuYcbGKadc81Bp@localhost:32796?ssl=true</jdbc-url> | ||
| <jdbc-additional-properties> | ||
| <property name="aspireResourceId" value="redis-hwmycsny" /> | ||
| </jdbc-additional-properties> | ||
| <working-dir>$ProjectFileDir$</working-dir> | ||
| </data-source> |
There was a problem hiding this comment.
This file also includes a Redis connection string with what appears to be an access token/password in jdbc-url. Please remove it from the repo history and rotate the credential; IDE datasource files should not be tracked.
| <data-source source="LOCAL" name="mongodb" uuid="1a564bcc-fc25-4ef0-a675-3bccecb8960c"> | |
| <driver-ref>mongo.4</driver-ref> | |
| <synchronize>true</synchronize> | |
| <jdbc-driver>com.dbschema.MongoJdbcDriver</jdbc-driver> | |
| <jdbc-url>mongodb://admin:jmr1sZxmTA3JAZ0J2QpJs4@localhost:32795/?authSource=admin&authMechanism=SCRAM-SHA-256</jdbc-url> | |
| <jdbc-additional-properties> | |
| <property name="aspireResourceId" value="mongodb-rkpqnkpt" /> | |
| </jdbc-additional-properties> | |
| <working-dir>$ProjectFileDir$</working-dir> | |
| </data-source> | |
| <data-source source="LOCAL" name="redis" uuid="075bb980-ed17-416f-aade-b9c8a4868f26"> | |
| <driver-ref>redis</driver-ref> | |
| <synchronize>true</synchronize> | |
| <jdbc-driver>jdbc.RedisDriver</jdbc-driver> | |
| <jdbc-url>jdbc:redis://3GtSRC0bKuYcbGKadc81Bp@localhost:32796?ssl=true</jdbc-url> | |
| <jdbc-additional-properties> | |
| <property name="aspireResourceId" value="redis-hwmycsny" /> | |
| </jdbc-additional-properties> | |
| <working-dir>$ProjectFileDir$</working-dir> | |
| </data-source> |
| })(); | ||
| </script> | ||
| <ResourcePreloader /> | ||
| <link rel="stylesheet" href="css/tailwind.css" /> |
There was a problem hiding this comment.
tailwind.css is referenced via a plain URL (href="css/tailwind.css") while other static assets in this file use @Assets[...] (fingerprinting/cache busting). For consistency and correct long-term caching, consider switching to @Assets["css/tailwind.css"].
| <link rel="stylesheet" href="css/tailwind.css" /> | |
| <link rel="stylesheet" href="@Assets["css/tailwind.css"]" /> |
| <PackageReference Include="bunit" Version="2.7.2" /> | ||
| <PackageReference Include="coverlet.collector" Version="6.0.4" /> | ||
| <PackageReference Include="coverlet.msbuild" Version="10.0.0"> |
There was a problem hiding this comment.
This project references both coverlet.collector and coverlet.msbuild and also sets CollectCoverage=true. That’s usually redundant and can result in confusing/double coverage runs depending on how dotnet test is invoked. The other test projects in this repo appear to use only coverlet.collector, so consider standardizing on a single approach here too.
| <script src="@Assets["_framework/blazor.web.js"]"></script> | ||
| <Routes /> | ||
| <ReconnectModal /> | ||
| <script src="js/theme.js"></script> |
There was a problem hiding this comment.
theme.js is referenced via a plain URL (src="js/theme.js") while other static assets in this file use @Assets[...]. Consider using @Assets["js/theme.js"] so it participates in fingerprinting/cache busting the same way as MyBlog.Web.styles.css and blazor.web.js.
| <script src="js/theme.js"></script> | |
| <script src="@Assets["js/theme.js"]"></script> |
Add explicit hard gate to routing.md, sprint-planning.md, and pr-merge-process.md so no agent can start coding without a GitHub issue linked to a milestone. Changes: - routing.md: guardrail #1 (absolute pre-code issue check) and guardrail #8 (direct user request gate): any coding request triggers an issue existence check first - sprint-planning.md: new 'Hard Gate — No Code Before Issue' section with enforcement sequence; two new anti-pattern entries covering no-issue code and plan-without-ceremony patterns - pr-merge-process.md: Ralph's Pre-Review Gate table now includes 'GitHub issue exists' check (Closes #N required); new anti-pattern for PRs missing issue link Closes #50 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Summary Closes #50 Adds an explicit **"no code before issue"** hard gate to prevent future process violations where implementation starts before a GitHub issue is created. ## Changes ### `routing.md` - **Guardrail #1** (new): Absolute pre-code issue check — any work must have an existing GitHub issue before any file is touched - **Guardrail #8** (new): Direct user coding requests trigger the same issue-first check ### `sprint-planning.md` - **New section: Hard Gate — No Code Before Issue** — enforcement sequence with explicit YES/NO decision tree - **Anti-patterns**: Added `❌ Writing any code before a GitHub issue exists` and `❌ Implementing a [[PLAN]] request without running the sprint planning ceremony` ### `pr-merge-process.md` - **Ralph's Pre-Review Gate**: Added `GitHub issue exists` row — PR body must contain `Closes #N`; if missing, Ralph creates the issue before review proceeds - **Anti-patterns**: Added `❌ Opening a PR without a Closes #N link` ## Testing This is a documentation/process change. No code was modified; no build/test verification needed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- sprint-planning.md: rename Hard Gate to 'No Code Before Issue / No Issue Without Sprint'; add explicit sprint-stamp check (title prefix + milestone + board); add two new anti-patterns for missing prefix and milestone; strengthen Step 3 with must-have callout - routing.md: update Guardrails #1 and #8 to require [Sprint N] title prefix and milestone in addition to issue existence - issue-lifecycle.md: add Mandatory Issue Format section with canonical create command and three-requirement table No issue may be created, branched, or PR'd without [Sprint N] title and milestone set to Sprint N: {Theme}. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- sprint-planning.md: strengthen Hard Gate to require [Sprint N] title prefix and milestone before any branch; add 2 new anti-patterns - sprint-planning.md: Step 3 gains mandatory-format table - routing.md: Guardrails #1 and #8 require milestone + sprint prefix on every issue - issue-lifecycle.md: add mandatory issue format block to GitHub section Closes #66 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- routing.md: Add Guardrails #9 (Gimli parallel), #10 (no-verify prohibition), #11 (rubber duck for new patterns); strengthen Rule #6 to name Gimli+Frodo+Pippin - ceremonies.md: Add Feature Work Kickoff ceremony; harden Retrospective with coverage-gate trigger and closure requirement - pre-push-process.md: Add hard block on git push --no-verify at top of file with SDK mismatch fix instructions - pr-merge-process.md: Step 3 now explicitly checks coverage gate (not just tests passing); adds 'Tests authored' gate for Gimli coverage - gimli/charter.md: Fix Critical Rule #1 paths from IssueTracker to MyBlog (tests/Unit.Tests, tests/Architecture.Tests); add coverage gate (89%); add Rule #9 enforcing parallel spawn Closes #68 (retrospective action items) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Closes #66 Working as Ralph (Meta / squad maintenance) ## Summary Strengthens three squad process documents so that no issue can exist without a sprint assignment and every issue title carries the `[Sprint N]` prefix. ## Changes - **`sprint-planning.md`** — Hard Gate updated to require `[Sprint N]` title prefix + milestone before any branch; Step 3 gains a mandatory-format table; two new anti-patterns added - **`routing.md`** — Guardrails #1 and #8 updated to require both milestone and sprint prefix on every issue before code starts - **`issue-lifecycle.md`** — Mandatory issue format block added to GitHub section (title pattern + milestone field rules) ## Testing Squad process documents — no build or test suite applies. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com## Summary
Closes #
Type of Change
Domain Affected
Self-Review Checklist
Code Quality
dotnet build IssueTrackerApp.slnx --configuration Release— 0 errors, 0 warningsdotnet test IssueTrackerApp.slnx --configuration Release --no-build— all passArchitecture
Command/Query/Handler/Validatornaming conventionssealedWeborPersistence.*projectsResult<T>/ResultErrorCodeused for expected failures (no exception-driven control flow)Domain.DTOs; Models are inDomain.ModelsTests
[Collection("XxxIntegration")])IssueDto.Empty/CommentDto.Emptyinstances directlySecurity (check if security-relevant)
RequireAuthorization/ policy appliedMarkupStringused with user-supplied contentMerge Readiness
main(no merge conflicts)Screenshots / Evidence
Notes for Reviewers