Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Setting Up a New Machine with One Command: Brewfile, WinGet Configuration, Runtime Versions with mise and Bootstrapping
The way to set up a new machine with one command is to split the job into layers: a Brewfile or WinGet Configuration installs machine tools, mise pins project versions with global.json and mise.toml, chezmoi applies dotfiles and just setup prepares the project. We show Bookstore's rerunnable bootstrap scripts, schema validation of the WinGet file, mise's trust question and mise exec installing missing tools by itself.
Dotfiles: Keeping Your Settings in Git, Syncing with chezmoi or Stow and Not Leaking Secrets
There are three ways to keep dotfiles in Git: a bare repo, GNU Stow and chezmoi; with several operating systems and secrets, chezmoi leaves the least manual work. We try all three in a fake home folder: the add -A trap in a bare repo, Stow folding the .config folder and --adopt overwriting the repo, templates and .chezmoiignore in chezmoi, previewing Windows output with --override-data, age encryption and a made-up token gitleaks didn't catch.
Collecting Project Commands in One Place: justfile, Makefile, npm scripts, dotnet tools and C# File-based Apps
Collect project commands in a justfile in the repo instead of the README, and make CI call the same recipes. With real output we show Bookstore's justfile (parameters, .env, starting the API and Angular together with [parallel], PowerShell on Windows), a comparison with Makefiles and npm scripts, the local .NET tool manifest, dnx's -- pitfall, and a seed tool written as a .NET 10 file-based app.
Your Own Project Template: a Bookstore Template with dotnet new and a Short Look at Angular Schematics
A dotnet new template is an ordinary .NET solution with a .template.config/template.json file; with sourceName, parameters and conditional content it generates a new Bookstore service in one command. With real output we cover packing the template, installing it from a local feed, the port generator, the .dockerignore lost without NoDefaultExcludes, a diff showing that the 1.1.0 update leaves old projects unchanged, and a custom Angular schematic.
Writing Snippets and Live Templates: Your Own C# and Angular Shortcuts in VS Code, Visual Studio and Rider
A snippet is the right tool for the small skeletons the language's syntax makes you type every time, not for repeated logic. We show VS Code snippets for Bookstore's xUnit v3 test, minimal API endpoint group, EF Core configuration and Angular 22 component, a transform that derives the namespace from the file path, the Visual Studio .snippet and Rider live template equivalents, and the .gitignore line that silently ignores the snippet file.
Exposing Localhost and Mock Servers: Dev Tunnels, Cloudflare Tunnel, ngrok, Prism and WireMock.Net
Receiving the payment provider's webhook on Bookstore.Api at localhost needs a tunnel, but what protects the API is the signature, not the tunnel. We try a webhook endpoint with an HMAC signature and a timestamp tolerance locally with real output, compare Dev Tunnels, Cloudflare's quick tunnel and ngrok by their access settings, and build a Prism mock from OpenAPI that returns 401 and 422 plus a WireMock.Net carrier mock with scenarios and delays.
Capturing HTTP Traffic: Seeing, Modifying and Replaying Browser, HttpClient and Angular Dev Server Requests with mitmproxy and Fiddler
To see Bookstore.Api's HTTPS call to the carrier API, we run mitmproxy on 127.0.0.1, point HttpClient at it with HTTPS_PROXY and give the CA to that client only, never to the OS. A Python addon delays the response by 3 seconds so we watch timeouts and retries in real output (the user gets a 503 while the carrier creates three quotes), then we cover filters, saving and replay, the Angular dev server, Chromium's loopback exception and Fiddler's capture modes.
jq and yq in Depth: Querying, Transforming and Editing JSON and YAML on the Command Line
jq returns a missing field as null instead of an error and exits with 0 on empty results too; add -e to every filter you use as a condition in CI. With output from Bookstore.Api, kubectl, dotnet list package and the GitHub API we show select, group_by, reduce inputs, --arg/--argjson and @csv, updating an image tag with yq while keeping comments, the two different yq tools and Windows quoting.
Validating Configuration with JSON Schema: Editor IntelliSense, SchemaStore and Validation in CI
The .NET binder silently ignores a misspelled settings key; additionalProperties: false in JSON Schema catches it while you write the file and in CI. We write a 2020-12 schema for Bookstore.Api and validate with SchemaStore, a VS Code mapping, a YAML schema comment, check-jsonschema, ajv and JsonSchema.Net, showing with real output how mixed drafts and format checking differ.
TOML, INI, .env and the Rest: Which Configuration Format When?
Choose by who reads the file: if .NET is the only reader, JSON and environment variables are enough; if several tools read the same .env, write it in the strictest common subset. We read one .env with Compose, Node.js, dotenv, python-dotenv and bash, one INI with .NET, Python and git, and show the differences, TOML 1.1's date types and Bookstore.Api's setting in five formats becoming one configuration.
YAML 2: Multiline Strings, Anchors/Aliases, Merge Keys, Multiple Documents and KYAML
Write scripts with |, long prose with >, and use |- for single-line values such as secrets, otherwise a \n is appended. The merge key (<<) is not in YAML 1.2: Compose, kubectl and kubeconform support it, GitHub Actions does not, and js-yaml 5 needs an option. We show multiple documents, the document boundary of anchors, unsafe tags, KYAML and a yamllint rule set for Bookstore with real output.
YAML 1: Syntax, Types and the "Norway Problem": Reading a YAML File Correctly
The type of an unquoted YAML value depends on the rule set the parser applies: in YAML 1.1 NO is false, 12:30 a number and 0755 octal; in YAML 1.2 all three differ. We run PyYAML, ruamel.yaml, js-yaml, YamlDotNet, yq, Docker Compose and kubectl on the same file and show three real type errors in Bookstore's compose.yaml and Kubernetes manifest.