27 JULY 2025 / BLAZOR
Markdown & Giscus Test
A first experiment integrating GitHub comments with Blazor. The comment theme follows the site's light and dark modes.
This example shows how the wrapper updates Giscus after the first interactive render:
// GiscusContainer.razor
<Giscus Repo="DylanRasburn/blazor-kiwi-comments"
RepoId="@RepoId"
Category="Announcements"
CategoryId="@CategoryId"
Mapping="Mapping.Specific"
ReactionsEnabled="true"
EmitMetadata="false"
InputPosition="InputPosition.Bottom"
Theme="@_currentTheme"
Lang="en"
Term="@Term"
Loading="Loading.Lazy" />
@code {
private string _currentTheme = "light";
private System.Timers.Timer? _debounceTimer;
private IJSObjectReference? _jsModule;
protected override void OnInitialized()
{
_currentTheme = ThemeService.IsDarkMode ? "dark" : "light";
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
_jsModule = await JSRuntime.InvokeAsync<IJSObjectReference>(
"import"", ""./js/giscus-wrapper.js");
ThemeService.OnThemeChanged += OnThemeChanged;
}
}
private void OnThemeChanged()
{
var newTheme = ThemeService.IsDarkMode ? "dark" : "light";
UpdateTheme(newTheme);
}
private void UpdateTheme(string newTheme)
{
_debounceTimer?.Stop();
_debounceTimer = new System.Timers.Timer(1000);
_debounceTimer.Elapsed += async (s, e) =>
{
_debounceTimer.Stop();
_currentTheme = newTheme;
if (_jsModule != null)
{
try
{
await _jsModule.InvokeVoidAsync("updateGiscusTheme", newTheme);
}
catch
{
}
}
await InvokeAsync(StateHasChanged);
};
_debounceTimer.Start();
}
public async ValueTask DisposeAsync()
{
ThemeService.OnThemeChanged -= OnThemeChanged;
_debounceTimer?.Dispose();
if (_jsModule != null)
{
await _jsModule.DisposeAsync();
}
}
}