Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Customizing Material and Its Versions: Token Overrides, Density, Your Own Component with the CDK, and Material from 12 to 22
Customize Material with tokens: to repaint one area, a mat.theme with only color inside a class added 4.2 kB, the old all-component-themes habit 53 kB; overlays stay outside the theme class, so give the class to the overlay container too. In Bookstore's institutional portal we measure the density scale, build a split button with CDK Menu and its harness, and look at Material from 12 to 22 and why old .mat-* overrides match zero elements.
CDK Scrolling and Layout: Virtual Scroll for a Long Catalog, BreakpointObserver, Clipboard and Other Utilities
CDK virtual scroll kept only 15 of 5,000 rows in the DOM and drew the page in 38 ms instead of 249 ms; the price is that Ctrl+F cannot find rows that are not rendered and that row height has to be fixed. On Bookstore's stock list we measure virtual scroll, content-visibility and a plain list, jumps with variable heights, choosing a menu or a bottom sheet with BreakpointObserver, the clipboard and CdkListbox.
CDK Drag and Drop: cdkDrag, cdkDropList, Sortable Lists and Moving Items Between Lists
In CDK Drag and Drop, cdkDropList and cdkDrag handle the dragging and you change the array: apply moveItemInArray and transferArrayItem to a copy, set it on the signal and track rows by identity. The CDK offers no keyboard sorting; we add button alternatives to a reading list and an institutional shipment plan in Bookstore, and measure focus lost on a moved row, touch behavior with a handle and touch-action, and the re-render cost at 500 rows.
CDK Overlay and Portal: Building Your Own Floating Panel, Position Strategies and a Comparison with CSS Anchor Positioning
In CDK Overlay, open the panel with createOverlayRef and a ComponentPortal, give FlexibleConnectedPositionStrategy fallback positions and the reposition scroll strategy, and dispose it with DestroyRef: without that, the panel and its backdrop stayed on screen after the page changed. We build a quick view and an account panel in Bookstore, and measure focus lost on Tab, the 14.5 kB cost of an eager import and the same panel with popover + CSS anchor positioning.
Dialog, Snackbar and Bottom Sheet: Passing Data with MatDialog, afterClosed, CDK Dialog and the Native dialog
Give MatDialog only ids, take the decision from afterClosed() and use closeOnNavigation: 'url-change': the default only closes on back/forward, so the dialog stayed open on a navigation from code. We build an order cancel dialog, an Undo snackbar and a bulk action bottom sheet in Bookstore, and measure a bare mat-dialog-close returning '', lost focus after confirming, a snackbar adding 34 kB to the initial bundle, and how MatDialog, CDK Dialog and the native dialog differ.
The Material Data Table: mat-table, MatSort, MatPaginator, Filtering and Server-side Pagination
Show a growing list by keeping sort, filter and page in the URL and paging in the API, not with MatTableDataSource in the browser: Bookstore's 10,000 orders sort in 59 ms in the browser, but the 1.5 MB response takes 1.26 seconds at 10 Mbit/s. We measure a missing URL param arriving as undefined, not resetting the page after a filter, avoiding an empty table while loading with linkedSignal, and the bug of reading SelectionModel inside computed().
Material Form Components: mat-form-field, matInput, mat-select, mat-autocomplete and mat-datepicker
mat-error only appears once a field is touched or after submit because of the default ErrorStateMatcher; with Signal Forms the ShowOnDirty matcher never shows the error of an empty required field. On Bookstore's institutional order form we measure an empty-looking mat-select without compareWith, debounce cutting 8 requests to 1, the native date adapter reading 05.12.2026 as 12 May, Turkish dates with date-fns and 15 December shifting to the 14th in UTC.
Getting Started with Angular Material and the CDK: ng add, the Component Catalog, the M3 Theme and Material vs CDK vs Angular Aria
Import Material components as standalone classes, not from one shared module: in Bookstore's admin panel a shared file exporting 35 modules grew the lazy chunk from 173 kB to 682 kB without a compiler warning. We measure what ng add changes, an M3 theme and density from the brand color, a responsive shell with toolbar and sidenav, why internal class overrides are fragile, and cutting the icon font from 325 KB to 1.4 KB.
What Changed in Blazor from .NET 8 to .NET 11: the Web App Model, RendererInfo, PersistentState, NotFound and .NET 11
.NET 8 moved Blazor to a single Web App model with render modes per component; .NET 9 and 10 filled its gaps, and .NET 11 brought more Static SSR, URL-based QuickGrid and circuit auto-pause. We upgraded the Bookstore panel to .NET 11: one using for [ValidatableType], the new BL0013/BL0016 analyzers, the removal of UseWebAssemblyDebugging, and .NET 10 LTS and .NET 11 STS support ending on the same day.
Taking Blazor to Production: WASM Size, Trimming, AOT, Circuit Resources, Reconnection UI and Hosting
Taking Blazor to production means measuring two costs: the first-visit download in WebAssembly (2.3 MB for the Bookstore panel, 4.3 MB with AOT but about six times faster on CPU work) and memory per circuit on the server (about 800 KB on the stock page, with a closed tab kept for three minutes). The post covers trimming and relinking, fingerprinted caching, CircuitOptions, ReconnectModal, a nonce-based Content Security Policy and WebSockets behind Nginx, all with real measurements.
Authentication and Authorization in Blazor: AuthenticationStateProvider, AuthorizeView, Auth per Render Mode and Passkeys
In Blazor the user comes from AuthenticationStateProvider: in InteractiveServer it is read from the cookie when the circuit starts and stays fixed, while WebAssembly receives only the serialized name and role claims, so AuthorizeView is a UI decision and security belongs to the endpoint and the API. In the Bookstore panel: Identity sign-in, a fallback policy, role-based price editing, an API protected by panel-signed tokens, and the passkey support in the .NET 10 template.
JavaScript Interop in Blazor: IJSRuntime, Collocated JS Modules, DotNetObjectReference and What's New in .NET 10
In Blazor, JS is imported as a .razor.js module next to the component and called through an IJSObjectReference; calls from JS back to .NET use DotNetObjectReference and [JSInvokable], and since there is no JS during prerendering, calls start in OnAfterRenderAsync. In the Bookstore panel we build a Chart.js sales chart with .NET 10's InvokeConstructorAsync, GetValueAsync and SetValueAsync, and show an ISBN copy button, JSDisconnectedException and the 32 KB message limit with real output.