Building This Portfolio Website in ASP.NET Core
A portfolio site could be a single static HTML page. I built this one as a server-rendered ASP.NET Core application instead. The roles I am applying for work with C#, .NET and SQL Server, and this site is my first project in that stack. Rather than only listing those technologies, I wanted the portfolio itself to be built with them.
Stack
- ASP.NET Core 10 with Razor Pages: every page is rendered on the server, with no SPA framework
- Entity Framework Core 10 as the data layer, with schema changes as EF Core migrations
- SQL Server 2022, run locally in a Docker container with Docker Compose
- Plain CSS and a 48-line JavaScript file, with no frontend build step, npm packages or web fonts
The only NuGet packages are EF Core's SQL Server provider and its design-time tools. Everything else comes with ASP.NET Core.
Content as data
Projects, skills and blog posts, including this one, are EF Core entities stored in SQL Server rather than hardcoded in the markup. A project has its technologies as child rows, skills are grouped into categories, and a blog post can point to a project, which is how the "Related project" box below is filled in. Presentation concerns stay out of the database. For example, which icon belongs to which skill is a mapping in the page code.
The related rows are loaded in the same query, so a page never makes one extra query per item, and the URL slugs of projects and posts have unique indexes.
Startup, migrations and seeding
On startup the app applies any pending migrations and then seeds the content, so a new database is created and filled without any manual commands. Seeding works per key: a skill by its name within its category, and a project or post by its slug. A new item added to the seed reaches a database that already has the earlier ones, and nothing is duplicated.
Existing rows are never updated, which is a deliberate trade-off: the seed can never overwrite content in a database. The cost is that editing an existing post in the seed means removing it from the database first, so it gets seeded again.
Design
The look is meant to be minimal and quiet, so the projects carry the page. One layout rule does most of the work: the header, every section and the footer share one container, so all content starts on the same vertical line at every screen width. Long text, like this post, is held to a comfortable reading width but stays on that left edge.
The one decorative element is a wave in the background. A small script
uses an IntersectionObserver to note which section is in the
middle of the screen, and CSS drifts, fades and tints the wave for that
section. Transitions only switch on after the first paint, so the page
doesn't flash on load. The skill icons are SVG files served with the
site, so no third-party CDN is involved.
Blog posts
A post's body is stored as HTML and rendered as is. That is only safe because every post comes from the seed in the repository. If posts ever became editable in the browser, the HTML would have to be sanitized first. The figures and screenshots in the posts are plain image files with set dimensions and lazy loading, so they don't shift the page while it loads.
Related project
This Portfolio Website
This site itself — a server-rendered ASP.NET Core application backed by EF Core and SQL Server, built specifically to demonstrate the Microsoft development stack.