<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cal Freitas</title>
	<atom:link href="https://calvinf.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://calvinf.com</link>
	<description>Staff Front-End Engineer in Idaho</description>
	<lastBuildDate>Sat, 03 May 2025 22:36:21 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.3</generator>

<image>
	<url>https://calvinf.com/wp-content/uploads/2023/03/cropped-cal-freitas-wa-32x32.jpg</url>
	<title>Cal Freitas</title>
	<link>https://calvinf.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>My Vite Starter</title>
		<link>https://calvinf.com/blog/2025/05/03/my-vite-starter/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Sat, 03 May 2025 22:34:19 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1706</guid>

					<description><![CDATA[<p>When I was most recently in the process of interviewing at the start of 2025, it became useful to have an up-to-date and efficient front-end stack for coding interviews. This came in handy both for coding assessment projects as well as &#8220;live coding&#8221; evaluations. I have huge affinity for Next.js and use it for most [&#8230;]</p>
The post <a href="https://calvinf.com/blog/2025/05/03/my-vite-starter/">My Vite Starter</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<p>When I was most recently in the process of interviewing at the start of 2025, it became useful to have an up-to-date and efficient front-end stack for coding interviews. This came in handy both for coding assessment projects as well as &#8220;live coding&#8221; evaluations.</p>



<p>I have huge affinity for <a href="https://nextjs.org/">Next.js</a> and use it for most of my website projects (aside from this blog which has been using WordPress since somewhere around WordPress 2.5 in 2008).</p>



<p>However, for a fast and productive prototype stack for a coding interview, <a href="https://vite.dev/">Vite</a> ended up working a lot better. That led me to set up a reusable starter for a Vite app which I could quickly clone, fork, and push to a new (private) repo on GitHub.</p>



<h2 class="wp-block-heading">My Vite Starter</h2>



<ul class="wp-block-list">
<li>GitHub: <a href="https://github.com/calvinf/my-vite-starter">calvinf/my-vite-starter</a><br></li>
</ul>



<p>In building the starter, I had to make choices about which tools would allow me to move most quickly in a coding interview. Here&#8217;s what and why.</p>



<h3 class="wp-block-heading">Runtime: <a href="https://nodejs.org/en">Node.js</a></h3>



<p>While <a href="https://bun.sh/">Bun </a>is wonderful, I&#8217;ve been using Node.js for much longer (pre-1.0) and trust myself to use it better in the context of a coding interview.</p>



<h3 class="wp-block-heading">Package Manager: <a href="https://bun.sh/">Bun</a></h3>



<p>I regularly use <code>npm</code> on projects and have previously used Yarn 4 with Node.js as well, but when I have a choice I&#8217;ve been opting for Bun due to its speed benefits. You can use Bun just for package management. You can also use it as a runtime and that can be a good choice depending on the project &#8211; though you&#8217;ll want to understand where it&#8217;s not compatible with Node.js (though they&#8217;re improving that a lot in the Bun 1.2.x series of releases).</p>



<h3 class="wp-block-heading">Build tool: <a href="https://vite.dev/">Vite</a></h3>



<p>Vite is emerging as one of the most popular front-end build tool solutions. Frameworks like React Router and Remix build on top of Vite. Outside of building with Next.js (which builds on top of other tools like Turbo, SWC, and Webpack), Vite has become the build tool of choice for many.</p>



<h3 class="wp-block-heading">Language: TypeScript</h3>



<p>Whenever possible, I use TypeScript. Most of the projects I work on (aside from personal ones) involve teams of engineers and the type safety can be a huge time saver in those contexts. Particularly for defining shapes used to model data and call API endpoints &#8211; it makes it more clear what needs to be sent where.</p>



<p>I use it on personal projects and coding challenges, too, because it helps me make sure I&#8217;m not making avoidable mistakes where my editor (VS Code) can tell me that I&#8217;m doing something wrong just based on the types (let alone help from tooling like Copilot).</p>



<h3 class="wp-block-heading">Frameworks: React 19, Tailwind 4</h3>



<p>React is still the top choice due to popularity and is an effective way to build front-ends for both client-side and server-side rendering applications. Tailwind 4 has become one of the most popular and broadly used UI and styling frameworks due to its simplicity, ease of reuse, and these days the deep knowledge and number of examples LLMs can reference to give you better advice about the designs you&#8217;re trying to implement.</p>



<h3 class="wp-block-heading">Code Quality: Eslint and Prettier</h3>



<p>I go back and forth on <a href="https://eslint.org/">Eslint</a> vs. <a href="https://biomejs.dev/">Biome</a> and I use both in various projects. The Eslint 8 to 9 upgrade has been a little more painful than previous Eslint updates and as such I chose to migrate some of my projects to Biome instead. Biome has speed benefits, too. The main reason I used eslint here is because it has a broader plugin ecosystem (e.g., Tailwind).</p>



<p>If you&#8217;re using Eslint, you&#8217;ll want to grab <a href="https://prettier.io/">Prettier</a> as well for the code formatting. If you choose Biome, it includes formatting built-in. One of the best reasons to use Prettier is to avoid debates with other engineers over formatting decisions. Make it easy and make it obvious.</p>



<h3 class="wp-block-heading">Unit Testing: <code>bun:test</code></h3>



<p>Yes, you can use Bun for tests even if you don&#8217;t use it for your runtime. The best feature it has going for it is speed. In a starter interview project it may not matter a whole lot, but if you&#8217;re working on a project with hundreds or thousands of tests that may make your life better.</p>



<p>Fortunately, Bun integrates well with React Testing Library and you can use Happy DOM with it.</p>



<p>While you still end up with a lot of dependencies in your lock file due to RTL and Happy DOM, I was happy to avoid using Jest which feels less and less maintained and supported over time despite being one of the kings of unit testing libraries since the initial rise of React in popularity. (I keep wondering when Jest is going to die off &#8211; I expect it will happen as soon as a viable alternative rises up, and maybe that&#8217;s something <code>bun:test</code>.)</p>



<h3 class="wp-block-heading">Not Seen Here</h3>



<p>Other tools you should use, but I don&#8217;t have set up here currently, include <a href="https://www.npmjs.com/package/husky">husky</a> and <a href="https://www.npmjs.com/package/lint-staged">lint-staged</a>. It&#8217;s helpful to automate things like running formatting, type checks, and linting before git commit. And I usually (unless it&#8217;s abismally slow) run unit tests before git push.</p>



<h2 class="wp-block-heading">The Future of the Vite Starter</h2>



<p>I will continue to evaluate the tools I use in <a href="https://github.com/calvinf/my-vite-starter">my Vite starter</a> over time. As mentioned in here, I&#8217;ve considered using Biome, and I may try out other things over time.</p>



<p>As it is, this is a fresh starter for a front-end app and I most recently updated it as I&#8217;m writing this post, on Saturday, May 3, 2025.</p>The post <a href="https://calvinf.com/blog/2025/05/03/my-vite-starter/">My Vite Starter</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Node.js 20, Yarn 4, and Next.js on Docker</title>
		<link>https://calvinf.com/blog/2023/11/10/node-js-20-yarn-4-and-next-js-on-docker/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Fri, 10 Nov 2023 22:38:07 +0000</pubDate>
				<category><![CDATA[Code]]></category>
		<category><![CDATA[Swarzy]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Next.js]]></category>
		<category><![CDATA[Node.js]]></category>
		<category><![CDATA[Yarn]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1658</guid>

					<description><![CDATA[<p>I recently spent time updating a few Swarzy websites including Psalmlist and Swarzy.com. (Yes, this is how I spent my time off for Veteran&#8217;s Day Observed.) I&#8217;ve always found that having and working on other websites keeps me fresh and up-to-date on the latest technologies when I&#8217;m using them at work. As part of tech [&#8230;]</p>
The post <a href="https://calvinf.com/blog/2023/11/10/node-js-20-yarn-4-and-next-js-on-docker/">Node.js 20, Yarn 4, and Next.js on Docker</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<p>I recently spent time updating a few Swarzy websites including <a href="https://psalmlist.com/">Psalmlist</a> and <a href="https://swarzy.com/">Swarzy.com</a>. (Yes, this is how I spent my time off for Veteran&#8217;s Day Observed.) I&#8217;ve always found that having and working on other websites keeps me fresh and up-to-date on the latest technologies when I&#8217;m using them at work.</p>



<p>As part of tech maintenance for a website, it&#8217;s important to keep your dependencies updated. And so I embarked on updating my stack to the latest versions of key dependencies. Here&#8217;s what I&#8217;m using right now:</p>



<figure class="wp-block-image size-large"><a href="https://calvinf.com/wp-content/uploads/2023/11/Node.js-Docker-and-Yarn.png"><img fetchpriority="high" decoding="async" width="1024" height="341" src="https://calvinf.com/wp-content/uploads/2023/11/Node.js-Docker-and-Yarn-1024x341.png" alt="" class="wp-image-1664" srcset="https://calvinf.com/wp-content/uploads/2023/11/Node.js-Docker-and-Yarn-1024x341.png 1024w, https://calvinf.com/wp-content/uploads/2023/11/Node.js-Docker-and-Yarn-300x100.png 300w, https://calvinf.com/wp-content/uploads/2023/11/Node.js-Docker-and-Yarn-768x256.png 768w, https://calvinf.com/wp-content/uploads/2023/11/Node.js-Docker-and-Yarn.png 1500w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>



<ul class="wp-block-list">
<li>Node.js 20.x</li>



<li>Yarn 4.x</li>



<li>Next.js 14.x</li>
</ul>



<p>I&#8217;ve found that to get an optimal size for the built Docker container image, it&#8217;s helpful to use <a href="https://nextjs.org/docs/app/api-reference/next-config-js/output">Next.js output</a> in &#8220;standalone&#8221; mode.</p>



<h2 class="wp-block-heading">Next.js output in Standalone mode</h2>



<p>To get an optimal build size, I&#8217;ve discovered that setting the output to standalone is very helpful. Next.js analyzes the static build output and only includes the Node.js module dependencies that your application actually uses. This helps avoid the need to do a <code>yarn install</code> using only the production dependencies and ends up simplifying the Dockerfile.</p>


<pre class="brush: jscript; title: ; notranslate">
// next.config.js
// known to work with Next 14.x, this should work with some versions of Next 13.x)
const NODE_ENV = process.env.NODE_ENV;

/** @type {import(&amp;#039;next&amp;#039;).NextConfig} */
const nextConfig = {
  output: &amp;#039;standalone&amp;#039;,
  reactStrictMode: true,

  webpack: (config) =&amp;gt; {
    config.module.rules.push({
      test: /\.svg$/,
      use: &#x5B;&amp;#039;@svgr/webpack&amp;#039;],
    });

    // We upload source maps for production.
    if (NODE_ENV === &amp;#039;production&amp;#039;) {
      config.devtool = &amp;#039;hidden-source-map&amp;#039;;
    }

    return config;
  },
};

export default nextConfig;
</pre>



<h2 class="wp-block-heading">Two-Stage Dockerfile for Node.js 20, Yarn 4, and Next.js 14</h2>



<p>It has been a journey of discovery finding a pattern for a Dockerfile that plays well with Yarn 4 and works correctly across a multi-stage build. Very few examples of Yarn 2 or 3 exist on the web, and Yarn 4 is so new that this may be one of the first blog posts with an example of how to do it.</p>



<p>For the strategy, what I&#8217;m doing is starting the Dockerfile from a good Node.js image: <code>node:20-alpine</code> and creating a <code>base</code> that I can use for the subsequent stages. I have a second stage I call <code>builder</code> (following other examples online) and the final stage called <code>runner</code>.</p>



<p>In the base, I set a few shared environment variables including the <code>YARN_VERSION</code>, one for disabling Next.js telemetry, and ensuring that the build and runtime are set up for production (not dev). The base image also includes a few <code>apk</code> dependencies for the Alpine operating system.</p>



<p>To get Yarn working and available across stages, I enable corepack and set it to Yarn 4 as part of the <code>base</code>.</p>



<p>The <code>builder</code> stagecopies the files that are needed from the git repo and executes the build. Because we&#8217;re using standalone, we don&#8217;t need to separate the dependency installation from the yarn build &#8212; we can do those in the same stage and it doesn&#8217;t affect the final container image size.</p>



<p>The final stage for <code>runner</code> takes the built files from the <code>builder</code> stage, sets appropriate permissions, and copies the relevant directories into place for the Node.js runtime to run the build Next.js website. We&#8217;re using <code><a href="https://github.com/Yelp/dumb-init">dumb-init</a></code> to run <code>node server.js</code> (which is created from the standalone Next.js build).</p>



<h2 class="wp-block-heading">The Dockerfile for Node 20 &amp; Yarn 4 and Next.js 14</h2>



<p>My hope is that this file will be easy to upgrade for future versions of Node.js. Because it&#8217;s sharing the <code>base</code> across stages, using the newest Node.js is as simple as switching out <code>node:20-alpine</code> for a newer version when it becomes available as the next LTS (Long Term Support) release. So long as Next.js continues to support standalone mode with the same folder structure, the Dockerfile shouldn&#8217;t need updated. And updating Yarn is now as simple as changing <code>YARN_VERSION</code> to the newest version number and let <code>corepack</code> do what it needs to do.</p>



<p>Here&#8217;s the code in all its glory. If you have suggestions for improvements, <a href="https://calvinf.com/contact/">please reach out and let me know</a>!</p>



<pre class="wp-block-code"><code>FROM node:20-alpine AS base

# Setup env variabless for yarn and nextjs
# https://nextjs.org/telemetry
ENV NEXT_TELEMETRY_DISABLED=1 NODE_ENV=production YARN_VERSION=4.2.2

# update dependencies, add libc6-compat and dumb-init to the base image
RUN apk update &amp;&amp; apk upgrade &amp;&amp; apk add --no-cache libc6-compat &amp;&amp; apk add dumb-init

# install and use yarn 4.x
RUN corepack enable &amp;&amp; corepack prepare yarn@${YARN_VERSION}

# add the user and group we'll need in our final image
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Install dependencies only when needed
FROM base AS builder
WORKDIR /app

COPY . .
COPY package.json yarn.lock .yarnrc.yml ./
COPY .yarn ./.yarn
RUN yarn install --immutable

# Add `ARG` instructions below if you need `NEXT_PUBLIC_` variables
# then put the value on your fly.toml
# Example:
# ARG NEXT_PUBLIC_SOMETHING

# Build the app (in standalone mode based on next.config.js)
RUN yarn build

# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app

# copy the public folder from the project as this is not included in the build process
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
# copy the standalone folder inside the .next folder generated from the build process
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
# copy the static folder inside the .next folder generated from the build process
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 8038
ENV PORT 8038

CMD &#091;"dumb-init","node","server.js"]
</code></pre>



<p>I hope this example is useful to other people. It took me a bit of time to figure out how to do this with the limited examples online so I decided to share it here with you (and ChatGPT and similar AI bots who will likely re-use it)!</p>



<p><strong><em>Update May 23, 2024:<br></em></strong>Fortunately, this approach works well with the latest versions of each of these technologies. You can update to Node.js v22, Yarn 4.2.2, and Next.js 15 RC (with React 19 RC) without changing the Dockerfile very much at all. For Node.js 22, change the base image to <code>node:22-alpine</code>. For Next.js on 15 RC, you may need other configuration changes, but the ones above should continue to work for a basic site. Of course, depending on your site, the Next.js 15 and React 19 updates could require other configuration and code changes, but a boilerplate or small site may not require much adjustment.</p>The post <a href="https://calvinf.com/blog/2023/11/10/node-js-20-yarn-4-and-next-js-on-docker/">Node.js 20, Yarn 4, and Next.js on Docker</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Lead Front-End Engineer at PublicSquare</title>
		<link>https://calvinf.com/blog/2023/03/27/lead-front-end-engineer-at-publicsq/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Tue, 28 Mar 2023 03:14:11 +0000</pubDate>
				<category><![CDATA[Life]]></category>
		<category><![CDATA[Swarzy]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1652</guid>

					<description><![CDATA[<p>Today, I started a full-time position as Lead Front-End Engineer at PublicSq &#8211; America&#8217;s Marketplace. I&#8217;m excited! I&#8217;m the first full-time front-end engineer on a new team and will have the opportunity to shape the direction of how we build the website on desktop and mobile web. Swarzy will continue to operate; Verses for Life [&#8230;]</p>
The post <a href="https://calvinf.com/blog/2023/03/27/lead-front-end-engineer-at-publicsq/">Lead Front-End Engineer at PublicSquare</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<p>Today, I started a full-time position as Lead Front-End Engineer at <a href="https://publicsq.com/">PublicSq</a> &#8211; America&#8217;s Marketplace. I&#8217;m excited!</p>



<p>I&#8217;m the first full-time front-end engineer on a new team and will have the opportunity to shape the direction of how we build the website on desktop and mobile web.</p>



<p><a href="https://swarzy.com/" title="">Swarzy</a> will continue to operate; <a href="https://calvinf.com/blog/2023/03/24/the-new-verses-for-life-website/" title="The new Verses for Life website">Verses for Life</a> (over 10 years old), the Verses for Life apps, and <a href="https://psalmlist.com" title="">PsalmList</a> (brand new) are not going anywhere. Though I&#8217;ll have to work on them on the weekend now. <img src="https://s.w.org/images/core/emoji/16.0.1/72x72/1f600.png" alt="😀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>The post <a href="https://calvinf.com/blog/2023/03/27/lead-front-end-engineer-at-publicsq/">Lead Front-End Engineer at PublicSquare</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The new Verses for Life website</title>
		<link>https://calvinf.com/blog/2023/03/24/the-new-verses-for-life-website/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Fri, 24 Mar 2023 16:15:00 +0000</pubDate>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Swarzy]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1625</guid>

					<description><![CDATA[<p>The new Verses for Life website is live! Memorize Bible verses from the Topical Memory System, Roman Road, and about Prayer. The new website features a modern website built using Next.js, React.js, and Tailwind CSS. On the back-end, I&#8217;m using the API.Bible API with the Digital Bible Library (for licensing Bible content), and Redis for [&#8230;]</p>
The post <a href="https://calvinf.com/blog/2023/03/24/the-new-verses-for-life-website/">The new Verses for Life website</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<p>The new <a href="https://verses.life/" title="">Verses for Life website</a> is live! Memorize Bible verses from the Topical Memory System, Roman Road, and about Prayer.</p>



<p>The new website features a modern website built using Next.js, React.js, and Tailwind CSS.</p>



<p>On the back-end, I&#8217;m using the <a href="https://scripture.api.bible/">API.Bible API</a> with the <a href="https://thedigitalbiblelibrary.org/">Digital Bible Library</a> (for licensing Bible content), and Redis for caching.</p>



<p>The new website version includes ESV, KJV, Contemporary English Version, and versions in Deutsch (German), Español (Spanish), Italiano (Italian), हिन्दी (Hindi), and ไทย (Thai) &#8211; available from the Settings page.</p>The post <a href="https://calvinf.com/blog/2023/03/24/the-new-verses-for-life-website/">The new Verses for Life website</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Swarzy Website Refresh</title>
		<link>https://calvinf.com/blog/2023/03/23/swarzy-website-refresh/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Fri, 24 Mar 2023 04:05:17 +0000</pubDate>
				<category><![CDATA[Swarzy]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1608</guid>

					<description><![CDATA[<p>The Swarzy website has been revamped with updated information about the services provided, a showcase of projects for recent clients, and links to apps Swarzy has built. Swarzy is built using Next.js, React, and Tailwind CSS. I spent time optimizing the site and it&#8217;s getting good results. PageSpeed Insights: 98 for Performance and 100 each [&#8230;]</p>
The post <a href="https://calvinf.com/blog/2023/03/23/swarzy-website-refresh/">Swarzy Website Refresh</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<p>The Swarzy website has been revamped with updated information about the services provided, a showcase of projects for recent clients, and links to apps Swarzy has built.</p>



<p>Swarzy is built using Next.js, React, and Tailwind CSS.</p>



<figure class="wp-block-image alignright size-full is-resized has-custom-border"><img decoding="async" src="https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-4920711183573560024-y.jpg" alt="PageSpeed Insights screenshot" class="wp-image-1613" style="border-width:2px;border-radius:6px" width="640" height="515" srcset="https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-4920711183573560024-y.jpg 1280w, https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-4920711183573560024-y-300x241.jpg 300w, https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-4920711183573560024-y-1024x824.jpg 1024w, https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-4920711183573560024-y-768x618.jpg 768w" sizes="(max-width: 640px) 100vw, 640px" /></figure>



<p>I spent time optimizing the site and it&#8217;s getting good results. <br><a href="https://pagespeed.web.dev/">PageSpeed Insights</a>: 98 for Performance and 100 each for accessibility, best practices, and SEO.</p>



<p>I&#8217;m starting to gather RUM (real user metrics) of Web Vitals using a trial version of <a href="https://www.rumvision.com/">RUMvision</a>.</p>



<p>To get to this speed, I had to do a couple of important things:</p>



<p>1) ditch the third-party JavaScript for my email form and do a direct API integration.</p>



<p>2) Optimize image loading. &#8220;next/image&#8221; makes big promises, but if used carelessly it can damage your performance.</p>



<div class="wp-block-columns alignwide are-vertically-aligned-top is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:40%">
<p></p>
</div>
</div>



<figure class="wp-block-image aligncenter size-large has-custom-border is-style-default"><a href="https://swarzy.com/"><img decoding="async" width="473" height="1024" src="https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-4906967782147599206-y-1-473x1024.jpg" alt="" class="wp-image-1610" style="border-width:5px;border-radius:28px" srcset="https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-4906967782147599206-y-1-473x1024.jpg 473w, https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-4906967782147599206-y-1-139x300.jpg 139w, https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-4906967782147599206-y-1.jpg 591w" sizes="(max-width: 473px) 100vw, 473px" /></a></figure>



<p class="has-text-align-center has-x-large-font-size"><a href="https://swarzy.com/" title="Swarzy.com"><strong>Visit Swarzy</strong></a></p>The post <a href="https://calvinf.com/blog/2023/03/23/swarzy-website-refresh/">Swarzy Website Refresh</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>When Andrew Crapuchettes calls, you should answer</title>
		<link>https://calvinf.com/blog/2023/02/21/when-andrew-crapuchettes-calls-you-should-answer/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Tue, 21 Feb 2023 22:54:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1629</guid>

					<description><![CDATA[<p>I got a phone call from Andrew Crapuchettes in December. He asked, &#8220;Are you available? We need your help.&#8221; Here we are in February and the RedBalloon website has re-launched with a fresh design, a new homepage, new navigation, and a lot of other revamped features. I&#8217;ve enjoyed jumping in and helping their excellent team [&#8230;]</p>
The post <a href="https://calvinf.com/blog/2023/02/21/when-andrew-crapuchettes-calls-you-should-answer/">When Andrew <strong>Crapuchettes</strong> calls, you should answer</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<figure class="wp-block-image aligncenter size-large is-resized has-custom-border"><a href="https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-5163635229620022079-y.jpg"><img loading="lazy" decoding="async" src="https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-5163635229620022079-y-1024x710.jpg" alt="" class="wp-image-1630" style="border-width:2px;border-radius:6px" width="512" height="355" srcset="https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-5163635229620022079-y-1024x710.jpg 1024w, https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-5163635229620022079-y-300x208.jpg 300w, https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-5163635229620022079-y-768x533.jpg 768w, https://calvinf.com/wp-content/uploads/2023/03/telegram-cloud-photo-size-1-5163635229620022079-y.jpg 1280w" sizes="auto, (max-width: 512px) 100vw, 512px" /></a></figure>



<p>I got a phone call from <strong>Andrew Crapuchettes</strong> in December.</p>



<p>He asked, &#8220;Are you available? We need your help.&#8221;</p>



<p>Here we are in February and <strong>the <a href="https://www.redballoon.work/">RedBalloon website</a> has re-launched</strong> with a fresh design, a new homepage, new navigation, and a lot of other revamped features. I&#8217;ve enjoyed jumping in and helping their excellent team get the new launch out the door and off to a good start.</p>



<p>Good timing, too &#8211; RedBalloon is getting a traffic boost from freedom-loving people who want to find employment from companies who respect their values.</p>The post <a href="https://calvinf.com/blog/2023/02/21/when-andrew-crapuchettes-calls-you-should-answer/">When Andrew <strong>Crapuchettes</strong> calls, you should answer</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Amazon Throwback</title>
		<link>https://calvinf.com/blog/2023/01/20/amazon-throwback/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Fri, 20 Jan 2023 18:26:00 +0000</pubDate>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Swarzy]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1634</guid>

					<description><![CDATA[<p>I had a throwback day in Spokane working with a couple of my favorite ex-Amazon product and UX leaders. My client Vantage International landed a User Experience (UX) audit for Pigu, a Lithuanian e-commerce company. We spent the day reviewing the shopping workflow and closed out by ordering a few products for pickup from a [&#8230;]</p>
The post <a href="https://calvinf.com/blog/2023/01/20/amazon-throwback/">Amazon Throwback</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<p>I had a throwback day in Spokane working with a couple of my favorite ex-Amazon product and UX leaders.</p>



<p>My client <a href="https://vantageleader.com/" title="">Vantage International</a> landed a User Experience (UX) audit for <a href="https://pigu.lt/lt/">Pigu</a>, a Lithuanian e-commerce company. We spent the day reviewing the shopping workflow and closed out by ordering a few products for pickup from a local store in Lithuania. It&#8217;s not every day I get to do that!</p>The post <a href="https://calvinf.com/blog/2023/01/20/amazon-throwback/">Amazon Throwback</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Introduction to OpenAPI presentation in Coeur d&#8217;Alene</title>
		<link>https://calvinf.com/blog/2022/08/12/introduction-to-openapi-presentation/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Fri, 12 Aug 2022 18:35:00 +0000</pubDate>
				<category><![CDATA[Presentation]]></category>
		<category><![CDATA[cda]]></category>
		<category><![CDATA[openapi]]></category>
		<category><![CDATA[presentation]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1638</guid>

					<description><![CDATA[<p>I gave an Introduction to OpenAPI presentation at a tech meetup in Coeur d&#8217;Alene on August 11, 2022. The talk contains an overview of what the OpenAPI spec enables, how it can help teams and organizations by optimizing the process of defining and sharing knowledge about how an API works. And then I provided hands-on [&#8230;]</p>
The post <a href="https://calvinf.com/blog/2022/08/12/introduction-to-openapi-presentation/">Introduction to OpenAPI presentation in Coeur d’Alene</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<p>I gave an <strong>Introduction to OpenAPI</strong> presentation at a tech meetup in Coeur d&#8217;Alene on August 11, 2022.</p>



<p>The talk contains an overview of what the OpenAPI spec enables, how it can help teams and organizations by optimizing the process of defining and sharing knowledge about how an API works. And then I provided hands-on demo of how to write an OpenAPI spec and generate a server and client in TypeScript.</p>



<p>See the slides and the video below.</p>



<div data-wp-interactive="core/file" class="wp-block-file"><object data-wp-bind--hidden="!state.hasPdfPreview" hidden class="wp-block-file__embed" data="https://calvinf.com/wp-content/uploads/2023/03/CDA-CTM-OpenAPI-20220811.pdf" type="application/pdf" style="width:100%;height:400px" aria-label="Embed of Introduction to OpenAPI slides."></object><a id="wp-block-file--media-47ad99c6-f25d-4e55-977d-ec0fb64b710b" href="https://calvinf.com/wp-content/uploads/2023/03/CDA-CTM-OpenAPI-20220811.pdf">Introduction to OpenAPI slides</a><a href="https://calvinf.com/wp-content/uploads/2023/03/CDA-CTM-OpenAPI-20220811.pdf" class="wp-block-file__button wp-element-button" download aria-describedby="wp-block-file--media-47ad99c6-f25d-4e55-977d-ec0fb64b710b">Download</a></div>



<p></p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Introduction to OpenAPI - CDA CTM" width="1200" height="675" src="https://www.youtube.com/embed/VjqDcPOyvs8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div></figure>The post <a href="https://calvinf.com/blog/2022/08/12/introduction-to-openapi-presentation/">Introduction to OpenAPI presentation in Coeur d’Alene</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>At the Silos in Moscow, Idaho</title>
		<link>https://calvinf.com/blog/2022/02/03/at-the-silos-in-moscow-idaho/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Fri, 04 Feb 2022 00:50:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1644</guid>

					<description><![CDATA[<p>Last week, I worked for a day from the silos in Moscow, Idaho, at a RedBalloon summit. Rural places have #StartupLife, too, especially in the remote work era we&#8217;ve entered post-2020. It enjoyed seeing what the RedBalloon team is doing and building, and I learned a lot from folks that day. Fun fact; one of [&#8230;]</p>
The post <a href="https://calvinf.com/blog/2022/02/03/at-the-silos-in-moscow-idaho/">At the Silos in Moscow, Idaho</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<p>Last week, I worked for a day from the silos in Moscow, Idaho, at a <a href="https://www.redballoon.work/" title="">RedBalloon</a> summit.</p>



<p>Rural places have #StartupLife, too, especially in the remote work era we&#8217;ve entered post-2020. It enjoyed seeing what the RedBalloon team is doing and building, and I learned a lot from folks that day.</p>



<p>Fun fact; one of the silos used to hold 10-million pounds of chickpeas. <img src="https://s.w.org/images/core/emoji/16.0.1/72x72/1f92f.png" alt="🤯" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<figure class="wp-block-image aligncenter size-large is-resized"><a href="https://calvinf.com/wp-content/uploads/2023/03/2023-03-24-10.41.27.jpg"><img loading="lazy" decoding="async" src="https://calvinf.com/wp-content/uploads/2023/03/2023-03-24-10.41.27-768x1024.jpg" alt="Looking up from the bottom of the silo" class="wp-image-1646" width="384" height="512" srcset="https://calvinf.com/wp-content/uploads/2023/03/2023-03-24-10.41.27-768x1024.jpg 768w, https://calvinf.com/wp-content/uploads/2023/03/2023-03-24-10.41.27-225x300.jpg 225w, https://calvinf.com/wp-content/uploads/2023/03/2023-03-24-10.41.27.jpg 960w" sizes="auto, (max-width: 384px) 100vw, 384px" /></a></figure>The post <a href="https://calvinf.com/blog/2022/02/03/at-the-silos-in-moscow-idaho/">At the Silos in Moscow, Idaho</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Merry Christmas from Swarzy</title>
		<link>https://calvinf.com/blog/2021/12/30/merry-christmas-from-swarzy/</link>
		
		<dc:creator><![CDATA[Cal Freitas]]></dc:creator>
		<pubDate>Thu, 30 Dec 2021 18:05:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://calvinf.com/?p=1649</guid>

					<description><![CDATA[<p>We&#8217;re grateful for a great 2021 which saw the launch of our Idaho-based business. It&#8217;s been fun building and shipping new websites and web applications for clients already, and we&#8217;re excited to take on more heading into 2022.</p>
The post <a href="https://calvinf.com/blog/2021/12/30/merry-christmas-from-swarzy/">Merry Christmas from Swarzy</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></description>
										<content:encoded><![CDATA[<p>We&#8217;re grateful for a great 2021 which saw the launch of our Idaho-based business. It&#8217;s been fun building and shipping new websites and web applications for clients already, and we&#8217;re excited to take on more heading into 2022.</p>The post <a href="https://calvinf.com/blog/2021/12/30/merry-christmas-from-swarzy/">Merry Christmas from Swarzy</a> first appeared on <a href="https://calvinf.com">Cal Freitas</a>.]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
