A personal portfolio and playground built with Blazor Server on .NET 10, deployed to Azure. It's part CV, part side-project showcase — live API integrations, a dark/light mode toggle, and a handful of genuinely useful dashboards rather than lorem-ipsum filler content.
Live: marksmith-portfolio.azurewebsites.net
| Page | What it does |
|---|---|
| Home | Hero intro, quick stats, links to the rest |
| Projects | GitHub repos pulled live from the API + side-project cards |
| Skills | Work history timeline, education, tech badges |
| Contact | Email form (SMTP via Gmail app password) |
| NASA APOD | Astronomy Picture of the Day — date picker + random |
| SpaceX | Upcoming & past launches with mission patch images |
| Weather | Current conditions for a few cities, °C/°F toggle |
| F1 Dashboard | Driver standings, constructor standings, last race results, calendar — season selector |
- Blazor Server — .NET 10, C#
- Bootstrap 5 + custom CSS design system (CSS variables, dark mode)
- Font Awesome icons
- IMemoryCache — thread-safe, TTL-based caching across all services
- DotNetEnv —
.envfile for local secrets (API keys) - Azure App Service — hosting
- GitHub Actions — CI/CD (build + deploy on push to
master)
| API | Auth | Used for |
|---|---|---|
| GitHub REST API | None (public) | Projects page repos |
| NASA APOD | API key (env var) | NASA page |
| SpaceX API (r/SpaceX) | None | SpaceX page |
| Jolpica / Ergast F1 | None | F1 Dashboard |
| Weather API | API key (env var) | Weather page |
Prerequisites: .NET 10 SDK
git clone https://github.com/marksmith1994/MyPortfolio.git
cd MyPortfolioCreate a .env file in the project root:
Nasa__ApiKey=your_nasa_key
Weather__ApiKey=your_weather_key
Email__GmailAddress=you@gmail.com
Email__GmailPassword=your_gmail_app_password
GitHub__Token=your_github_pat
The double-underscore (
__) maps to the:separator in ASP.NET Core's configuration system (e.g.Nasa__ApiKey→Nasa:ApiKey). Azure App Service application settings follow the same convention.
Then run:
dotnet run- NASA and Weather API keys are free — get them at api.nasa.gov and weatherapi.com.
GitHub__Tokenis optional but recommended — without it the GitHub API is limited to 60 requests/hour per IP; a personal access token (read-only, public repos scope) raises this to 5,000/hour.Email__GmailPasswordshould be a Gmail app password, not your account password.
MyPortfolio/
├── Components/
│ ├── Layout/ # MainLayout, NavMenu
│ ├── Pages/ # One .razor file per page
│ └── Shared/ # Timeline, LoadingSkeleton, etc.
├── Services/ # One service per API (models co-located)
├── wwwroot/
│ ├── css/ # base.css + per-page CSS files
│ ├── js/ # theme.js (dark/light toggle)
│ └── data/ # skills-data.json
├── plan/
│ └── TODO.md # Ongoing improvement backlog
└── .github/workflows/ # GitHub Actions CI/CD
Every push to master triggers the GitHub Actions workflow:
- Build with
dotnet build --configuration Release - Publish with
dotnet publish - Deploy to Azure App Service (
marksmith-portfolio) via OIDC (no stored credentials)