<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Matt's Blog</title><link href="https://blog.wakayos.com/" rel="alternate"/><link href="https://blog.wakayos.com/feeds/all.atom.xml" rel="self"/><id>https://blog.wakayos.com/</id><updated>2026-03-10T00:00:00-04:00</updated><subtitle>Developer, Devops Guy in a Govtech World</subtitle><entry><title>Thinking of Atari Writer</title><link href="https://blog.wakayos.com/thinking-of-atari-writer.html" rel="alternate"/><published>2026-03-10T00:00:00-04:00</published><updated>2026-03-10T00:00:00-04:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2026-03-10:/thinking-of-atari-writer.html</id><summary type="html">&lt;p&gt;Where I have fond memories of AtariWriter&lt;/p&gt;</summary><content type="html">&lt;h1&gt;AtariWriter is like a time machine&lt;/h1&gt;
&lt;p&gt;My first job doing computer work was for my Mom, who worked at a
doctors office. They didn't have the means to easily send out dunning
letters, so she recruited me to use AtariWriter to do a mass mailing
of dunning letters with addresses and names.&lt;/p&gt;
&lt;p&gt;AtariWriter was totally cool, you could spell check, mail merge and
the file didn't disappear when you turned off the computer, if you
remembered to save the file.&lt;/p&gt;
&lt;p&gt;This weekend I had some LLMs generate the whole thing, including a
bunch of cool accessory features to try to make it useful.&lt;/p&gt;
&lt;p&gt;I will probably have to do a lot of manual tweaking to find the right
mix of retro and modern usability.&lt;/p&gt;</content><category term="devlog"/><category term="devlog"/></entry><entry><title>Did I work on the right kind of side project?</title><link href="https://blog.wakayos.com/side-projects-big-apps-vs-little-libraries.html" rel="alternate"/><published>2026-01-04T00:00:00-05:00</published><updated>2026-01-04T00:00:00-05:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2026-01-04:/side-projects-big-apps-vs-little-libraries.html</id><summary type="html">&lt;p&gt;Did I work on the right kind of side project?&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Choosing a side project:&lt;/h1&gt;
&lt;p&gt;December just wrapped up and I didn't get done nearly as many professional side projects or portfolio projects as I'd
hoped, I got the flu instead.&lt;/p&gt;
&lt;p&gt;My career happens to be almost entirely "Business Computing", helping large organizations capture data, do something
with it, search and aggregate it sometimes.&lt;/p&gt;
&lt;p&gt;Those projects are huge, multiyear projects that take 10 people to create it, another 3-5 people to maintain it forever.&lt;/p&gt;
&lt;p&gt;I have maybe 4 hours to do a side project, maybe 20 spread across a month. So I've been doing small python libraries and
CLI tools and I go out of my way to avoid incorporating server products or databases.&lt;/p&gt;
&lt;p&gt;On one hand, I have built up a portfolio of side projects that are complete, but none of them are interesting to
hypothetical recruiters for "Business Computing"&lt;/p&gt;
&lt;p&gt;So I'm pivoting to trying to do more mini-websites. I still don't plan to host a live 24x7 database, but I can make&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a local first experience&lt;/li&gt;
&lt;li&gt;generate a static website&lt;/li&gt;
&lt;li&gt;record a YouTube video of what it does because no one in my target audience will clone my repo and do the 20 steps to
  install&lt;/li&gt;
&lt;li&gt;blog about it with some screenshots&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now I just need to time travel back in time and reallocate all the time I spent on my past portfolio projects.&lt;/p&gt;</content><category term="devlog"/><category term="devlog"/></entry><entry><title>Taking control of my social media use</title><link href="https://blog.wakayos.com/taking-control-of-my-social-media-use.html" rel="alternate"/><published>2026-01-01T00:00:00-05:00</published><updated>2026-01-01T00:00:00-05:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2026-01-01:/taking-control-of-my-social-media-use.html</id><summary type="html">&lt;p&gt;Can I get rid of algorithmic feeds?&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Establishing the problem&lt;/h2&gt;
&lt;p&gt;Social media is a double-edged sword. I enjoy the human contact that I would otherwise miss, given that I work from
home as an IT worker.&lt;/p&gt;
&lt;p&gt;On the other hand, my time tracker say that I routinely burn 10-20 hours on social media, the bulk of that time spent
scrolling, which is bad for my mood in addition to squeezing out other more valuable activities out of my day.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Wake up scrolling.&lt;/li&gt;
&lt;li&gt;Twinge of boredom scrolling. This is the worst, it kicks me out of whatever I was doing.&lt;/li&gt;
&lt;li&gt;Waiting for something scrolling. In IT work, waiting is pretty common.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On the other hand, sometimes it isn't bad, some pro-social events that happen&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I post a thought that gets some feedback.&lt;/li&gt;
&lt;li&gt;I find a post that I can usefully contribute to&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Establishing the solution&lt;/h2&gt;
&lt;p&gt;Obviously, the solution is to write more code.&lt;/p&gt;
&lt;h3&gt;A feed of people&lt;/h3&gt;
&lt;p&gt;First, the feed could be a feed of people, not the infinite scroll. This is the most difficult part to fix. A feed of
people is a newsfeed where the content is news about those people, especially mutuals or people that ever comment on
your posts. This would be a feed where each person shows once, retweets are absent, non-mutuals are de-emphasized, posts
of, say newspaper articles are de-emphasized.&lt;/p&gt;
&lt;p&gt;The number of people you follow stay the same, the number of people who posted in the last 24 hours is finite. This feed
should be something that could be consumed in finite time, has a stopping point.&lt;/p&gt;
&lt;h3&gt;Content curated by friends&lt;/h3&gt;
&lt;p&gt;There used to be a Twitter client that downloaded all your friends posts and created a whole new browsing experience.
Some of the tabs (deemphasized ones) in twitter also gave you a new experience, e.g. the media tab turned twitter into
a photo website, or a YouTube site with content made or curated by your friends.&lt;/p&gt;
&lt;p&gt;This could work for a variety of content types&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A news tab&lt;/li&gt;
&lt;li&gt;A books tab&lt;/li&gt;
&lt;li&gt;A Github repos tab&lt;/li&gt;
&lt;li&gt;Best finds tab (e.g. all your friends retweets)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'm of two minds about how the curated content tabs should work. Twitter, et al, want to increase your minutes spent on
the site, so twitter cards and content is brought into your feed. But I think these tabs should be launching points,
kind of like how google use to be your front door to the web that took you places.&lt;/p&gt;
&lt;h3&gt;First draft&lt;/h3&gt;
&lt;p&gt;Anyhow, this is my first draft, "
Mastohuman" &lt;a href="https://github.com/matthewdeanmartin/mastohuman"&gt;https://github.com/matthewdeanmartin/mastohuman&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I don't like the name and the LLM didn't really get my vision. But that's not the point of this blog post, I'm thinking
aloud about what the final product should look like.&lt;/p&gt;
&lt;p&gt;But I like the trajectory of this project and if I could switch to a "finite feed", that would really improve my quality
of life.&lt;/p&gt;</content><category term="devlog"/><category term="social-media"/></entry><entry><title>Creating a Portfolio Website</title><link href="https://blog.wakayos.com/creating-a-portfolio-website.html" rel="alternate"/><published>2025-12-20T00:00:00-05:00</published><updated>2025-12-20T00:00:00-05:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2025-12-20:/creating-a-portfolio-website.html</id><summary type="html"/><content type="html">&lt;h2&gt;How many ways to create a home page?&lt;/h2&gt;
&lt;p&gt;I think people (like me) might want to have a personal website for 3 reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Job hunting. "I need a job, you need a techie"&lt;/li&gt;
&lt;li&gt;An Identity site. "This is who I am"&lt;/li&gt;
&lt;li&gt;Project promotion. "Look at this thing I did."&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As of today, I don't need a job, but when I do, these are the features I wish my website had:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easy way to list my resumes&lt;/li&gt;
&lt;li&gt;Easy way to let a technical hiring manager go from a skill claim directly to a portfolio repo demonstrating that&lt;/li&gt;
&lt;li&gt;A way to quickly recombine the parts of my resume to create new job requisition specific resumes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also wish that all the various ways to repackage the data about me could be auto-updated.&lt;/p&gt;
&lt;p&gt;So I've been coding, with LLM help, most of the above.&lt;/p&gt;
&lt;h2&gt;The Perfect Readme&lt;/h2&gt;
&lt;p&gt;Github has a special readme that shows top-of-page on your profile page.&lt;/p&gt;
&lt;p&gt;My perfect profile readme has all the information about me. That is more than fits on a screen, so
I've swung towards a much shorter and depend on mode (job hunting, identity, project-promotion), switches from longer to
shorter.&lt;/p&gt;
&lt;p&gt;When complete, I plan to have most of the information available on markdown links from the compact
front page. I don't expect people to browse those much, so I got an HTML site, too.&lt;/p&gt;
&lt;p&gt;Github gives you a primary URL and I've pointed that to the HTML version, with&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Resume looking thing&lt;/li&gt;
&lt;li&gt;Grouped project list&lt;/li&gt;
&lt;li&gt;A static Swagger API, because why not. I was thinking of using this as a datasource for an angular website.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Taxonomy is pain&lt;/h2&gt;
&lt;p&gt;The biggest challenge is just managing the data and cleaning it up.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Projects need to be grouped, tagged&lt;/li&gt;
&lt;li&gt;Dead projects need to be deleted, archived, hidden.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tagging is a particular pain. There are at least 3+ ways projects need to be categorized&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Github's tags, so github searchers can find my repo or more likely, as a hint to what the repo is about&lt;/li&gt;
&lt;li&gt;pypi's tags, so package searcher can find my packages&lt;/li&gt;
&lt;li&gt;related to a skill&lt;/li&gt;
&lt;li&gt;Language which sometimes is a skill and sometimes it is noise in the tags&lt;/li&gt;
&lt;li&gt;relevant to a job hunt&lt;/li&gt;
&lt;li&gt;quality- is it awesome or not worth looking at because it is too new, too old, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Dreams of publishing this&lt;/h2&gt;
&lt;p&gt;It is on my wishlist to make this generic enough to publish on pypi.&lt;/p&gt;
&lt;p&gt;It will probably end up being github centric and python centric because of the pypi integration.&lt;/p&gt;</content><category term="programming"/><category term="programming"/></entry><entry><title>Vegan 3:15 Marathon Project, Part 2</title><link href="https://blog.wakayos.com/vegan-three-fifteen-marathon-project-update.html" rel="alternate"/><published>2025-03-03T00:00:00-05:00</published><updated>2025-03-03T00:00:00-05:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2025-03-03:/vegan-three-fifteen-marathon-project-update.html</id><summary type="html">&lt;p&gt;Can a mediocre vegan runner match an omnivore professional?&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Can a mediocre vegan runner match an omnivore professional? Part 2&lt;/h1&gt;
&lt;p&gt;Well, not yet. Here is my theory why:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I need about 5 years of serious running to build up to it&lt;/li&gt;
&lt;li&gt;I'm starting around age 48-49, currently 50, so I'm doing this in difficult mode, as compared to if I'd started
  when I was 35&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My marathon times to date are definitely mediocre.&lt;/p&gt;
&lt;p&gt;Any, after a race, I do bounce back really fast, so I think the vegan-recovery advantage is a real thing, but I'm not
surrounded by enough runners to make this data based opinion.&lt;/p&gt;</content><category term="running"/><category term="running"/><category term="marathon"/></entry><entry><title>Vegan 3:15 Marathon Project</title><link href="https://blog.wakayos.com/vegan-three-fifteen-marathon-project.html" rel="alternate"/><published>2023-05-14T00:00:00-04:00</published><updated>2023-05-14T00:00:00-04:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2023-05-14:/vegan-three-fifteen-marathon-project.html</id><summary type="html">&lt;p&gt;Can a mediocre vegan runner match an omnivore professional?&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Can a mediocre vegan runner match an omnivore professional?&lt;/h1&gt;
&lt;p&gt;My uncle worked at the YMCA, ran sometimes twice a day as part of job as a fitness coach. He
ran dozens of marathons in his life, with a known lifetime PR of 3:15 at the age of 50. He, like my
Dad and everyone else at the time, ate like everyone else--neither vegetarian or vegan.&lt;/p&gt;
&lt;p&gt;I recently saw "The Game Changers" a documentary with the thesis, "Plant Based athletes recover
faster and so can work out harder and more frequently." I figure I should put that to the test.&lt;/p&gt;
&lt;p&gt;My goal is to run a 3:15 marathon at the 2024 Marine Corps Marathon. That 13 months from now.&lt;/p&gt;
&lt;h1&gt;Can I do it?&lt;/h1&gt;
&lt;p&gt;You can take your recent races and plug them into calculators to predict your race time. Depending
on the calculator, it seems like my 5k, 10k and half marathon paces are not far from where they need to
be. I've never run a marathon before, so I only have predictions, which say I have quite a large gap
to close.&lt;/p&gt;
&lt;h1&gt;How will I do it?&lt;/h1&gt;
&lt;p&gt;Well, eating plant based of course. But also eating clean in the currently sense of clean- low saturated fat,
high fiber, high carb, etc.&lt;/p&gt;
&lt;h2&gt;Daily Goals&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Grits or oats for breakfast&lt;/li&gt;
&lt;li&gt;Something vegan for lunch and dinner&lt;/li&gt;
&lt;li&gt;Less restaurant food than usual&lt;/li&gt;
&lt;li&gt;Less&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Supplements and why&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;B12 - because there's no bacterial sources of b12 in modern vegan diet.&lt;/li&gt;
&lt;li&gt;D - because I'm indoors a lot&lt;/li&gt;
&lt;li&gt;Hibiscus - to reduce blood pressure by 5-10 points&lt;/li&gt;
&lt;li&gt;Omega 3 Fatty Acids, Lutein - Speculated to help with brain, nervous system, vision because I'm not young anymore.&lt;/li&gt;
&lt;li&gt;Magnesium - to replace magnesium lost to sweating&lt;/li&gt;
&lt;li&gt;No multivitamin - too many effects&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Post workout&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;20g protein after workouts. Replace any protein lost, rebuild muscles, tendons, etc.&lt;/li&gt;
&lt;li&gt;Salt tablet, like Nuun. To prevent feeling exhaustion post workout&lt;/li&gt;
&lt;li&gt;Watermelon juice. Citruline is speculated to reduce muscle soreness, speed recovery&lt;/li&gt;
&lt;li&gt;Cracker or some sugary drink. Speeds restocking glycogen in liver and muscles&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pre-workout/Race&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Beet juice - temporary increase to Vo2 max/cardiovascular efficiency&lt;/li&gt;
&lt;li&gt;Taurine - 3g speculated to help with recovery&lt;/li&gt;
&lt;li&gt;Creatine - for speed bursts and has good data supporting its use in sports&lt;/li&gt;
&lt;li&gt;Caffeine - for speed, data appears to support net-benefit&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Actions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Hired a coach and will follow the plan as close as I can&lt;/li&gt;
&lt;li&gt;Sleep 11 hours a day&lt;/li&gt;
&lt;li&gt;Do something to tighten up scheduling in the rest of my life to make time for enough running&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Information Tracking&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Use Garmin tracker&lt;/li&gt;
&lt;li&gt;Use Garmin chest strap HR tracker&lt;/li&gt;
&lt;li&gt;Use Strava and Final Surge&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Gear&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Carbon plate shoes on race days only&lt;/li&gt;
&lt;li&gt;Maximalist shoes because I'm used to them and changing is as risky as any merit or demerit of a shoe type&lt;/li&gt;
&lt;/ul&gt;</content><category term="running"/><category term="running"/><category term="marathon"/></entry><entry><title>Catching up on TypeScript</title><link href="https://blog.wakayos.com/catching-up-on-typescript-2023.html" rel="alternate"/><published>2023-04-08T00:00:00-04:00</published><updated>2023-04-08T00:00:00-04:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2023-04-08:/catching-up-on-typescript-2023.html</id><summary type="html">&lt;p&gt;After avoid JavaScript for a few years, I must reface my nemesis, the undefined, the null, the falsy.&lt;/p&gt;</summary><content type="html">&lt;h1&gt;Hello TypeScript, again.&lt;/h1&gt;
&lt;h2&gt;Surprise!&lt;/h2&gt;
&lt;p&gt;So, I had ChatGPT write a merit tracker. It wrote up some Javascript I don't even recognize anymore.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;const&lt;/code&gt; is everywhere&lt;/li&gt;
&lt;li&gt;looks like &lt;code&gt;requires()&lt;/code&gt; won the module wars&lt;/li&gt;
&lt;li&gt;JS isn't restricted to a DOM and can deal with CLI args with &lt;code&gt;yargs&lt;/code&gt; and the file system with &lt;code&gt;fs&lt;/code&gt; ... but&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fs&lt;/code&gt; is already passé and &lt;code&gt;fs-extra&lt;/code&gt; is the new hotness&lt;/li&gt;
&lt;li&gt;&lt;code&gt;export&lt;/code&gt; is now a keyword and not an IIFE (Immediately Invoked Function Expression)&lt;/li&gt;
&lt;li&gt;There are things like python f-strings, e.g. &lt;code&gt;console.log(``${date}.``)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I had the bot convert it to TypeScript. Usefully it gave me step-by-step instructions to convert it myself, rather than
giving me a big blob of TypeScript.&lt;/p&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;p&gt;I installed &lt;code&gt;jest&lt;/code&gt;, several times to be sure. I ended up installing all of these.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;@jest/globals&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;^29.5.0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;@types/jest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;^29.5.0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;jest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;^29.5.0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;&amp;quot;ts-jest&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;^29.1.0&amp;quot;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then I had to install a &lt;code&gt;jest-config.js&lt;/code&gt; file. Without it, the tests ran twice, one time for the typescript version and
another time for javascript version. The relevant magic is the &lt;code&gt;testRegex&lt;/code&gt;, particular the last part that restricts
running tests against the &lt;code&gt;.ts&lt;/code&gt; version of the file.&lt;/p&gt;
&lt;p&gt;This later turns out to be a bad idea. &lt;code&gt;testMatch: ['**/*.test.(ts|tsx)'],&lt;/code&gt; is better, and less likely to be buggy
regex. The real problem was I wasn't specifying a dist folder in &lt;code&gt;tsconfig.json&lt;/code&gt; e.g. &lt;code&gt;"outDir": "dist"&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {import(&amp;#39;ts-jest&amp;#39;).JestConfigWithTsJest} */&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;roots&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;./tests&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;preset&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;ts-jest&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;testEnvironment&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;node&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;testRegex&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;moduleFileExtensions&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;js&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ts&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tsx&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;json&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Astonishing&lt;/h2&gt;
&lt;p&gt;If I imported &lt;code&gt;import jest from 'jest';&lt;/code&gt; I got error messages about jest not having certain properties. So I removed the
import altogether and it worked! Astonishing.&lt;/p&gt;
&lt;p&gt;I also ran into a problem where the mocks failed to have the right properties. The error message:
&lt;code&gt;Cannot read properties of undefined (reading 'readJsonSync')&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The solution, put this into &lt;code&gt;tsconfig.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;quot;esModuleInterop&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Coverage&lt;/h2&gt;
&lt;p&gt;Now coverage is not working, it consistent reports 0% coverage and acts generally like the tests are using .js and
coverage is looking at .ts or vica versa.&lt;/p&gt;
&lt;p&gt;The problem was .ts and .js files were compiled to the same directory and the coverage tool was looking at the wrong
one. I had to tell typescript to compile the .js files to a dist folder.&lt;/p&gt;
&lt;h2&gt;Linting&lt;/h2&gt;
&lt;p&gt;I'm working through that right now. I'll publish again when I get it working.&lt;/p&gt;</content><category term="typescript"/><category term="typescript"/></entry><entry><title>Creating a useful and funny python serializer</title><link href="https://blog.wakayos.com/python-markpickle-2023.html" rel="alternate"/><published>2023-03-19T00:00:00-04:00</published><updated>2023-03-19T00:00:00-04:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2023-03-19:/python-markpickle-2023.html</id><summary type="html">&lt;p&gt;I wrote a library that serializes and deserializes markdown to and from python, but more in the style of pickle&lt;/p&gt;</summary><content type="html">&lt;p&gt;and less in the style of a document object model.&lt;/p&gt;
&lt;h1&gt;Hello markpickle&lt;/h1&gt;
&lt;p&gt;I got the name from ChatGPT.&lt;/p&gt;
&lt;h2&gt;Origin Story&lt;/h2&gt;
&lt;p&gt;I wanted an API to support as many mime types as possible. Some mime types are for the people, such as PDF, Excel/CSV.
Some time types are for the machines, like json, bson.&lt;/p&gt;
&lt;p&gt;I thought, what about HTML and text? HTML has a problem with XSS risks. Text has a problem of not having much of a
standard story for "styled" plaintext. Except for Markdown. Can I use markdown as a mime type for what starts out as a
JSON object?&lt;/p&gt;
&lt;h2&gt;Challenges&lt;/h2&gt;
&lt;p&gt;The app is two functions, loads and dumps and they take or return an &lt;code&gt;Any&lt;/code&gt; type and take or return a string. The &lt;code&gt;Any&lt;/code&gt;
is a problem, because mypy doesn't know how to deal with arbitrarily complex types. It seems to get confused with
&lt;code&gt;Union&lt;/code&gt;s of &lt;code&gt;Union&lt;/code&gt;s of &lt;code&gt;Union&lt;/code&gt;s. It gets confused with generics, e.g. lists that can work with any contents.&lt;/p&gt;
&lt;h2&gt;Impedance Mismatches&lt;/h2&gt;
&lt;p&gt;Markdown has some analogies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;header groupings + paragraphs make dicts, or even nested dicts&lt;/li&gt;
&lt;li&gt;Lists or lists of lists&lt;/li&gt;
&lt;li&gt;tables are dicts, but you can only put scalars in the values. This makes python objects of a certain level of nesting
  unrepresentable.&lt;/li&gt;
&lt;li&gt;strings and non-string types can be represented, but you can only infer a number should be integer. This blocks round
  tripping.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some things are impossible&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;empty dictionaries, empty lists exist in python but have no representation in markdown. An empty list is just
  zero-length whitespace where the list is not. This blocks round tripping.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Python has no use for a lot of markdown formatting, such as bold, or code block or quote. Those things would just be
strings and they'd continue to hold markdown in the string.&lt;/p&gt;</content><category term="python"/><category term="python"/></entry><entry><title>Matt's Health Advice in 2023</title><link href="https://blog.wakayos.com/health-advice-2023.html" rel="alternate"/><published>2023-02-26T00:00:00-05:00</published><updated>2023-02-26T00:00:00-05:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2023-02-26:/health-advice-2023.html</id><summary type="html">&lt;p&gt;I'm going to talk about how I'm managing my health and how it is going&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Overall Goal&lt;/h2&gt;
&lt;p&gt;The overall goal is to maximize your healthspan. More and more people are making it to or close to their maximum
lifespan, of something close to 100. At the same time, more people are getting lifestyle diseases that mean they will be
sick a good chunk of that.&lt;/p&gt;
&lt;h2&gt;What I Eat&lt;/h2&gt;
&lt;p&gt;I would still be vegan if the health data wasn't panning out in favor of plant based diets. I believe the data
demonstrates that I've lucked out and my ethical preferences match up with my health goals.&lt;/p&gt;
&lt;p&gt;I was omnivore until age 16. I read a book that made the case for vegetarianism and adopted it. I ate dairy and egg
until about age 38 or so. Despite the dairy, for most of the time I tried to be "low fat" which is somewhat
contradictory if you eat any cheese at all. For this whole time I had a healthy body weight, 145-150 lbs for a 5'11"
guy.&lt;/p&gt;
&lt;p&gt;I am vegan for a bit over a decade. My lipid numbers are great. Blood pressure fine, but could be better.&lt;/p&gt;
&lt;h2&gt;What I do&lt;/h2&gt;
&lt;p&gt;I ran in high school, I did a few years or two of no particular exercise. After starting a desk job and getting colossal
back pain, I started doing follow-along exercise on DVD videos. That worked out great. On and off, I did bicycling,
scootering, roller-blading, hiking. I resumed running about a decade ago and have been particularly serious in the last
five.&lt;/p&gt;
&lt;h2&gt;Mood&lt;/h2&gt;
&lt;p&gt;I think that we all suffer from anger, depression and anxiety in different ratios. Depending on what ratio you got, you might have a personality, or a diagnosable disorder.&lt;/p&gt;
&lt;h2&gt;Optimizing&lt;/h2&gt;
&lt;p&gt;Between eating right (vegan) and exercising (running) I'm doing pretty good. Everything else is a micro-optimization.&lt;/p&gt;
&lt;p&gt;I'm also pushing 50. Even if you eat right &amp;amp; exercise you'll still age. I got grey hairs &amp;amp; when the knee parts fail, they really fail. Some joints have the start of arthritis. The eyes have nuisance cataracts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vitamins&lt;/li&gt;
&lt;li&gt;B12. Only bacteria make it, animals don't. Heck even farm animals have to take B12.&lt;/li&gt;
&lt;li&gt;Creatine. For sprinting &amp;amp; strength training&lt;/li&gt;
&lt;li&gt;Magnesium. Because I run and sweat a lot.&lt;/li&gt;
&lt;li&gt;Hibiscus - Weak anti-hypertensive.&lt;/li&gt;
&lt;li&gt;Coffee - makes me type faster&lt;/li&gt;
&lt;li&gt;Sometimes&lt;/li&gt;
&lt;li&gt;Algal Omega Fatty Acids. They are taken up by the brain. Who knows it if helps.&lt;/li&gt;
&lt;li&gt;Other B vitamins.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I used to, but no longer take multivitamins, the data on them was negative.&lt;/p&gt;
&lt;h2&gt;Sources&lt;/h2&gt;
&lt;p&gt;My favorite source on this sort of thing is Dr. Gregor. The rest of the sources are lost to memory, because they were
books I checked out at the library.&lt;/p&gt;</content><category term="health"/><category term="health"/></entry><entry><title>Running, OpenAI Side Project, Shells</title><link href="https://blog.wakayos.com/running-openai-side-project-shells.html" rel="alternate"/><published>2023-02-12T00:00:00-05:00</published><updated>2023-02-12T00:00:00-05:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2023-02-12:/running-openai-side-project-shells.html</id><summary type="html">&lt;p&gt;I'm training for another half-marathon, learning prompt engineering and trying to switch to fish.&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Running&lt;/h2&gt;
&lt;p&gt;Last December, I ran my 1/2 marathon, got a mild case of extensor tendonitis (self diagnosed) and then the holidays and
side projects took over. So I ran between 5 and 7 miles per week most weeks. This week I'm back to 21+ miles per week.&lt;/p&gt;
&lt;p&gt;I got a half-marathon coming up fast, in 7 weeks, so I figure I need to ramp up to 6 miles a day. That means the running
I do over the next 3 weeks has the most impact, if it takes 4 weeks for training to have an impact. Last time I did a
surge of training, I did daily split sessions and strength training most days.&lt;/p&gt;
&lt;h2&gt;Side Projects&lt;/h2&gt;
&lt;p&gt;My most successful side project has been &lt;a href="https://github.com/matthewdeanmartin/cheaper_openai"&gt;cheaper_openai&lt;/a&gt; which I
created when I heard they might charge $42 a month. The lower price came out and I cancelled my satellite radio and
signed up. Which should you use? Assistant (ChatGPT) is for hard questions, coding. Davinci is for experiments where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;having a machine make many similar request would help, e.g. trying to get a funny joke&lt;/li&gt;
&lt;li&gt;having code compile the response would help, e.g. book writing&lt;/li&gt;
&lt;li&gt;the response is machine-readable, e.g. generating json, yaml, etc&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Otherwise, most of the time, Assistant is smarter.&lt;/p&gt;
&lt;h2&gt;The rabbit-hole of shells&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;sh&lt;/code&gt; and &lt;code&gt;bash&lt;/code&gt; shell are both annoying, brain-damaged programming languages. I tried to get Davinci to generate a
whole book on &lt;code&gt;fish&lt;/code&gt; and &lt;code&gt;powershell&lt;/code&gt; shell programming as well as how to do shell-programming-like tasks using &lt;code&gt;python&lt;/code&gt;
with mixed results.&lt;/p&gt;
&lt;p&gt;Optimal shell workflow (which I haven't achieved myself)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fish for a daily driver&lt;/li&gt;
&lt;li&gt;python for anything not mostly just calling other commands (i.e. not 90% subprocess code)&lt;/li&gt;
&lt;li&gt;powershell for anything windows specific or where the code for some reason needs to be shell&lt;/li&gt;
&lt;li&gt;bash for esperanto of scripts, but with none of esperanto's charm or personality&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Short story, I think I'm going to try to make fish my default shell.&lt;/p&gt;</content><category term="life"/><category term="life"/></entry><entry><title>Side projects</title><link href="https://blog.wakayos.com/docker-on-gitlab-polyrepos-chatgpt.html" rel="alternate"/><published>2023-01-21T00:00:00-05:00</published><updated>2023-01-21T00:00:00-05:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2023-01-21:/docker-on-gitlab-polyrepos-chatgpt.html</id><summary type="html">&lt;p&gt;Github and ChatGPT experiments, learning about mono and polyrepos&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Migrating my docker images to github.&lt;/h2&gt;
&lt;p&gt;I find Github's pricing guidance bemusing, but it looks like I can host more public images on Github than I can on Dockerhub (many more than 1 vs 1). The limits are on bandwidth per month (1GB) with no obvious guidance on how that is calculated.&lt;/p&gt;
&lt;p&gt;Anyhow, &lt;a href="https://github.com/matthewdeanmartin?tab=packages"&gt;my Stackoverflow novelty build tool and my text editor novelty are both available prebuilt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The most challenging part was learning about Github secrets.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I used a recommended workflow file that logs into Dockerhub and Gitlab&lt;/li&gt;
&lt;li&gt;I had to realize GITLAB_TOKEN is automatically available and I don't have to create such a secret.&lt;/li&gt;
&lt;li&gt;I had to create an environment&lt;/li&gt;
&lt;li&gt;Set that environment to "all branches"&lt;/li&gt;
&lt;li&gt;I had to edit the workflow file to explicitly name a &lt;code&gt;environment: NAME_OF_MY_ENVIRONMENT&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next I guess I will experiment with pex/shiv and other ways to package a&lt;/p&gt;
&lt;h2&gt;Monorepo and polyrepo build strategies&lt;/h2&gt;
&lt;p&gt;I just started looking at this stuff. They both appear to be alternate ways to deal with dependency hell. If you read up on the sort of solutions for monorepos, you get ideas for doing the same thing with polyrepos, e.g. builds that trigger builds in other repos, making changes to many repos at the same time as a sort of "transaction".&lt;/p&gt;
&lt;p&gt;So far, I've found tools like &lt;code&gt;gita&lt;/code&gt; which run the same git command against many local repos. The build server part depends on your host, but API for github, gitlab, etc, would simulate the build-script-of-build-scripts. Anyhow, cool stuff.&lt;/p&gt;
&lt;h2&gt;Playing Toca Boca on ChatGPT&lt;/h2&gt;
&lt;p&gt;My 6-year-old daughter and I have been playing Toca Boca with ChatGPT. It is difficult. You prompt needs to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get it to stop saying, "Oh, I'm just a model, I can't do anything"&lt;/li&gt;
&lt;li&gt;Get it to stop saying, "Oh, I'm just a model, I have no wants"&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you tell it to write at a 6-year-old's level that helps.&lt;/p&gt;
&lt;p&gt;Another challenge is that Assistant can't cope with arbitrarily messed up English. Humans can just sound out a 1st grader's text and get it, but Assistant just can't cope. It isn't sounding out word, it can't hear.&lt;/p&gt;</content><category term="devlog"/><category term="devlog"/></entry><entry><title>Meta and stuff</title><link href="https://blog.wakayos.com/chatgpt-markdown-running-jan-15.html" rel="alternate"/><published>2023-01-15T00:00:00-05:00</published><updated>2023-01-15T00:00:00-05:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2023-01-15:/chatgpt-markdown-running-jan-15.html</id><summary type="html">&lt;p&gt;Whatever man, I don't know.&lt;/p&gt;</summary><content type="html">&lt;h2&gt;Telling Assistant to translate python code to Go&lt;/h2&gt;
&lt;p&gt;Yesterday was spent hacking on ChatGPT. I almost got it to convert pymarc to golang. The key is to strip down the source code to the bare bones so that it can fit into Assistants memory.&lt;/p&gt;
&lt;p&gt;I tried &lt;a href="https://github.com/dflook/python-minifier"&gt;python-minifier&lt;/a&gt; but that didn't really help, I think it made it worse by nearly obfuscating some code. If I can't read it, Assistant probably can't either. I think it just needs comments and docstrings stripped out. Assistant really also can only see things as one document, so if you got 10 files, it needs them merged to one, in an order than tells a story.&lt;/p&gt;
&lt;h2&gt;Chasing Markdown down a rabbit hole&lt;/h2&gt;
&lt;p&gt;A while ago I tried to create a markdown build script. Markdown is such a weird thing. It is English, so it needs spellcheck, grammar check. It is a templating language so it can benefit from linting. It also an input to a lot of CMS's that all did different things to handle Markdowns limitations.&lt;/p&gt;
&lt;p&gt;Here is what I made:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/matthewdeanmartin/blog/blob/main/build.sh"&gt;A build script&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/matthewdeanmartin/blog/blob/main/.pre-commit-config.yaml"&gt;A pre-commit script&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also had the pre-commit hook call the build script adn the build commit call &lt;code&gt;pre-commit run&lt;/code&gt; and wondered why it took forever.&lt;/p&gt;
&lt;p&gt;And cloudflare fought with me until I wrote this script to deploy it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/matthewdeanmartin/blog/blob/main/cloudflare.sh"&gt;Cloudflare pages deploy&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="devlog"/><category term="devlog"/></entry><entry><title>Hacking on the first weekend of January 2023</title><link href="https://blog.wakayos.com/what-i-did-today.html" rel="alternate"/><published>2023-01-08T00:00:00-05:00</published><updated>2023-01-08T00:00:00-05:00</updated><author><name>Matthew Martin</name></author><id>tag:blog.wakayos.com,2023-01-08:/what-i-did-today.html</id><summary type="html">&lt;p&gt;Learning about Github Issues, Actions and writing a Markdown build script.&lt;/p&gt;</summary><content type="html">&lt;p&gt;All I did all weekend was Github hacking. First I invested a lot of time learning about
Github Issues and Projects. It is like Jira, but more limited. Will it convince me to stop
using a &lt;code&gt;TODO.md&lt;/code&gt; document? Maybe.&lt;/p&gt;
&lt;p&gt;I also reviewed all my repos, deleted junk repos and forks I don't care about. I added
all my repos to lists, e.g. "My Best Repos" so that I could find them. I noticed that
Github allows pinning repos but not lists and not gists.&lt;/p&gt;
&lt;p&gt;I started adding Github actions to all my repos that I care about and got passing builds
on about half dozen.&lt;/p&gt;
&lt;p&gt;I noticed many repos were text oriented, so I revived my idea of writing a build script for markdown + English.
In other words, doing the things that word-processors do, spellcheck, format, grammar check, but
doing so with the tools of software development.&lt;/p&gt;</content><category term="devlog"/><category term="devlog"/></entry></feed>