<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Projects on csMACnz&#39;s Blog</title>
    <link>https://blog.csmac.nz/categories/projects/</link>
    <description>Recent content in Projects on csMACnz&#39;s Blog</description>
    <image>
      <url>https://blog.csmac.nz/favicon.png</url>
      <title>csMACnz&#39;s Blog</title>
      <link>https://blog.csmac.nz</link>
    </image>
    <ttl>1440</ttl>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-nz</language>
    <lastBuildDate>Tue, 07 Apr 2026 01:11:00 +0000</lastBuildDate><atom:link href="https://blog.csmac.nz/categories/projects/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Vibe Coding up a Vibe Blogging Machine</title>
      <link>https://blog.csmac.nz/post/vibe-coding-up-a-vibe-blogging-machine/</link>
      <pubDate>Tue, 07 Apr 2026 01:11:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/vibe-coding-up-a-vibe-blogging-machine/</guid>
      <description>&lt;p&gt;Introducing VibeBlog, my playground for exploring GitHub&amp;rsquo;s agentic workflows (that&amp;rsquo;s the whole AI-powered automation thing everyone&amp;rsquo;s talking about). It&amp;rsquo;s also a daily experiment in AI-generated writing—one post per day, initially curated from my own knowledge but eventually evolving into a learning tool based on whatever topics catch my interest. The goal? Produce publicly useful content while I play copyeditor to Copilot&amp;rsquo;s drafts, turning AI output into genuinely informative articles.&lt;/p&gt;
&lt;p&gt;Seriously, as a learning exercise in various Github Copilot features, it has been great fun to build out a daily generated blog site with minimal human-in-the-loop vibes.&lt;/p&gt;
&lt;p&gt;What follows is a bit of a diary of the development and how I got here.&lt;/p&gt;
&lt;h2 id=&#34;the-setup&#34;&gt;The Setup&lt;/h2&gt;
&lt;p&gt;I didn’t start by “writing posts.” I started by building a machine that could publish them reliably.&lt;/p&gt;
&lt;p&gt;When creating a repository in GitHub, you can start with an initial prompt, So I did.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A static site generated blog. Articles will be written and stored as markdown and rendered as a static site. Uses GitHub Actions to build and publish. Agwntic instruction files will support copilot agent tasks to write the posts.&lt;/p&gt;
&lt;p&gt;C# is the preferred language for any code used in this repository&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yeah, I went with what I know, C#. I could have left it up to the AI but I did want to at least feel confident that what it produced was valid, safe and maintainable code.&lt;/p&gt;
&lt;p&gt;While I did review what it created, I left this as the first prototype and commited without change. As I went on, reviews often fell into more of a YOLO camp, but I did try to stick to a couple of guardrails:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Read everything before it gets merged&lt;/li&gt;
&lt;li&gt;Don&amp;rsquo;t produce any commits directly&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(I only had a couple of late-stage exceptions to that second rule, due to trying to save a few premium session tokens on one-lineer changes.)&lt;/p&gt;
&lt;p&gt;This PR was complete enough that will a few extra clicks to enable GitHub Pages, I had a live blog with a working generator and deploy pipeline within minutes of creating the repo. From there, I just iterated on the codebase and the agentic workflow, with the goal of making it more robust and more automated over time.&lt;/p&gt;
&lt;p&gt;From this point on, every PR started as an agentic session prompt, and proceeded as a Pull Request collaboration workflow.&lt;/p&gt;
&lt;p&gt;I went straight into a CICD mindset and added automated tests, especially leveraging playwright, and some GitHub Actions for doing more robust build and deploy. The first prompt out of the gate did manage to provide a build and deploy which was great.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It looks like we gave no tests. We should add some xunit and playwright .net tests for both the generator app and the generated site. These tests should be part of the github actions, and verified against pull requests too.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fortunately for me, I was able to give a very vague prompt for CI and it ran with it, producing more and better that I probably would have even thought to ask for.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Review the github actions for build and test and offer improvements&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I went through a short manual testing and feedback phase at this point, where I identified some bugs. Since I was already using a custom domain for GitHub Pages, it did require a little bit of change to make the expected relative paths work, but that was a quick fix. From this, I layered on some extra integrity checking of the site as well.&lt;/p&gt;
&lt;p&gt;I managed to even get it to scrape my styles from the existing blog for consistency. This was a lesson on the Github copilot Firewall configuration. It wasn&amp;rsquo;t perfect, but it got the job done with a bit of iteration.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/agents/pull/14&#34;&gt;Updating site design to align with parent blog&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The style of the site needs updated. Id like to follow the style of the existing parent site blog.csmac.nz Ensure the pull request has a screenshot of the design attached as a comment. Please make sure you also download background images referenced in the css for reuse in this site as well&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As I went, I tried to add additional improvement to both avoid regression, and add automation to catch the same or similar issues from resurfacing. Each time it did something wrong, I would correct it, but ask it to &amp;ldquo;remember&amp;rdquo; essentially.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Please fix this articles title length.&lt;/p&gt;
&lt;p&gt;Please also update the agent prompts to always enforce this, even if the title provided is too long, enforce a shorter alternative title to the suggested one. This restriction is higher priority than keeping the suggested title.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;becoming-a-publishing-platform&#34;&gt;Becoming a publishing platform&lt;/h2&gt;
&lt;p&gt;The foundations were set, now the writing could begin.&lt;/p&gt;
&lt;p&gt;This went through a couple of refining phases:&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/5&#34;&gt;Updating Copilot agent instructions toward the actual writing style&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Take a look at my site &lt;a href=&#34;https://github.com/csMACnzBlog/csMACnzBlog.github.io&#34;&gt;https://github.com/csMACnzBlog/csMACnzBlog.github.io&lt;/a&gt; and improve the writing style guidance to match my writing style in github copilot markdown instructions&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/18&#34;&gt;Enhance blog-post-writer style guide with patterns from csMACnzBlog&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I would like a review of the writing style from the articles on blog.csmac.nz compared with the writing style used in this VibeBlog so far. I would like to enhance the style guides in this repository with any missing refinements or details for producing future posts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This improved the voice of the articles. These two prompts together did a great job of refining the style and tone of the writing, and I was pretty happy with the results. It was able to pick up on some of the nuances of my writing style that I hadn&amp;rsquo;t explicitly called out in the instructions, which was great. The &lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/blob/main/.copilot/agents/blog-post-writer.md&#34;&gt;final blog-post-writer.md agent&lt;/a&gt; is now pretty detailed and specific, and I think it will do a good job of maintaining a consistent voice across future posts.&lt;/p&gt;
&lt;h2 id=&#34;robustness-phase&#34;&gt;Robustness phase&lt;/h2&gt;
&lt;p&gt;I followed up by adding some more robustness to the publishing process, with a focus on making sure that the quality gates were in place and that the agent instructions were well-defined and versioned. This included:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Featured image support: &lt;strong&gt;PR #20&lt;/strong&gt; (merged &lt;strong&gt;2026-02-27&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/20&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/20&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Adding baseline validation steps to that setup flow: &lt;strong&gt;PR #102&lt;/strong&gt; (merged &lt;strong&gt;2026-03-28&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/102&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/102&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pagination (15 posts/page): &lt;strong&gt;PR #62&lt;/strong&gt; (merged &lt;strong&gt;2026-03-18&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/62&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/62&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Search page via lazy-loaded modal iframe: &lt;strong&gt;PR #64&lt;/strong&gt; (merged &lt;strong&gt;2026-03-19&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/64&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/64&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Search UX fixes + tag focus/order: &lt;strong&gt;PR #66&lt;/strong&gt; (merged &lt;strong&gt;2026-03-19&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/66&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/66&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Clicking a tag opens search pre-filtered: &lt;strong&gt;PR #103&lt;/strong&gt; (merged &lt;strong&gt;2026-03-29&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/103&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/103&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;image-generation&#34;&gt;Image Generation&lt;/h2&gt;
&lt;p&gt;This took a few iterations to get working but I was able to leverage some python and the Hugging Face API to get some blog images being generated for me as part of the build process. This was a fun one to iterate on, and I had to learn a bit about how to use the Hugging Face API and how to handle credentials in GitHub Actions. I tried out the familiarity of Powershell to start with but in the end went with what the models know best - Python. I also had to iterate on the prompt a bit to get it to generate images that were actually relevant and looked good. I ended up with a pretty good prompt that I can reuse for future image generation tasks as well. Maybe as a reduction exercise I&amp;rsquo;ll see if I can migrate what I have back to Powershell, but for now I&amp;rsquo;m happy with the Python solution.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Image generation pipeline moved from PowerShell → Python + HuggingFace client: &lt;strong&gt;PR #21&lt;/strong&gt; (merged &lt;strong&gt;2026-02-27&lt;/strong&gt;)&lt;br&gt;
&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/21&#34;&gt;https://github.com/csMACnzBlog/Vibeblogging/pull/21&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It did take a bunch of trial-and-error to get the credentials and API calls working correctly, but I got there in the end. The images are now being generated and uploaded to the site as part of the PR generation lifecycle process, which is pretty cool. Most of my drama came from fighting different environment sandboxes and differences between Copilot, and Workflow.&lt;/p&gt;
&lt;p&gt;I even did a bit of experimenting with the new &lt;a href=&#34;https://github.github.com/gh-aw/&#34;&gt;https://github.github.com/gh-aw/&lt;/a&gt;. It is pretty cool, but wasn&amp;rsquo;t the right tool for this particular job, since the repository sits public in the open. But I have some ideas for how I might be able to leverage it in the future for some of my more private repositories, so it was worth playing around with it a bit.&lt;/p&gt;
&lt;h2 id=&#34;finishing-the-automation&#34;&gt;Finishing the automation&lt;/h2&gt;
&lt;p&gt;I had a pretty good workflow going at this point, but I wanted to get to the point where I could just merge a PR and have it go live without any manual steps. This involved making sure that all the quality gates were in place and that the agent instructions were well-defined.&lt;/p&gt;
&lt;p&gt;I was still triggering and reviewing the daily post generation manually, but I wanted to get to the point where it was fully automated. So I tried a few different strategies and landed on the following approach:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;In another repository, I trigger the creation of a new Issue into the repository, and assign it to Copilot to work on&lt;/li&gt;
&lt;li&gt;Copilot then creates a new branch, and starts working on the post in that branch, using the agent instructions and style guide to produce the content&lt;/li&gt;
&lt;li&gt;Once the post is ready, it creates a PR from that branch into main, and assigns it to me for review&lt;/li&gt;
&lt;li&gt;Another automation checks over the PR for quality gates (links, accessibility, etc) and if it passes, it merges the PR automatically, which triggers the build and deploy process to publish the new post&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I read every post daily. So far I haven&amp;rsquo;t really had to make any changes to the articles, and find them both accurate and interesting to read.&lt;/p&gt;
&lt;p&gt;I even followed up with an automation that can investigate a topic suggestion and raise a more detailed Issue. If one of these is present, it uses that to assign to copilot instead of the generic &amp;ldquo;write a post about X&amp;rdquo; issue. This allows me to have a bit more control over the topic and the direction of the post, while still leveraging the automation to do the heavy lifting of writing and publishing.&lt;/p&gt;
&lt;h2 id=&#34;a-working-system&#34;&gt;A working system&lt;/h2&gt;
&lt;p&gt;By early April 2026, the engineering arc looks like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A C# generator that deploys cleanly to Pages (&lt;strong&gt;PR #1&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;CI + testing from day one (&lt;strong&gt;PR #2&lt;/strong&gt;, &lt;strong&gt;PR #4&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Deployment correctness handled early (subpath link fix) (&lt;strong&gt;PR #9&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Publishing quality gates baked in (&lt;strong&gt;PR #10&lt;/strong&gt;, &lt;strong&gt;PR #105&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Agent instructions + setup treated as versioned system components (&lt;strong&gt;PR #5&lt;/strong&gt;, &lt;strong&gt;PR #6&lt;/strong&gt;, &lt;strong&gt;PR #24&lt;/strong&gt;, &lt;strong&gt;PR #102&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Media pipeline with real-world credential iteration (&lt;strong&gt;PR #20&lt;/strong&gt;, &lt;strong&gt;PR #21&lt;/strong&gt;, &lt;strong&gt;PR #88&lt;/strong&gt;, &lt;strong&gt;PR #92&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Scale features (pagination + search) (&lt;strong&gt;PR #62&lt;/strong&gt;, &lt;strong&gt;PR #64&lt;/strong&gt;, &lt;strong&gt;PR #66&lt;/strong&gt;, &lt;strong&gt;PR #103&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;A daily agentic publishing workflow that’s been battle-tested through break/fix cycles (&lt;strong&gt;PR #68&lt;/strong&gt;, &lt;strong&gt;PR #79–#86&lt;/strong&gt;, &lt;strong&gt;PR #77/#87&lt;/strong&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Towards this later couple of weeks I&amp;rsquo;ve been focusing more on the main site and blog, trying to tie this new part into the larger site more seamlessly. This has identified many opportunities to apply similar learnings back to the way I opperate in the rest of the site&amp;rsquo;s development.&lt;/p&gt;
&lt;h2 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h2&gt;
&lt;p&gt;Well I&amp;rsquo;m pretty well set up for the moment. At some point topic choice might get interesting, and I don&amp;rsquo;t know what the LLM is going to do. I do have my mechanism to generate topics and topic notes, so perhaps that feeds it for a while. It is one I am very interested to watch.&lt;/p&gt;
&lt;p&gt;Otherwise, I just need to keep an eye on the daily workflow and make sure it doesn&amp;rsquo;t break. I have a good sense of what the failure modes are, so hopefully I can catch and fix them quickly if they come up. And since it runs on GitHub workflows, I get notifications when it fails, so that should help me stay on top of it.&lt;/p&gt;
&lt;p&gt;Security is always a concern, but since this is a public repo with no sensitive data, the main risk is someone trying to break the workflow or inject bad content. I&amp;rsquo;ll need to monitor for that and be ready to revert if necessary. Hopefully I&amp;rsquo;ve locked down enough of the accesses that it is resilient to obvious attack vectors.&lt;/p&gt;
&lt;h2 id=&#34;appendix&#34;&gt;Appendix&lt;/h2&gt;
&lt;p&gt;Some of the PRs are referenced directly for your interest and further reading.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/1&#34;&gt;PR #1: Generator + Pages deploy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/2&#34;&gt;PR #2: xUnit + Playwright + CI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/4&#34;&gt;PR #4: CI/CD optimizations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/9&#34;&gt;PR #9: fix broken links&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/10&#34;&gt;PR #10: quality gates (link/html/a11y)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/20&#34;&gt;PR #20: featured images&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/21&#34;&gt;PR #21: image pipeline → Python/HF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/24&#34;&gt;PR #24: copilot-setup-steps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/62&#34;&gt;PR #62: pagination&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/64&#34;&gt;PR #64: search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/68&#34;&gt;PR #68: daily-post workflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PR #79–#86: hardening fixes&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/102&#34;&gt;PR #102: baseline validation in setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/105&#34;&gt;PR #105: a11y runner fix&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnzBlog/Vibeblogging/pull/119&#34;&gt;PR #119: example content PR (Rate Limiting)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
    </item>
    
    <item>
      <title>An almost seamless transition from Ghost to Hugo</title>
      <link>https://blog.csmac.nz/post/an-almost-seamless-transition-from-ghost-to-hugo/</link>
      <pubDate>Tue, 10 Aug 2021 20:30:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/an-almost-seamless-transition-from-ghost-to-hugo/</guid>
      <description>&lt;p&gt;Well, I finally did it. Ghost has been sitting on an older version for a long time, my certs were expiring, and I did something about it.&lt;/p&gt;
&lt;h2 id=&#34;tldr&#34;&gt;TL;DR;&lt;/h2&gt;
&lt;p&gt;My blog engine and hosting were deteriorating fast, so I moved to GitHub Pages, Hugo, and Static Site Generation, (mostly) without losing or breaking anything.&lt;/p&gt;
&lt;h2 id=&#34;synopsys&#34;&gt;Synopsys&lt;/h2&gt;
&lt;p&gt;Years ago I moved from WordPress to Ghost. This let me get on with writing and not worrying about the hosting. I moved it to Azure and even added a dynamic SSL certificate rotator using Lets Encrypt.&lt;/p&gt;
&lt;p&gt;Eventually, the cert rotator broke, and the blog engine got enough major versions behind to make the upgrade path non-trivial to fix. Not to mention Google Ads decided my site wasn&amp;rsquo;t good enough for them and so disabled any ads that could have shown up. Hosting costs on Azure, while small, were a factor to think about too.&lt;/p&gt;
&lt;p&gt;Around the time I decided to do something about it, I also started paying attention to other people using static site generation to host their blogs. It didn&amp;rsquo;t take long to find a few really great articles that showed how simple this was going to be. The simplest of which seemed to be &lt;a href=&#34;https://gohugo.io/&#34;&gt;Hugo&lt;/a&gt; on &lt;a href=&#34;https://pages.github.com/&#34;&gt;GitHub Pages&lt;/a&gt;. So that is the path I went down.&lt;/p&gt;
&lt;h2 id=&#34;what-went-well&#34;&gt;What went well&lt;/h2&gt;
&lt;p&gt;My initial research was well-founded, and I very easily found the tool &lt;a href=&#34;https://github.com/jbarone/ghostToHugo&#34;&gt;jbarone/ghostToHugo&lt;/a&gt; designed for the job.&lt;/p&gt;
&lt;p&gt;Initially, everything was super simple, and I had my content in Hugo in under an hour. Mainly I was following youngkin&amp;rsquo;s article: &lt;a href=&#34;https://youngkin.github.io/post/createafreeblogsite/&#34;&gt;Create a Free Blog Site Using GitHub Pages and Hugo&lt;/a&gt;, and then using ghostToHugo for my content.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://gohugo.io/getting-started/installing/&#34;&gt;Install Hugo CLI locally&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;create basis repository setup with the suggested theme &lt;a href=&#34;https://youngkin.github.io/post/createafreeblogsite/&#34;&gt;youngkin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://ghost.org/help/the-importer/&#34;&gt;export my Ghost backup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;install &lt;a href=&#34;https://github.com/jbarone/ghostToHugo&#34;&gt;ghostToHugo&lt;/a&gt; tool&lt;/li&gt;
&lt;li&gt;run ghostToHugo to migrate posts into the site&lt;/li&gt;
&lt;li&gt;run locally to test&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;(I&amp;rsquo;m not repeating details here, because &lt;a href=&#34;https://youngkin.github.io/post/createafreeblogsite/&#34;&gt;youngkin&lt;/a&gt; has it nailed.)&lt;/p&gt;
&lt;p&gt;Getting this running on GitHub Pages was easy following that article too. Even setting a CNAME and DNS (a temporary subdomain while testing of course) was nice and easy to get working. (I use &lt;a href=&#34;https://dnsimple.com/&#34;&gt;DNSimple&lt;/a&gt;.) Job done. Right?&lt;/p&gt;
&lt;h2 id=&#34;what-went-wrong&#34;&gt;What went wrong&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;RSS.&lt;/strong&gt; My RSS feed has been a bit of an issue really. I knew it would probably break, and it wasn&amp;rsquo;t even available out of the box on Hugo either. So I fevered away adding RSS generation to the site generation and getting a fair approximation of my old feed. I knew it wouldn&amp;rsquo;t be perfect, but I learned a bit about how the templating engine worked along the way. And when that hot cutover day came, it certainly failed. I had a few bugs to fix and all 50 people who have added this blog to their feed probably got a bit of a noisy mess. But hopefully, as they now read this article they now understand why. Also, there are now sub-categories with sub-category RSS feed URLs linked to from the right-hand sidebar now.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Custom Theming.&lt;/strong&gt; I built my custom theme way back when I moved to Ghost. And I didn&amp;rsquo;t really feel like losing it. So I painstakingly mapped it from the Ghost templating engine to the one Hugo uses. This sucked. and it took ages (weeks) to get it right. Along the way, I probably did make some improvements that will be valuable later, like fixing the sidebar and better image handling possibilities. But this was probably the most time-consuming part of the whole process. In the end, retrologs&amp;rsquo; &lt;a href=&#34;https://retrolog.io/blog/creating-a-hugo-theme-from-scratch/&#34;&gt;Creating a Hugo Theme From Scratch&lt;/a&gt; was super useful at figuring out what went where, but I don&amp;rsquo;t actually understand some parts of the collection lookup code I wrote in some places yet. But it worked. At the very least, my CSS appears to have held the test of time (surprisingly!).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Permalinks.&lt;/strong&gt; Turns out Ghost had a few permalink redirect capabilities. And also the default URLs in Ghost were &lt;code&gt;/slug-for-page/&lt;/code&gt; while Hugo is &lt;code&gt;/post/slug-for-page/&lt;/code&gt;. Luckily the &lt;a href=&#34;https://gohugo.io/content-management/urls/#aliases&#34;&gt;Aliases feature in Hugo&lt;/a&gt; allowed me to add both the draft/preview link (&lt;code&gt;/p/&amp;lt;GUID&amp;gt;/&lt;/code&gt;) as well as the old URL so that hopefully, no one loses my content, and instead get bounced to the right place.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disqus.&lt;/strong&gt; See the comments at the bottom? I&amp;rsquo;ve been using Disqus to make them available. Turns out this was quite useful in moving to a static hosted solution. For the most part, this went well, because Disqus actually have a &lt;a href=&#34;https://help.disqus.com/en/articles/1717068-migration-tools&#34;&gt;migration tools feature&lt;/a&gt; available to use to move the URL associated with a page. The what went wrong part was that I prepared all the pages that looked like the normal post URL (&lt;code&gt;/slug-for-page/&lt;/code&gt;) before I cut over my DNS, but didn&amp;rsquo;t map any of the preview URLs (&lt;code&gt;/p/&amp;lt;GUID&amp;gt;/&lt;/code&gt;) across. I think what happened is that Ghost provided an id to Disqus as well as a URL, and it uses the first URL it sees as the identifying one. When I preview drafts, that preview URL is the one it saves. Since Hugo is just using the actual URL and not the id anymore, I lost my mapping over a few pages which I neglected to migrate. (My incorrect assumption was the draft ids didn&amp;rsquo;t have comments 😢.) I was without comments on some pages while I remedied that across a couple of evenings. It wasn&amp;rsquo;t too bad to put together a new CSV file for that though in the end.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Google Ads.&lt;/strong&gt; Turns out they are still not happy with my website (and neither am I to be fair) so there is a bit more work to get them reenabled. It barely makes dollars a month, to be honest, but with it not working it makes a lot less of course.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Content.&lt;/strong&gt; I spent far too much time looking at my content. While Ghost had tags, Hugo has both &lt;a href=&#34;https://blog.csmac.nz/tags/&#34;&gt;Tags&lt;/a&gt; and &lt;a href=&#34;https://blog.csmac.nz/categories/&#34;&gt;Categories&lt;/a&gt;. I went through every historic post (193 over 13 and a half years if you can believe it) and updated many tags (deleting a bunch, adding a few) and creating categories for my content. I could have spent days (and still might) tidying up some of the content that never had any attention since coming out of WordPress and getting auto-converted to markdown all those years ago. But I held back, since I wanted to actually get this process done and back to writing. There was a little bit of work migrating some of the image functionality over too, but for the most part that was fine, too.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary&lt;/h2&gt;
&lt;p&gt;Would I choose to do it again? Yes. I am certainly in a better place. So far, I think I&amp;rsquo;ve backed the right horse in Hugo. The workflow seems about as good as it was before, and I am aware of a few tools such as &lt;a href=&#34;https://cloudcannon.com/&#34;&gt;CloudCannon&lt;/a&gt; for better CMS management workflows if I desire. I might miss the Ghost app for drafts, but I mostly write on my desktop anyway. And since it is in GitHub, anything that can commit markdown to there is a way to draft.&lt;/p&gt;
&lt;p&gt;Now that I have that done, the next step is likely to repeat the whole process with &lt;code&gt;csmac.nz&lt;/code&gt; as well and fix its certs, ads, and content. (That last one has been bugging me since I moved to Ghost to be fair&amp;hellip; &lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt;)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Time-tracking Analysis - Parsing and Presenting a Heatmap of your working week from Toggl Data</title>
      <link>https://blog.csmac.nz/post/time-tracking-analysis/</link>
      <pubDate>Mon, 27 Aug 2018 06:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/time-tracking-analysis/</guid>
      <description>&lt;p&gt;As a remote worker, I need to keep myself honest. This is as much &amp;ldquo;Make sure I do my hours&amp;rdquo; as it is &amp;ldquo;Don&amp;rsquo;t overwork!&amp;rdquo;. Anyone who has worked from home or remotely for a period of time understands what I mean completely.&lt;/p&gt;
&lt;p&gt;To monitor this, I use &lt;a href=&#34;https://www.toggl.com&#34;&gt;Toggl&lt;/a&gt;. Toggl is time-tracking as a service, which includes cloud tracking data storage, annotating time against projects and clients, and Client applications for most if not all platforms including web, mobile and desktop. Tracking is even done server side so you can start your timer on one device, and stop it from another. As I say, you can annotate your time with Client, Project, even custom tags.&lt;/p&gt;
&lt;p&gt;Toggl has a bunch of advanced time-coding features to produce reports against different projects. If you pay for their starter plan, it can even handle Billable Time. I don&amp;rsquo;t use any of that. I use their Windows Desktop client (which includes idle time detection to easily clear &lt;a href=&#34;https://www.grammarly.com/blog/afk-meaning/&#34;&gt;AFK&lt;/a&gt; time) and their online data storage, to hold onto my data for me.&lt;/p&gt;
&lt;p&gt;I created this little tool to help me visualise my work patterns as a bit of a heatmap. This was a way for me to answer the question &amp;ldquo;What are my &amp;lsquo;office hours&amp;rsquo;&amp;rdquo; as well as an indication of my work patterns for my team.&lt;/p&gt;
&lt;h3 id=&#34;the-instructions&#34;&gt;The instructions&lt;/h3&gt;
&lt;h4 id=&#34;exporting-data&#34;&gt;Exporting Data&lt;/h4&gt;
&lt;p&gt;Using the Toggl Reports, I can select a time period of data I want to have access to. (Instructions &lt;a href=&#34;https://support.toggl.com/tag/export/&#34;&gt;here&lt;/a&gt;.) I select a range, say the last year, and then export as CSV.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://res.cloudinary.com/csmacnz/image/upload/c_scale,w_600/v1534489912/TogglExport_wzkiix.png&#34; alt=&#34;Export Toggl Report data using detailed.&#34;&gt;&lt;/p&gt;
&lt;p&gt;Make sure that you are Exporting a Detailed report. Your file will be named like &amp;ldquo;Toggl_time_entries_2016-01-01_to_2016-12-31.csv&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;The format of this file should be like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;User,Email,Client,Project,Task,Description,Billable,Start date,Start time,End date,End time,Duration,Tags,Amount ()
First Last,first.last@email.address,,,,&amp;#34;&amp;#34;,No,2016-05-04,10:00:00,2016-05-04,13:00:00,03:00:00,,
First Last,first.last@email.address,,,,&amp;#34;&amp;#34;,No,2016-05-04,14:00:00,2016-05-04,16:00:00,02:00:00,,
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In theory, anyone could create a CSV in this format and this tool will work just fine for them too. I only use the &lt;code&gt;Start date,Start time,End date,End time,Duration&lt;/code&gt; fields anyway.&lt;/p&gt;
&lt;h4 id=&#34;process-the-data&#34;&gt;Process the data&lt;/h4&gt;
&lt;p&gt;Now that I have a local CSV file, I can process it through my application.&lt;/p&gt;
&lt;p&gt;I have made this available as a dotnet tool, so you can easily install it globally and run it from anywhere.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmd&#34; data-lang=&#34;cmd&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# install globally
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dotnet tool install -g TogglHeatmap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# if installed globally, this should just be available on your path
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TogglHeatmap &amp;lt;args&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# install into a local folder
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dotnet tool install TogglHeatmap --tools-path tools
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# if installed into a tools path, you can run it from there.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;.\tools\TogglHeatmap &amp;lt;args&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For those new to tools, there is also an update option if newer versions come available, as well as a version parameter if you require a specific version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmd&#34; data-lang=&#34;cmd&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dotnet tool install -g TogglHeatmap --version 1.0.0
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# update doesn&amp;#39;t support version but instead gets the latest
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dotnet tool update -g TogglHeatmap
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# to replace with a specific version, first uninstall, then install with specific version required specified.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;At this stage, the args for the application are as follows (subject to change, check &lt;code&gt;TogglHeatmap --help&lt;/code&gt; for latest):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmd&#34; data-lang=&#34;cmd&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# Start and End dates
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TogglHeatmap dataFile.csv 2018-01-01 2018-06-01
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;# Start and week count
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;TogglHeatmap dataFile.csv 2018-01-01 26
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This should produce a nice report of numbers to the console output:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;&amp;gt; TogglHeatmap Toggl_time_entries_2017-08-15_to_2018-08-15.csv 2018-1-1 2018-08-15
Data from 1/1/18 0:00:00 to 15/8/18 0:00:00
First day: Monday
Number of weeks: 32
----
Time,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
00:00,0,13,0,11,0,0,0
00:30,0,8,0,8,0,0,0
01:00,0,4,0,5,0,0,0
01:30,0,2,0,2,0,0,0
02:00,0,0,0,0,0,0,0
02:30,0,0,0,0,0,0,0
03:00,0,0,0,0,0,0,0
03:30,0,0,0,0,0,0,0
04:00,0,0,0,0,0,0,0
04:30,0,0,0,0,0,0,0
05:00,0,0,0,0,0,0,0
05:30,0,0,0,0,0,0,0
06:00,0,0,0,0,0,0,0
06:30,0,0,0,0,0,0,0
07:00,0,0,0,0,0,0,0
07:30,0,0,4,0,0,0,0
08:00,0,0,5,3,4,0,0
08:30,3,5,10,7,6,0,0
09:00,4,10,12,13,6,0,0
09:30,8,17,16,18,10,0,0
10:00,19,22,27,23,26,0,0
10:30,24,20,27,24,23,0,0
11:00,24,21,28,28,22,0,1
11:30,24,20,29,28,22,0,0
12:00,23,22,28,27,21,0,0
12:30,21,20,27,27,21,0,0
13:00,23,20,25,23,21,0,0
13:30,23,21,26,23,23,0,0
14:00,23,23,28,24,22,0,0
14:30,24,24,25,25,24,0,0
15:00,22,25,27,23,25,0,0
15:30,22,24,26,26,24,0,0
16:00,23,27,27,26,24,0,0
16:30,22,25,27,24,24,0,0
17:00,19,21,20,21,16,0,0
17:30,11,18,16,16,7,0,0
18:00,11,19,10,13,6,0,0
18:30,9,13,3,12,5,0,0
19:00,3,9,2,6,5,0,0
19:30,2,9,4,3,3,0,0
20:00,7,4,9,5,2,0,0
20:30,8,7,12,6,2,0,0
21:00,11,6,15,6,2,0,0
21:30,22,6,18,5,1,0,1
22:00,22,4,21,3,1,0,1
22:30,19,1,21,1,1,0,1
23:00,18,1,19,0,0,0,0
23:30,13,1,14,0,0,0,0
----

Copy the data above into a CSV file to make it pretty in a spreadsheet
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We have our heatmap data, and we can copy and save it to a CSV file. Now we can do whatever makes sense to us to present it.&lt;/p&gt;
&lt;h4 id=&#34;spreadsheet-ui&#34;&gt;Spreadsheet UI&lt;/h4&gt;
&lt;p&gt;For instance, you may want to pull it into a Google Sheet. This should be similar for Excel if that is your office suite of choice instead.&lt;/p&gt;
&lt;p&gt;First, create a new Sheet.&lt;/p&gt;
&lt;p&gt;Take your CSV file of data you created before from the output. You can import that file into Sheets. Simply go to &lt;code&gt;File-&amp;gt;Import...&lt;/code&gt; menu, and in the popup and locate your file. Once you have located, uploaded and selected your file, you will get the second dialogue. In this dialogue Select where you want the data to go (for example &lt;code&gt;Insert new sheet&lt;/code&gt;, or &lt;code&gt;Replace current sheet&lt;/code&gt;) and choose &lt;code&gt;Comma&lt;/code&gt; for the Separator type.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://res.cloudinary.com/csmacnz/image/upload/c_scale,w_200/v1534489034/SheetsImportFileDialog_izktyl.png&#34; alt=&#34;Import Sheet dialogue&#34;&gt;&lt;/p&gt;
&lt;p&gt;Once imported, you may want to conditionally colour the numbers. Select cell range from &lt;code&gt;B2&lt;/code&gt; to &lt;code&gt;H49&lt;/code&gt;, Select &lt;code&gt;Format-&amp;gt;Conditional Formatting...&lt;/code&gt; from the menu. In the sidebar that opens on the right, select the &lt;code&gt;Color scale&lt;/code&gt; from the tab at the top, ensure &lt;code&gt;Apply to range&lt;/code&gt; is set to &lt;code&gt;B2:H49&lt;/code&gt; as selected before, And select the colours you want from the drop-down labelled &lt;code&gt;Preview&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://res.cloudinary.com/csmacnz/image/upload/c_scale,w_200/v1534491621/GoogleSheetsColorFormating_nzeuba.png&#34; alt=&#34;Use Color scale Conditional formatting on cells&#34;&gt;&lt;/p&gt;
&lt;p&gt;Click done to finish and enjoy your pretty picture.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;http://res.cloudinary.com/csmacnz/image/upload/c_scale,w_600/v1534492505/HeatmapResult_alnhio.png&#34; alt=&#34;A calendar view with heatmap data on each cell&#34;&gt;&lt;/p&gt;
&lt;h3 id=&#34;analysis&#34;&gt;Analysis&lt;/h3&gt;
&lt;p&gt;For me, this &amp;lsquo;graph&amp;rsquo; above gives me interesting insights, such as that my day is 10am-5pm then Monday nights and Wednesday nights 9:30 pm until 1 am, But I am really working anytime from 8:30 am till midnight early in the week, 8 am till 11 pm later in the week. There is also no correlation for when I take lunch, but dinner break is some time between 6:30 pm and 8 pm.&lt;/p&gt;
&lt;p&gt;These insights are easier to presume from the visual graph, and I can compare these graphs for different periods of the year to see how these insights change.&lt;/p&gt;
&lt;h3 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve got a bunch of ideas to improve the CLI interface for TogglHeatmap. Including just using all the data as the date range without requiring entry. It might happen at some point, who knows? One of my other projects is working on an &lt;a href=&#34;https://github.com/csMACnz/consolable&#34;&gt;args parser library&lt;/a&gt; so this might be just another testbed for that at some point.&lt;/p&gt;
&lt;p&gt;The source code is on Github at &lt;a href=&#34;https://github.com/csMACnz/TogglHeatmap&#34;&gt;github.com/csMACnz/TogglHeatmap&lt;/a&gt;. Issues welcome.&lt;/p&gt;
&lt;p&gt;Hopefully, someone other than me finds this useful. If not, I have found it useful to document the evolution of my working hours.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Beefeater - Guard your methods&#39; Ins and Outs.</title>
      <link>https://blog.csmac.nz/post/beefeater-guards-your/</link>
      <pubDate>Mon, 06 Aug 2018 06:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/beefeater-guards-your/</guid>
      <description>&lt;img align=&#34;right&#34; width=&#34;256px&#34; height=&#34;256px&#34; src=&#34;http://img.csmac.nz/Beefeater-256.svg&#34;&gt;
&lt;p&gt;A little while back I started paying attention to Rust and got all inspired to have a bit of that it C#. The result was this library I called Beefeater.&lt;/p&gt;
&lt;p&gt;This library contains helpers to add semantics to the optionality of your parameters and results from method calls. I built it on &lt;code&gt;NetStandard1.0&lt;/code&gt; for maximum compatibility.&lt;/p&gt;
&lt;p&gt;Some of this will soon become obsolete with C# 8 features such as the C# 8 nullable reference types, but much of it gives you the power you need right now.&lt;/p&gt;
&lt;p&gt;You can install the NuGet package using &lt;code&gt;Install-Package Beefeater&lt;/code&gt; or by heading to the &lt;a href=&#34;https://www.nuget.org/packages/Beefeater&#34;&gt;Nuget Package Page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Last week I released version 0.5.0.&lt;/p&gt;
&lt;p&gt;The basic idea is similar to the &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; type that exists for value types. But extend this into semantic markup around method arguments and return types.&lt;/p&gt;
&lt;p&gt;The approach is to allow you to write declarative code, and let the library determine which part gets called.&lt;/p&gt;
&lt;p&gt;To make this seamless, I&amp;rsquo;ve leveraged a few features of C#, namely the Implicit Casts, and Generics.&lt;/p&gt;
&lt;p&gt;But just declaring optionality isn&amp;rsquo;t enough, so the goal is to go further and provide functions to write better safer code using these types.&lt;/p&gt;
&lt;h3 id=&#34;the-bits&#34;&gt;The bits&lt;/h3&gt;
&lt;p&gt;The library is made up of a few different utilities and ideas.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt; - declare a reference type as possibly null (C# 8 makes this obsolete, but implicit casts to/from the new syntax might work)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NotNull&amp;lt;T&amp;gt;&lt;/code&gt; - so you can declare something is certainly never null (or crash immediately rather than on dereference)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Result&amp;lt;TValue, TError&amp;gt;&lt;/code&gt; - Represents either a success result or an error (Modelled after &lt;a href=&#34;https://doc.rust-lang.org/std/result/&#34;&gt;Rust&amp;rsquo;s std::result&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Either&amp;lt;TValue, TError&amp;gt;&lt;/code&gt; - a more generic concept of a two-part Union type&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are implicit casts to and from (where sensible) these types when they are in use, so you only need to explicitly declare them in contracts, and occasionally in return types. Although, a bunch of work has been put in to avoid return types most of the type.&lt;/p&gt;
&lt;p&gt;These classes have some consistent methods to help out:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Match - a function or action that is provided lambda &lt;code&gt;Func&lt;/code&gt;s/&lt;code&gt;Action&lt;/code&gt;s  respectively to cover both known states of the object.&lt;/li&gt;
&lt;li&gt;HasValue - similar to the &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;ValueOrDefault - to ensure you certainly get back a value&lt;/li&gt;
&lt;li&gt;IsSuccess - a similar pattern to &lt;code&gt;Nullable&amp;lt;T&amp;gt;&lt;/code&gt; applied to &lt;code&gt;Result&amp;lt;,&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There was a theory of making an enum match but it wasn&amp;rsquo;t achievable. However again C# 8 might solve this with new pattern matching too.&lt;/p&gt;
&lt;p&gt;There is also Resharper definitions provided to work with and be trusted by the Resharper Null static analysis.&lt;/p&gt;
&lt;h3 id=&#34;show-me-the-code&#34;&gt;Show me the code!&lt;/h3&gt;
&lt;h4 id=&#34;optiont&#34;&gt;Option&lt;T&gt;&lt;/h4&gt;
&lt;p&gt;As a simple example you may have a method like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;public string Modify(string first, string second)
{
    if (first == null)
    {
        throw new ArgumentNullException(nameof(first));
    }
    if (second == null)
    {
        return null;
    }
    return first + second;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Typical code. A bit of error checking, and some switch logic based on an optional argument.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t know about you, but it is hard for me to know that &lt;code&gt;first&lt;/code&gt; is required, but &lt;code&gt;second&lt;/code&gt; is optional. At least not without comments, or a thorough inspection of the code. Shouldn&amp;rsquo;t the signature tell me this? (C# 8 says it will.)&lt;/p&gt;
&lt;p&gt;Lets take a look at this using Beefeater:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;public Option&amp;lt;string&amp;gt; Modify(NotNull&amp;lt;string&amp;gt; first, Option&amp;lt;string&amp;gt; second)
{
    return second.Match(
        v =&amp;gt; first + v,
        () =&amp;gt; Option&amp;lt;string&amp;gt;.None);
}

var x = Modify(&amp;#34;Hello&amp;#34;, &amp;#34;World&amp;#34;);
var y = Modify(&amp;#34;Hello&amp;#34;, null);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That is very clean to me. First, the signature tells us everything we need to know.&lt;/p&gt;
&lt;p&gt;And when we look at the calling syntax, it is seamless. it works exactly as you expect. With one difference.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; in the example are both &lt;code&gt;Option&amp;lt;string&amp;gt;&lt;/code&gt; type. This means you cannot pass this to a method that requires &lt;code&gt;NotNull&amp;lt;string&amp;gt;&lt;/code&gt;, or even &lt;code&gt;string&lt;/code&gt; itself.&lt;/p&gt;
&lt;p&gt;Why? Well, clearly you have no idea if that result is safe. You know it is either a Nothing or a non-null string. (Is it both?  Schrodinger&amp;rsquo;s &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt;?)&lt;/p&gt;
&lt;p&gt;The only sensible thing to do is to check, right? It would be unsafe not to.  Thus the value of the library is revealed.&lt;/p&gt;
&lt;p&gt;That check can use the &lt;code&gt;Match&lt;/code&gt; method, too.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;var x = Modify(&amp;#34;Hello&amp;#34;, &amp;#34;World&amp;#34;);

var outputMessage = x.Match(
  some: value =&amp;gt; $&amp;#34;The result is {value}&amp;#34;,
  none: () =&amp;gt; &amp;#34;There wasn&amp;#39;t anything to report&amp;#34;);

Console.WriteLine(outputMessage);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Your code will start to become very functional, but you will also get compile-type checks to ensure you are handling error cases correctly.&lt;/p&gt;
&lt;p&gt;If you really want to live dangerously, though, there is an explicit cast back to the original type, that will throw a &lt;code&gt;PanicException&lt;/code&gt;. This is basically the library equivalent to the &lt;code&gt;NullReferenceException&lt;/code&gt;, but should normally throw earlier in your code when the Null is first observed, rather than late at dereference.&lt;/p&gt;
&lt;p&gt;Much like async/await, this library is contagious and will ripple through your code, just FYI.&lt;/p&gt;
&lt;h4 id=&#34;resulttvalue-terror&#34;&gt;Result&amp;lt;TValue, TError&amp;gt;&lt;/h4&gt;
&lt;p&gt;Apart from &lt;code&gt;Option&amp;lt;T&amp;gt;&lt;/code&gt;, the other most useful is the &lt;code&gt;Result&amp;lt;TValue, TError&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Again, you might have written:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;public bool Create(string filePath, string second)
{
    if (filePath == null)
    {
        throw new ArgumentNullException(nameof(filePath));
    }
    if(second == null)
    {
        return false;
    }
    using (FileStream stream = File.OpenWrite(filePath))
    {
        using (var writer = new StreamWriter(stream))
        {
            writer.WriteLine(second);
        }
    }
    return true;
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Again, a little cruft. Optionality unclear. But there is more.  This method can and will throw a bunch of exceptions. FileNotFound, UnauthorizedAccess, and others. Your calling code is either going to handle many exceptions, or the app will crash. We could put the logic into the method, and the code would get complex. But how do we handle the return? returns &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt; or Throws exception, how do you translate that into a concise return type of &lt;code&gt;true&lt;/code&gt;, &lt;code&gt;false&lt;/code&gt; or FileNotFound or Unauthorized or Other?&lt;/p&gt;
&lt;p&gt;Beefeater says like this:
(Rust too, actually&amp;hellip;)&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;public enum ErrorResult
{
    UnknownError,
    FileNotFound,
    Unauthorized
}
public Result&amp;lt;bool, ErrorResult&amp;gt; Create(NotNull&amp;lt;string&amp;gt; filePath, Option&amp;lt;string&amp;gt; second)
{
    FileStream stream;
    try
    {
        stream = File.OpenWrite(filePath);
    }
    catch (UnauthorizedAccessException ex)
    {
        return ErrorResult.Unauthorized;
    }
    catch (FileNotFoundException ex)
    {
        return ErrorResult.FileNotFound;
    }
    catch (Exception ex)
    {
        return ErrorResult.UnknownError;
    }
    using (stream)
    {
        return second.Match(
            v =&amp;gt;
            {
                using (var writer = new StreamWriter(stream))
                {
                    writer.WriteLine(v);
                }
                return true;
            },
            () =&amp;gt; false);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;To me, the business logic is very easy to read from this code. Again the signature is clear what to expect and how to use the result.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;var result = Create(&amp;#34;myfile.txt&amp;#34;, someVar);
var outputMessage = result.Match(
  isCreated =&amp;gt; isCreated
    ? &amp;#34;The file was created with someVar&amp;#34;
    : &amp;#34;The file was not created because someVar&amp;#34;,
  error =&amp;gt; 
  {
      switch(error)
      {
          case FileNotFound:
              return &amp;#34;File Not Found&amp;#34;;
          case Unauthorized:
              return &amp;#34;The file is secure and you can&amp;#39;t get it.&amp;#34;;
          case UnknownError:
          default:
              return &amp;#34;An unknown Error occurred&amp;#34;;
      }
  });

Console.WriteLine(outputMessage);
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Just like that, every code-branch/edge-case has to be covered, or it will not compile. (Enum notwithstanding.)&lt;/p&gt;
&lt;h4 id=&#34;either&#34;&gt;Either&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;Either&amp;lt;T1, T2&amp;gt;&lt;/code&gt; is very similar to Result, except the semantic meaning differs. It allows a method to return either one type or another type.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;public Either&amp;lt;long, double&amp;gt; DivideByTwo(int aNumber)
{
    if (aNumber % 2 == 0)
        return aNumber / 2;
    return aNumber / (double)2;
}

var x = DivideByTwo(10);
var x = DivideByTwo(5);
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id=&#34;recursion&#34;&gt;Recursion?&lt;/h4&gt;
&lt;p&gt;You could even nest these things:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;Either&amp;lt;Option&amp;lt;string&amp;gt;, NotNull&amp;lt;int&amp;gt;&amp;gt;
Option&amp;lt;Either&amp;lt;Foo, Bar&amp;gt;&amp;gt;
Result&amp;lt;Option&amp;lt;string&amp;gt;,CustomError&amp;gt;
Result&amp;lt;Unit,string&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Different combinations will provide different value in different situations.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Unit&lt;/code&gt;? Yeah. When you go functional, representing &lt;code&gt;void&lt;/code&gt; as a type is much helpful. I have another library where I get my Unit from, but there are literally dozens on Nuget.&lt;/p&gt;
&lt;h3 id=&#34;c-8&#34;&gt;C# 8&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve hung a lot of stuff on C# 8 in this article. At some point, I should cover what is coming (though at this stage nothing is certain). Basically, though, this library has been hanging around for a while, before nullable reference types was even being discussed publicly. So whether nullable reference types happens in 8, 8.1 or C# 9, this library is here today and can get you started thinking about different states of optionality in your code today.&lt;/p&gt;
&lt;h3 id=&#34;performance&#34;&gt;Performance?&lt;/h3&gt;
&lt;p&gt;About that&amp;hellip;.&lt;/p&gt;
&lt;p&gt;So I haven&amp;rsquo;t actually spent any time profiling to see if this is damaging your code. For most LOB apps, this will not be the bottleneck compared to IO. But it is a valid point and does need further investigation and optimisation.&lt;/p&gt;
&lt;p&gt;From a development performance point of view, I do go slower to go faster. I think about and code up the edge cases up front, rather than doubling back when something goes wrong.&lt;/p&gt;
&lt;h3 id=&#34;attention&#34;&gt;Attention!&lt;/h3&gt;
&lt;p&gt;So that&amp;rsquo;s Beefeater. I&amp;rsquo;ve started using it slowly on utilities and simple console apps. Hopefully, you find it interesting and it inspires you to think about how you handle your code yourself.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t like the ideas in this library, remember a &lt;code&gt;Result&amp;lt;,&amp;gt;&lt;/code&gt; is just a tuple, a &lt;code&gt;(string, ErrorEnum)&lt;/code&gt; if you wish. The rest is just boilerplate code you could write yourself. (Though I do handle all the error and state checking for you so you can just provide the Actions 😉 )&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Coveralls.Net 1.0.0 Release</title>
      <link>https://blog.csmac.nz/post/coveralls-net-1-0-0-release/</link>
      <pubDate>Mon, 04 Jun 2018 07:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/coveralls-net-1-0-0-release/</guid>
      <description>&lt;p&gt;Christmas 2014. I was building out projects on GitHub in open source. The obsession with open source even went on to spawn a &lt;a href=&#34;https://blog.csmac.nz/-net-os-1-source-control/&#34;&gt;Series of Blog Posts&lt;/a&gt;. Each tool or library I was building lead onto another tool or library to make the build pipeline, or development process better. Often putting down one project while I sorted out another one first.  This has continued at a slow pace for the last 3 years.&lt;/p&gt;
&lt;p&gt;Back in January 2015 I &lt;a href=&#34;https://blog.csmac.nz/introducing-coveralls-net/&#34;&gt;Announced Coveralls.Net&lt;/a&gt;. This is a code coverage publisher for publishing your coverage results to the coveralls.io API. Coveralls.io is a coverage tracking service, which is free for open source projects, with a paid service for private use, and now an Enterprise version as well. There was a bunch of python and ruby versions, but I wanted fewer dependencies on those runtimes so built my own.  I even managed to get it listed as one of the two &lt;a href=&#34;https://docs.coveralls.io/dot-net&#34;&gt;recommended .Net coverage integrations&lt;/a&gt; on the coveralls.io docs.&lt;/p&gt;
&lt;p&gt;While development has been a slow work of labour over the last three years, the announcement of dotnet CLI tools (proper npm-style tools, not the weird interim dotnet-tool stuff&amp;hellip;) with dotnet SDK 2.1, I had to jump in and get on board.&lt;/p&gt;
&lt;h3 id=&#34;announcing-100&#34;&gt;Announcing 1.0.0&lt;/h3&gt;
&lt;p&gt;Which brings me to announcing Coveralls.Net 1.0.0. This is a dotnet CLI tools compatible version of &lt;code&gt;csmacnz.Coveralls&lt;/code&gt;. Easier to install. Easier to update. And a whole bunch new features, including more coverage options, and better autodetection processes in AppVeyor.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# install globally
dotnet tool install -g coveralls.net --version 1.0.0

# if installed globally, this should just be available on your path
csmacnz.coveralls &amp;lt;args&amp;gt;

# install into a local folder
dotnet tool install coveralls.net --version 1.0.0 --tools-path tools

# if installed into a tools path, you can run it from there.
.\tools\csmacnz.Coveralls &amp;lt;args&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now, I&amp;rsquo;ve been struggling a bit with beta 0.8.0. It hasn&amp;rsquo;t been easy to find time to test the new stuff I added, get others to test, and be happy to call it a stable release. But there was a bunch of new stuff and fixes in there. These have all rolled forward into the 1.0.0 Release now. (I might go back and call 0.8.0 stable now since it still works the old way. But for now the old way still works with stable &lt;code&gt;0.7.0&lt;/code&gt; and &lt;code&gt;0.8.0-beta003&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;Still not happy/comfortable with using CLI tools? Not using 2.1? That&amp;rsquo;s ok. I&amp;rsquo;ve used the power of the &lt;a href=&#34;https://blog.csmac.nz/dotnetcore2-self-contained-applications/&#34;&gt;self-contained app&lt;/a&gt; to provide a &lt;code&gt;windows&lt;/code&gt;, &lt;code&gt;linux&lt;/code&gt; and &lt;code&gt;osx&lt;/code&gt; native version (Linux targets the cross-compat Linux target) in a zip file under &lt;a href=&#34;https://github.com/csMACnz/coveralls.net/releases/tag/1.0.0&#34;&gt;the Releases folder on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For windows in PowerShell you would use it something like this:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;# The TLS change was necessary on my development machine
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$zipDownloadPath=&amp;#34;https://github.com/csMACnz/coveralls.net/releases/download/1.0.0/coveralls.net.1.0.0-windows.zip&amp;#34;
Invoke-WebRequest -UseBasicParsing $zipDownloadPath -OutFile coveralls-windows.zip
mkdir coveralls-windows
Expand-Archive .\coveralls-windows.zip coveralls-windows

.\coveralls-windows\csmacnz.Coveralls.exe
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I hope to get more details added on the GitHub Wiki for linux and mac usage of the self-contained app, as well as updating all the samples over at &lt;a href=&#34;https://github.com/csMACnz/Coveralls.net-Samples/&#34;&gt;Coveralls.net-Samples&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;more-targets&#34;&gt;More targets&lt;/h3&gt;
&lt;p&gt;Since the first release, targeting OpenCover coverage files (the most popular at the time), this has been expanded to include Visual Studio Coverage, monocov, Report Generator, Chutzpah javascript coverage, lcov, NCover and &lt;a href=&#34;https://github.com/tonerdo/coverlet&#34;&gt;Coverlet&lt;/a&gt; cross-platform .Net coverage (via its opencover file format).&lt;/p&gt;
&lt;h3 id=&#34;whats-next&#34;&gt;What&amp;rsquo;s Next?&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve already started working on 1.1.0 while the dotnet 2.1 tools have been working towards stable.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Better autodetection functionality (including Travis and TeamCity)&lt;/li&gt;
&lt;li&gt;dotcover support&lt;/li&gt;
&lt;li&gt;parallel build support&lt;/li&gt;
&lt;li&gt;add native coverlet support&lt;/li&gt;
&lt;li&gt;Bug fixes that didn&amp;rsquo;t make it to 1.0.0&lt;/li&gt;
&lt;li&gt;Complete and test Enterprise support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hopefully, it won&amp;rsquo;t be soon before long that you will see an Announcing 1.1.0 Post.&lt;/p&gt;
&lt;p&gt;Interested in following progress on this? I have a twitter account &lt;a href=&#34;https://twitter.com/coverallsdotnet&#34;&gt;@coverallsdotnet&lt;/a&gt; That I am trying to be more proactive with.  You can also track progress on the &lt;a href=&#34;https://github.com/csMACnz/coveralls.net&#34;&gt;GitHub Project&lt;/a&gt;.  Contributions welcome, though I hear I&amp;rsquo;m a bit of a stickler for quality and such. C&amp;rsquo;est la vie.&lt;/p&gt;
&lt;p&gt;The irony of a coverage publishing tool only having 42% coverage wasn&amp;rsquo;t lost on me, so I got it up to 74%. Soon enough I should get that to 100%. Probably just in time for a version 2.0.0.&lt;/p&gt;
&lt;h3 id=&#34;need-more&#34;&gt;Need more?&lt;/h3&gt;
&lt;p&gt;Issues, feature requests or feedback? Just write up an issue on GitHub. I would love to hear your experience of using the tool, and I would love to expand the supported coverage formats to include your favourite tool.&lt;/p&gt;
&lt;p&gt;Thanks for using it! It makes me more inclined to make it awesome.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>New Projects - Consolable, ConcurrentConsole &amp; t4tinytypes</title>
      <link>https://blog.csmac.nz/post/new-projects-consolable-concurrentconsole-t4tinytypes/</link>
      <pubDate>Sun, 14 Aug 2016 21:51:20 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/new-projects-consolable-concurrentconsole-t4tinytypes/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been working on some new projects, so thought I would do a quick elevator pitch for each.&lt;/p&gt;
&lt;h3 id=&#34;consolable&#34;&gt;Consolable&lt;/h3&gt;
&lt;p&gt;I was having an issue with environment variables as arguments, and with PowerShell replacing &lt;code&gt;&amp;quot;text&amp;quot;&lt;/code&gt; with &lt;code&gt;text&lt;/code&gt; (stripping double-quotes) and how these interacted with my command line arguments. Especially when the environment variable was empty, the error messages were just not clear enough.&lt;/p&gt;
&lt;p&gt;So I&amp;rsquo;m building yet another CLI parsing library, but with a primary focus on error messaging. It should work well to provide the developer the arguments from the user, but should also provide the user with better help on where the mistake they have made is.&lt;/p&gt;
&lt;p&gt;Follow my progress &lt;a href=&#34;https://github.com/csMACnz/consolable&#34;&gt;here on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;concurrentconsole&#34;&gt;ConcurrentConsole&lt;/h3&gt;
&lt;p&gt;I was wanting to build a chatbot. So naturally as a test harness I need a console app to test with. But it turns out my bot is asynchronous (I can keep talking, while it keeps thinking and returning new messages to an existing thread).  It turns out that concurrently printing text and allowing text entry is not an Out-Of-The-Box feature.&lt;/p&gt;
&lt;p&gt;Introducing ConcurrentConsole, a wrapper over System.Console to allow multithreaded writes while a thread is still reading from the user. Maintain your existing typed text, and even define your own prompt text (which can also be dynamically updated at runtime).&lt;/p&gt;
&lt;p&gt;Check it out &lt;a href=&#34;https://github.com/csMACnz/ConcurrentConsole&#34;&gt;on GitHub&lt;/a&gt; and &lt;a href=&#34;https://www.nuget.org/packages/csMACnz.ConcurrentConsole/&#34;&gt;NuGet&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;t4tinytypes&#34;&gt;t4tinytypes&lt;/h3&gt;
&lt;p&gt;Something I have been meaning to do for a while was to automate my &lt;a href=&#34;http://blog.csmac.nz/semantics-vs-implementation-detail/&#34;&gt;tiny types&lt;/a&gt;. It can get tedious to build and maintain many small wrapper types, and creating the right definition while in the flow of building out your code can be distracting.&lt;/p&gt;
&lt;p&gt;t4tinytypes is a NuGet package of t4 templates that can be used with Visual Studio or the command-line (for dotnet cli) to generate and regenerate tiny types, simply, easily and flexibly (not to mention extensible).  I&amp;rsquo;m still working on testing samples to show all the ways it can be used, but it should be published as an early alpha release soon.&lt;/p&gt;
&lt;h3 id=&#34;while-youre-at-it&#34;&gt;While you&amp;rsquo;re at it&amp;hellip;&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s what&amp;rsquo;s new, feel free to influence me on what the think you would find valuable to have me finish first. But don&amp;rsquo;t forget the other little projects I&amp;rsquo;ve already put out there and would love feedback on, too.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnz/Beefeater&#34;&gt;Beefeater&lt;/a&gt; - &amp;ldquo;Guard your methods&amp;rsquo; Ins and Outs.&amp;rdquo; - return and optionality semantics helper library&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnz/coveralls.net&#34;&gt;coveralls.net&lt;/a&gt; - a publisher for .Net code coverage to &lt;a href=&#34;https://coveralls.io/&#34;&gt;coveralls.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnz/BCLExtensions&#34;&gt;BCLExtensions&lt;/a&gt; - extensive extensions and helpers for primative types&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/csMACnz/coveritypublisher&#34;&gt;coveritypublisher&lt;/a&gt; - a publisher for &lt;a href=&#34;https://scan.coverity.com/&#34;&gt;Coverity Scan&lt;/a&gt; static analysis results&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feedback appreciated :)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introducing PublishCoverity</title>
      <link>https://blog.csmac.nz/post/introducing-publishcoverity/</link>
      <pubDate>Sun, 08 Mar 2015 17:34:21 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/introducing-publishcoverity/</guid>
      <description>&lt;p&gt;As part of my open source development tooling investigation, I came across &lt;a href=&#34;https://scan.coverity.com/&#34;&gt;Coverity Scan&lt;/a&gt; Static Analysis. And thanks to &lt;a href=&#34;http://arkfps.github.io/2015/01/07/using-coverity-scan-with-appveyor/&#34;&gt;Arkfps&amp;rsquo; post&lt;/a&gt; I could automate the process of submitting the results. And now &lt;a href=&#34;http://help.appveyor.com/discussions/suggestions/497-coverity-static-analysis-support&#34;&gt;Appveyor includes Coverity on it&amp;rsquo;s images&lt;/a&gt;. But I decided to take his work one step further, and so I built a small utility to compress and submit the results.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.nuget.org/packages/PublishCoverity&#34;&gt;PublishCoverity&lt;/a&gt; is available on NuGet, and has two use cases: Compress and Publish.&lt;/p&gt;
&lt;p&gt;Compress takes a directory and compresses it to produce an output zip file.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmd&#34; data-lang=&#34;cmd&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Signature:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PublishCoverity compress [-o &amp;lt;file&amp;gt;] [-i &amp;lt;folder&amp;gt;] [--overwrite] [--dryrun]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Example:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PublishCoverity compress -o results.zip -i cov-int
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Publish takes that file and some of your project data and posts it off to Coverity for you.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-cmd&#34; data-lang=&#34;cmd&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Signature:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PublishCoverity publish -t &amp;lt;token&amp;gt; -e &amp;lt;email&amp;gt; [-r &amp;lt;name&amp;gt;] [-z &amp;lt;file&amp;gt;] [-d &amp;lt;desc&amp;gt;] [--codeVersion &amp;lt;version&amp;gt;] [--dryrun] [--nologo]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Example:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PublishCoverity publish -t COVERITYTOKEN -e example@example.com -r MyUser/MyProject -z results.zip -d &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;my project&amp;#34;&lt;/span&gt; --codeVersion 0.1.2.3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Although this is still evolving, the gist of what is above will be available to compress and/or publish your results to Coverity Scan. The idea is that anything that I can reasonably determine for you I will try and make optional. Such as your repository name from the AppVeyor Build Environment variables.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve already had a request to add some guards around the results to ensure they are valid and complete before sending, but right now version 0.9 is available on NuGet for you to install and use, and the source is &lt;a href=&#34;https://github.com/csMACnz/coveritypublisher&#34;&gt;available on GitHub&lt;/a&gt;  All feedback and features requests welcome as GitHub issues, or just comment on this post.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introducing BCLExtensions</title>
      <link>https://blog.csmac.nz/post/introducing-bclextensions/</link>
      <pubDate>Sun, 15 Feb 2015 15:25:45 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/introducing-bclextensions/</guid>
      <description>&lt;p&gt;It has been a pipe-dream of mine for a while to have my very own C# extensions library. Well now I do.  I&amp;rsquo;ve been chipping away at a library on github for ages (my init commit was &lt;strong&gt;15 Sep 2012!&lt;/strong&gt;) and it is finally a real thing! I&amp;rsquo;ve got a V1.0.0, a Nuget package, and even 100% coverage. I even have the &lt;a href=&#34;https://scan.coverity.com/projects/3770&#34;&gt;coverity report&lt;/a&gt; running, although it&amp;rsquo;s taken so long that I don&amp;rsquo;t have anything to worry about right now.  So far there are 24 Extensions available to use.&lt;/p&gt;
&lt;p&gt;As a bonus, my library is a PCL using profile 328, which pretty much means it will work with any C# application you are writting.  I even have it building and running all my test on &lt;a href=&#34;https://travis-ci.org/csMACnz/BCLExtensions&#34;&gt;Travis-CI&lt;/a&gt; (252 tests and counting).&lt;/p&gt;
&lt;p&gt;Please feel free to grab the nuget at &lt;a href=&#34;https://www.nuget.org/packages/BCLExtensions&#34;&gt;nuget.org/packages/BCLExtensions&lt;/a&gt; and check the source as &lt;a href=&#34;https://github.com/csMACnz/BCLExtensions&#34;&gt;github.com/csMACnz/BCLExtensions&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next steps: keep knocking out the extensions from my wishlist, get resharper&amp;rsquo;s inspectcode.exe command-line tool running, and tidy up all the documentation onto the wiki and maybe on of the docs services.&lt;/p&gt;
&lt;p&gt;Have suggestions? Or are there extensions on my list that you want me to prioritise? Open an issue and let me know.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Introducing Coveralls.net</title>
      <link>https://blog.csmac.nz/post/introducing-coveralls-net/</link>
      <pubDate>Sat, 24 Jan 2015 14:33:48 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/introducing-coveralls-net/</guid>
      <description>&lt;p&gt;So I&amp;rsquo;ve built an (almost MVP) code coverage publisher for &lt;a href=&#34;http://coveralls.io&#34;&gt;coveralls.io&lt;/a&gt; from C# code, using opencover coverage results.  Checkout the &lt;a href=&#34;https://github.com/csmacnz/coveralls.net&#34;&gt;github repo&lt;/a&gt; and &lt;a href=&#34;https://www.nuget.org/packages/coveralls.net/&#34;&gt;nuget packages&lt;/a&gt; if you want to use it.  I&amp;rsquo;m even dogfooding it on appveyor as part of my &lt;a href=&#34;https://github.com/csmacnz/coveralls.net/blob/master/build.tasks.ps1#L81&#34;&gt;psake build tasks&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So how do you use it?  Well luckily I used &lt;a href=&#34;https://github.com/docopt/docopt.net&#34;&gt;docopts.net&lt;/a&gt; to give you a bit of a command line experience while you use it, but the gist is this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;csmacnz.Coveralls.exe --opencover -i opencovertests.xml --repoToken &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;abcdefghijklmnopqrstuvwxyz&amp;#34;&lt;/span&gt; --commitId $env:APPVEYOR_REPO_COMMIT --commitBranch $env:APPVEYOR_REPO_BRANCH --commitAuthor $env:APPVEYOR_REPO_COMMIT_AUTHOR --commitEmail $env:APPVEYOR_REPO_COMMIT_AUTHOR_EMAIL --commitMessage $env:APPVEYOR_REPO_COMMIT_MESSAGE --jobId $env:APPVEYOR_JOB_ID
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will locate the xml file opencovertests.xml as a result from running opencover on your c# project, and publish it to your coveralls project based on the repoToken &amp;ldquo;abcdefghijklmnopqrstuvwxyz&amp;rdquo; (using your repo token found on your coveralls.io project page) along with the git commit and branch details pulled out of appveyor.&lt;/p&gt;
&lt;p&gt;So what does this mean to you? How will you use it? Well you can replace the appveyor environment variables above with the actual values found in your build server, get your repo token from coveralls.io, and plus this in on top of your existing opencover coverage CI.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t currently have opencover hooked up, there are tutorials all over the place for your specific build server, I&amp;rsquo;ll leave you to figure out the best way to get this running.&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t use/want to use opencover? The next steps for me is to get other coverage reports working with coveralls.net so stay tuned, or go +1 some of my features listed in the &lt;a href=&#34;https://github.com/csmacnz/coveralls.net/issues&#34;&gt;repository issues&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For me, the next steps is to test this works on my other projects so that I will be in the same situation as anyone else who wants to use it.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Hey, I found this thing called Coveralls.io</title>
      <link>https://blog.csmac.nz/post/hey-i-found-this-thing-called-coveralls-io/</link>
      <pubDate>Sun, 14 Dec 2014 19:50:47 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/hey-i-found-this-thing-called-coveralls-io/</guid>
      <description>&lt;p&gt;In my pursuit to &lt;a href=&#34;//blog.csmac.nz/gulp-vs-net/&#34;&gt;find a build task runner for my code coverage&lt;/a&gt; I stumbled on this whole other side of the internet I didn&amp;rsquo;t know about (from a .Net developer&amp;rsquo;s perspective). I&amp;rsquo;ve been using &lt;a href=&#34;http://www.appveyor.com/&#34;&gt;AppVeyor.com&lt;/a&gt; for my open-source CI build, which is a great option for anyone with a project on the Microsoft Stack. The cool thing about this (and other similar services) is that if you have an open source project on GitHub, you can use these services with your project for free!&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m aware this isn&amp;rsquo;t new, and there are others like &lt;a href=&#34;http://travis-ci.org/&#34;&gt;Travis-CI.org&lt;/a&gt; which run all the other platforms, but I didn&amp;rsquo;t realise how prolific it really was! Especially how exclusive of microsoft languages they all are. Travis-CI for instance, doesn&amp;rsquo;t seem to support .Net by looking on their &lt;a href=&#34;http://docs.travis-ci.com/&#34;&gt;docs page&lt;/a&gt;, though there does seem to be &lt;a href=&#34;http://docs.travis-ci.com/user/languages/csharp/&#34;&gt;mono support in beta&lt;/a&gt; (and that didnt exist when i looked a week ago, so will keep an eye on this).&lt;/p&gt;
&lt;p&gt;But my main reason for this post, is that I found this cool new (to me any way) Continuous Code Coverage host called &lt;a href=&#34;https://coveralls.io/&#34;&gt;coveralls.io&lt;/a&gt;. With a cool name like that, and a badge for my project, I&amp;rsquo;m sold. But wait, lets check &lt;a href=&#34;https://coveralls.zendesk.com/hc/en-us&#34;&gt;those docs&lt;/a&gt; again.  Yip as I thought, no C# support.  They even have C/C++, this is wrong!&lt;/p&gt;
&lt;p&gt;Ah but whats this? They have an api? And they want you to add missing support? I think I have to help with this. So now I have looked at the java and python implementations, a little bit of the api documentation, and I now have a project placeholder to support C# from various Code Coverage xml output formats to post that data up to coveralls, at &lt;a href=&#34;https://github.com/csmacnz/coveralls.net&#34;&gt;coveralls.net on github&lt;/a&gt;.  I&amp;rsquo;ve even got my badges, for coveralls.io ready to go.&lt;/p&gt;
&lt;p&gt;So fastforward another week and I have a working prototype done. It&amp;rsquo;s even showing &lt;a href=&#34;https://coveralls.io/r/csMACnz/coveralls.net&#34;&gt;coverage on coveralls.io&lt;/a&gt;, supporting opencover xml format.&lt;/p&gt;
&lt;p&gt;So whats left now? finish building it to be reusable by my other projects, publish it to nuget and chocolately and wherever else I need to, and start getting people integrating it into their .Net builds. Probably build out other C# coverage report formats as well, so your not forced to use opencover. Wish me luck!&lt;/p&gt;
&lt;h6 id=&#34;small-side-note&#34;&gt;small side note&lt;/h6&gt;
&lt;p&gt;So I also found this other continuous code quality metrics thing for python called &lt;a href=&#34;https://landscape.io/&#34;&gt;landscape.io&lt;/a&gt;. When will we see this type of thing available for .Net as well? Turns out right now. Check out
&lt;a href=&#34;https://scan.coverity.com/projects/3696&#34;&gt;Coverity Scan Static Analysis&lt;/a&gt; (&lt;a href=&#34;https://scan.coverity.com/projects/3696&#34;&gt;mine&lt;/a&gt; needs you to create an account to use, but no permissions to view.)&lt;/p&gt;
&lt;p&gt;And two more for fun: &lt;a href=&#34;https://waffle.io/&#34;&gt;waffle.io&lt;/a&gt; &amp;amp; &lt;a href=&#34;https://readthedocs.org/&#34;&gt;readthedocs.org&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Gulp vs .net</title>
      <link>https://blog.csmac.nz/post/gulp-vs-net/</link>
      <pubDate>Sun, 07 Dec 2014 17:41:40 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/gulp-vs-net/</guid>
      <description>&lt;p&gt;I wanted to add continuous code coverage to my &lt;a href=&#34;https://github.com/csmacnz/BCLExtensions&#34;&gt;little extension library project&lt;/a&gt;, and so realised i would need to run one of nCover, dotCover or openCover from the command line on my build server. This calls for a task based build automation library!&lt;/p&gt;
&lt;p&gt;Because I&amp;rsquo;m started to learn more about this nodejs thing as a .Net developer, I figured I should give one of the build automation projects from there a go, even though my project is a .Net library and I dont need node (even if it is a PCL).&lt;/p&gt;
&lt;h4 id=&#34;a-few-hurdles&#34;&gt;A Few Hurdles&lt;/h4&gt;
&lt;p&gt;So the first major problem is node itself. not a current dependancy from any of the project, so that needed to be installed. Not a big deal, i did have to hack around with powershell to set up node so that npm was recognised, but thats a once off per machine. Then I had to add a package.json file, that was that.&lt;/p&gt;
&lt;p&gt;Next up was gulp, again, not too bad except that I did have issues getting gulp recognised as a command, but a few powershell restarts and some new PATH variables and that was fine too.&lt;/p&gt;
&lt;p&gt;Now to get gulp to build and run my tests. Luckily there is a &lt;a href=&#34;https://www.npmjs.org/package/gulp-msbuild&#34;&gt;gulp-msbuild&lt;/a&gt; task that I could install, which works without much trouble. Unfortunately, there was no gulp-mstest. after much trial and error, I found and used the node package &lt;a href=&#34;https://www.npmjs.org/package/mstest&#34;&gt;mstest&lt;/a&gt;, and jumped some extra hoops to do a manual gulp task for that. I notice that there is a &lt;a href=&#34;https://www.npmjs.org/package/grunt-mstest&#34;&gt;grunt-mstest&lt;/a&gt; available, and a &lt;a href=&#34;https://www.npmjs.org/package/gulp-nunit&#34;&gt;gulp-nunit&lt;/a&gt;, so not too big a deal for others that might be following a similar path.&lt;/p&gt;
&lt;p&gt;I even managed to get a AssemblyInfo rewritter build step as well, which was a nice, but unnecessary bonus at this stage.&lt;/p&gt;
&lt;p&gt;About now, after several hours mucking about, I realised that I had achieved the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Introduced an unnecessary dependancy on nodeJS&lt;/li&gt;
&lt;li&gt;Added new node-module dependancies to the setup of my build tasks that need downloading&lt;/li&gt;
&lt;li&gt;Require you to spin up an entire node environment, just to shell out to command line applications to build and test my .Net project.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I haven&amp;rsquo;t even got to code coverage and already feel I&amp;rsquo;m breaking ground, and will need to build my own node libraries for gulp to run my tests and code coverage.  At this point I also realise since ive been doing the whole thing in powershell, I should just install psake and be done with it.&lt;/p&gt;
&lt;h4 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;If you&amp;rsquo;ve got a web application in .Net and you will need a pipeline for less/sass/typescript/coffeescript/javascript , gulp is a nice way to go, and can even do the build, run the test, package to a zip and/or deploy to your environments for you.  But if all you have is a .Net library with no web requirements whatsoever, I recommend psake, with a little chocolatey for environment dependancies thrown in.&lt;/p&gt;
&lt;h4 id=&#34;for-your-interest&#34;&gt;For your interest&lt;/h4&gt;
&lt;p&gt;You can check out the changes in the following &lt;a href=&#34;https://github.com/csmacnz/BCLExtensions/tree/d04a6a311f78f0fd52b8900af375ee1a15746eee&#34;&gt;Commit&lt;/a&gt; (I&amp;rsquo;m pretty sure it&amp;rsquo;s going to become psake pretty soon.)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>7 Lessons from Building a WP7 Game in 7 days</title>
      <link>https://blog.csmac.nz/post/7-lessons-from-building-a-wp7-game-in-7-days/</link>
      <pubDate>Tue, 05 Jul 2011 18:00:00 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/7-lessons-from-building-a-wp7-game-in-7-days/</guid>
      <description>&lt;p&gt;This is a companion post for my talk at Wellington&amp;rsquo;s SLAMD user group on 6 July 2011.&lt;/p&gt;
&lt;p&gt;Recently I took part in &lt;a href=&#34;http://blogs.msdn.com/b/nigel/&#34;&gt;Nigel Parker&lt;/a&gt;&amp;rsquo;s &amp;ldquo;&lt;a href=&#34;http://blogs.msdn.com/b/nigel/archive/2011/05/16/release-an-app-for-windows-phone-7-in-7-days-to-win-a-phone.aspx&#34;&gt;Release an App for Windows Phone 7 in 7 Days for a Chance to Win a New HTC 7 Trophy Phone&lt;/a&gt;&amp;rdquo; competition, with the intent of winning a Windows Phone 7 device. Although I didn&amp;rsquo;t manage to win the device, I did get a free 1 year subscription to the App Hub, allowing me to develop and submit apps that I build, had fun doing it, and learned a few lessons along the way. This was my first exposure to the WP7 development ecosystem, as well as my first excursion onto a mobile platform in general.&lt;/p&gt;
&lt;p&gt;So what follows is a few lessons that I would like to pass on about developing a windows phone application. First though, I will give a quick overview of what exactly I built. The brief was simple, build an application, and have it live on the marketplace by the 6th of June. Not that big of a task, really. The point of this exercise was to both boost awareness of the new development tools, and to increase the footprint of New Zealand-built apps on the marketplace.&lt;/p&gt;
&lt;p&gt;&amp;lsquo;7 days&amp;rsquo; was a bit of a guideline really, as the competition ran from the 16th May, but this gave time after your 7 days to get it through the approval process, get your account validated and active, and still have time to fix anything that stopped it getting approved first time around. So I came up with a great idea, for a spacies-type game where the main character was a bottle of sauce, defending his kitchen against an invasion of bacon. Bacon Vaders was born. With an idea in hand, the very next thing to do, of course, was to grab all of the developer tools and sdk. This brings me to Lesson number 1.&lt;/p&gt;
&lt;h3 id=&#34;1-tools-only-work-on-windows-vista-and-windows-7&#34;&gt;1) Tools only work on Windows Vista and Windows 7&lt;/h3&gt;
&lt;p&gt;This was a bit of a problem for two reasons. The first is that my primary portable solution is my EeePC. It is perfectly practical for taking my development with me, and has been my PC of choice for presentations. The only catch is that it is running Windows XP. I am keen to find out if it can handle windows 7 and still be a functional dev machine, but the cost of upgrading when XP works perfectly fine has held me back. Lucky for me, my girlfriend also has a Netbook, a newer one, and it has Windows 7. Portability problem solved. Problem 2, this restriction means that it also doesn&amp;rsquo;t work on Windows Server 2008 R2. If anyone was wondering, that is the OS running on my office machine.&lt;/p&gt;
&lt;p&gt;Hmm, so can&amp;rsquo;t do any dev at work either in my lunch break or before I head home. I&amp;rsquo;m sure I&amp;rsquo;m not the only developer who thinks that developing on a Server makes heaps of sense, but I guess they don&amp;rsquo;t expect that developers of web applications, deskop applications and web services ( + any database solutions) will want to develop for the WP7. Well its lucky that my gaming machine is running Windows 7 then, so I can use that for the majority of my coding and testing.&lt;/p&gt;
&lt;p&gt;So with the environment set up I was ready to start coding. With the help of my sister creating the graphical images and characters, I had a playable version of the game working by the end of 5 days made up of a weekend, and a couple of late nights after work. But as with anything new, there were a few bugs and oddities that had to be worked through to make it presentable for the marketplace.&lt;/p&gt;
&lt;h3 id=&#34;2-tombstoning&#34;&gt;2) Tombstoning&lt;/h3&gt;
&lt;p&gt;If you had been following any development blog or message boards around Windows Phone 7, you would have heard the term &amp;lsquo;Tombstoning&amp;rsquo;. This is the way Window Phone 7 handles not having multitasking (at least for the first release, Mango improves upon this model). There are several scenarios where this occurs. The simplest way to demonstrate the tombstoning behavior is to press the windows key on the device while your application is running. This puts it into an out of processor state. If memory is needed, then your application will be closed completely. This is tombstoning. If you come back before this happens, everything is exactly were you left it. If you come back after tombstoning, you get to come back to the same page or screen, but you will have to do some work to continue where you left off.&lt;/p&gt;
&lt;p&gt;Luckily, you can be notified when your application is tombstoned, and write code to save any important information, that you might need to use to bring it back up again. After much trial and error, I was able to get my game to behave how I wanted it to. rather than rely of specific Tombstoning information, I decided that if you were playing the game, and you left the in game screen in anyway, the current level state would be saved. Then, whenever you return to the page, either with resume from the menu, or using the back button, the level would resume itself. Even if tombstoning hadn&amp;rsquo;t occurred, the same code can be used to refresh the page, and then resume the game.&lt;/p&gt;
&lt;p&gt;After tombstoning, the rest of the application came together pretty easily, since it was simply Silverlight, and I have plenty of experience building silverlight apps. I wasn&amp;rsquo;t using any networking, any complex configuration, saving or loading. I wasn&amp;rsquo;t even doing anything overly complex with the game loop. The next lesson didn&amp;rsquo;t crop up until closer to the end of the project.&lt;/p&gt;
&lt;h3 id=&#34;3-games-vs-apps&#34;&gt;3) Games vs Apps&lt;/h3&gt;
&lt;p&gt;As you might know, the phone allows for two categorisations of Applications, apps, and games. Both can be pinned to the tiles screen, but the first appears in the applications list (to the right of the tiles screen) and the latter is on the Games Hub. So how do we get it there? Here comes a three part lesson learned.&lt;/p&gt;
&lt;p&gt;Part 1, how to set where your application ends up? In the solution, when you create a new Silverlight project, the file WMAppManifest.xml is created in the Properties folder with the setting Genre=&amp;ldquo;apps.Normal&amp;rdquo;. If you set this to apps.games, your application will be place inside the games hub. Alternatively, when you create a WP7 XNA application, you will have apps.games, and by changing to apps.normal, you will no longer be placing you xna application in the games hub. One thing to note here, is that this does not affect the categorisation of you application, this is done during the submission process.&lt;/p&gt;
&lt;p&gt;This brings me to part 2 of the apps verses game lesson: &lt;strong&gt;icons&lt;/strong&gt;. When you create a silverlight wp7 application, you get an image in the project called ApplicationIcon.png, with a resolution of 62x62. This is the size of the icon in the applications list. However, when you create an xna application, you get a GameThumbnail.png, which is 173x173. There is a really good reason for this: in the Game Hub, games get bigger icons. This means that if you start with a silverlight application, and change its genre to apps.games, you get a distorted icon, as the phone tries to stretch the 62x62 icon to the 173x173 size. So you need to make sure that you make the image for the icon a 173x173 image, if its a game.&lt;/p&gt;
&lt;p&gt;A side note here is that a separate image is used for the tile background, but this too is 173x173. What makes this a bit of a problem is part 3 of the lesson. In the emulator, you only get a subset of the phones functionality. The emulator doesn&amp;rsquo;t include the Games Hub for instance. This means that once you set the application to become a game, you can no longer launch it from the phone, without starting it through Visual Studio. This relates to the last bit, because without looking on an actual device, you might not notice you need to change the icon size. This is what happened to me before I tested it on an actual device. The next lesson is also as a result of finally testing on an actual device.&lt;/p&gt;
&lt;h3 id=&#34;4-performance&#34;&gt;4) Performance&lt;/h3&gt;
&lt;p&gt;There are a few things to know about the emulator. 1, it performs better on the cpu then the actual device will. 2) sometime graphics processing will be better on the device then on the emulator. This all comes down to a very simple lesson, always test on a real device. I noticed that my application was not running smoothly on a real device, and made a few enhancement to improve this.&lt;/p&gt;
&lt;p&gt;I was ready to submit. I filled out all the details, had a activated account, sent through all my verification details, and submitted my first draft of Bacon Vaders. After a few days I had my response and my next lesson. I failed validation.&lt;/p&gt;
&lt;h3 id=&#34;5-contrast&#34;&gt;5) Contrast&lt;/h3&gt;
&lt;p&gt;If you have played with the phone, or the emulator, you would see that there are two basic themes to the device, light and dark. From silverlight, this theme is used for the font color, and backgrounds. many theme resources are available to use when you need to set the colour of something, including the accent colour. Unfortunately, I didn&amp;rsquo;t use these. I failed the validation because when you put the phone in light mode, you couldn&amp;rsquo;t read some of the text, since I had made a few rectangles with either black or white translucent colours, instead of using the provided theme resources. So I quickly fixed this up, and got my application resubmitted. This time it passed, and now my app is available on the marketplace. For more information about the specifications that are tested against, &lt;a href=&#34;http://msdn.microsoft.com/en-us/library/hh184843(v=VS.92).aspx&#34;&gt;check here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;6-silverlight-for-games&#34;&gt;6) Silverlight for Games&lt;/h3&gt;
&lt;p&gt;There are a few issues with the current version of my game. I have some performance issues with my game loop. This brings me to my second to last lesson, building games in silverlight. If you are building a simple game, without any real-time processing, or a nominal gameloop, you can build games in silverlight, especially if you want to rely on the animations, UI dynamic layouts and simple 2D graphics that it provides in a nice API . If you need a gameloop, however, XNA can do all the heavy lifting for you. And if you want to do 3D on the phone, you will certainly want to use XNA. Of course, now you can get the best of both world with using XNA and silverlight together on WP7 Mango. If I built this again, I would most likely use XNA to do it, but for this short build-time project, I had to go with what I knew.&lt;/p&gt;
&lt;h3 id=&#34;7-tasks-on-the-emulator&#34;&gt;7) Tasks on the emulator&lt;/h3&gt;
&lt;p&gt;Some things I have come across since finishing, while trying to add a few tasks to my application, such as rating, links to my website, and integrated sending feedback/bug reports, have been interesting discoveries. This relates to the Tasks in the API, and to the hubs and built in applications. I wont go into too much detail, but you can basically use the tasks as a backdoor to access the hidden hubs. From there, you can set up an email account or two, as well as a few other settings, and then get a lot more functionality out of the tasks. More about this can be seen on &lt;a href=&#34;http://dotnet.dzone.com/articles/real-email-accounts-inside&#34;&gt;this blog post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So there you have it. 7 lessons from 7 days developing an application for Windows Phone 7.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Time for an update</title>
      <link>https://blog.csmac.nz/post/time-for-an-update/</link>
      <pubDate>Fri, 10 Sep 2010 08:33:12 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/time-for-an-update/</guid>
      <description>&lt;p&gt;So I really should have posted something sooner, but I&amp;rsquo;ve been so busy with other things. Anyway, Change should soon be coming, I have a whole backlog of things i need to post about, and I&amp;rsquo;ve started using Twitter, which should result in this post being tweeted about due to a new plugin (fingers crossed). So here is my mental note, to myself and perhaps also a promise to the wider public, of what i hope to get done to this site over the next few months (I hope this is realistic enough :-) ).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Finish Photo Album Application&lt;/li&gt;
&lt;li&gt;Restyle the site&lt;/li&gt;
&lt;li&gt;Add twitter and Social Networking to my site&lt;/li&gt;
&lt;li&gt;Post about the HTML bridge&lt;/li&gt;
&lt;li&gt;Post about DataTemplateSelector&lt;/li&gt;
&lt;li&gt;Post about Attached Behaviour and default item selection&lt;/li&gt;
&lt;li&gt;Post about Blend and UI Styling&lt;/li&gt;
&lt;li&gt;Create a Silverlight frontend for WordPress&lt;/li&gt;
&lt;li&gt;Create Silverlight Tag Cloud&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And if i manage to get through all that I can probably afford to skip another month of not posting! lets see how we go aye?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Playing with Silverlight</title>
      <link>https://blog.csmac.nz/post/playing-with-silverlight/</link>
      <pubDate>Mon, 21 Sep 2009 22:54:49 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/playing-with-silverlight/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve just started to experiment with silverlight, well, silverlight 2 to be exact. Its an interesting combination of C# and xml markup, but i like it none-the-less. So far if made a series of buttons that change elements on the screen, nothing special, but am keen to get stuck into something more substantial. Maybe if i get my traffic simulator working in C++ ill port it over to silverlight? We shall see.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>My First YouTube Post</title>
      <link>https://blog.csmac.nz/post/my-first-youtube-post/</link>
      <pubDate>Sun, 15 Feb 2009 22:31:58 +0000</pubDate>
      
      <guid>https://blog.csmac.nz/post/my-first-youtube-post/</guid>
      <description>&lt;p&gt;Well here is the YouTube movie I promised, 6 weeks work to make, and im really proud of it.&lt;/p&gt;
&lt;iframe width=&#34;560&#34; height=&#34;315&#34; src=&#34;https://www.youtube-nocookie.com/embed/ZMvdaIs1tCo&#34; title=&#34;YouTube video player&#34; frameborder=&#34;0&#34; allow=&#34;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&#34; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;This was made using Blender for the animation, and GIMP to prepare the stop motion frames. Be sure to keep posted for the second installment of Fred. :)&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>