<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Sam Beckham</title><description>The personal website, blog, portfolio, and playground of Sam Beckham. Frontend engineering manager at GitLab</description><link>https://sam.beckham.io/</link><item><title>The Quiet Tax</title><link>https://sam.beckham.io/wrote/the-quiet-tax/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/the-quiet-tax/</guid><description>You see a problem, stay quiet, and pay for it later. How to say the hard thing, calmly and quickly, to build trust and avoid the quiet tax.</description><pubDate>Tue, 03 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There&apos;s a moment I keep paying for.&lt;/p&gt;
&lt;p&gt;It&apos;s the end of a hard week, we&apos;re approaching a deadline and we&apos;re getting ready to ship. I can already see the bug. It&apos;s not a bug-bug, it&apos;s the kind that eats trust. A small truth that seemingly only I can see. This plan won&apos;t work. The alignment is off. The scope towers over what little capacity (and appetite) engineering have left. We&apos;re about to close the week on smiles and promises that will both break after the weekend.&lt;/p&gt;
&lt;p&gt;I feel it itching in my gut. The tiny friction of a sentence I don&apos;t want to say and no one wants to hear. The sentence forms in my mind, &amp;quot;This isn&apos;t going to work.&amp;quot;. It moves to my mouth, but I roll it up and swallow it back down. Maybe I&apos;m wrong, maybe it will all be fine. Maybe it&apos;s better left unsaid. I leave the meeting having said nothing. I&apos;ll pay the quiet tax.&lt;/p&gt;
&lt;p&gt;The quiet tax doesn&apos;t feel like much in the moment; but it compounds. It&apos;s the act of not speaking up, of not pushing back, of letting things slide. Those small moments left unsaid, which turn into larger moments, then turn into catastrophes. All because we didn&apos;t speak up and say the hard thing in the moment that mattered.&lt;/p&gt;
&lt;p&gt;The hard thing is rarely clever, eloquent, or groundbreaking. It&apos;s dull, brief and obvious. It sounds like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;We don&apos;t have the capacity.&amp;quot;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;We&apos;re solving different problems.&amp;quot;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&amp;quot;This doesn&apos;t align with our goals.&amp;quot;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&apos;s not a speech, it&apos;s a door. You open it and a draft of honesty fills the room. It&apos;s not about being right. What follows is either agreement or disagreement, but either way, it&apos;s discussion.&lt;/p&gt;
&lt;h2&gt;How to say the hard thing&lt;/h2&gt;
&lt;p&gt;There are some rules to follow when saying hard things. Saying them out loud is better, but saying them so they can be heard is best.&lt;/p&gt;
&lt;h3&gt;1. Use your inside voice&lt;/h3&gt;
&lt;p&gt;Stay calm, collected. You&apos;re pointing out a truth that others may not have noticed. You&apos;re not campaigning against injustice. Theatrics are often met with more theatrics and conversation breaks down. Keep it civil.&lt;/p&gt;
&lt;h3&gt;2. Get to the point&lt;/h3&gt;
&lt;p&gt;Say what you need to say, then shut up. Don&apos;t over explain, don&apos;t fluff it up, and avoid the temptation to slap it in a compliment sandwich. I prefer my bad news gluten-free.&lt;/p&gt;
&lt;h3&gt;3. Own your part&lt;/h3&gt;
&lt;p&gt;Say, &amp;quot;We&amp;quot; not, &amp;quot;You&amp;quot;. &amp;quot;We are not aligned&amp;quot; lands much better than, &amp;quot;You are wrong&amp;quot;. It reframes it as us against the problem, not us against each other. We&apos;re looking for healthy discourse, not blame.&lt;/p&gt;
&lt;h3&gt;4. Close the loop&lt;/h3&gt;
&lt;p&gt;You&apos;ve said the hard thing, you shut up and listened, now close the loop. Don&apos;t leave the meeting until you are aligned. At worst, schedule a time where you&apos;ll get that alignment. If you leave it unresolved, you&apos;ll still have to pay the quiet tax.&lt;/p&gt;
&lt;h3&gt;5. Don&apos;t overthink it&lt;/h3&gt;
&lt;p&gt;Saying the hard thing the right way is preferred. Not saying the hard thing because you&apos;re trying too hard to think of the best way to say it, leaves it unsaid. &lt;a href=&quot;https://open.spotify.com/track/7d66u8J2iM8WXcUKdujNZJ?si=51e3b7aca3db47f2&quot;&gt;Ronan Keating&lt;/a&gt; is wrong; you say it best when you say anything at all.&lt;/p&gt;
&lt;h2&gt;Psychological safety&lt;/h2&gt;
&lt;p&gt;There&apos;s a counter argument, and it sounds reasonable, Psychological safety. As if safety and honesty sit at opposing ends of a seesaw and saying the hard thing threatens this safety. This is backwards. Safety is not the absence of discourse, it&apos;s the presence of trust. Minor discomfort delivered honestly will be forgiven long before the pain of a hard truth left unsaid.&lt;/p&gt;
&lt;p&gt;The hard thing is not hard because it&apos;s mean. It&apos;s hard because you have to be the first one to say it. To spend a little bit of your credibility so the team can buy clarity. That&apos;s leadership. Pay the quiet tax less. Say the hard thing sooner. Leave the room lighter, and clearer, than you found it. What&apos;s the hard thing you need to say today? How can you avoid paying the quiet tax?&lt;/p&gt;
</content:encoded></item><item><title>To Me, By Me</title><link>https://sam.beckham.io/wrote/to-me-by-me/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/to-me-by-me/</guid><description>Over dinner my wife asked, “So what are you going to do about it?” That question flipped me from “to me” to “by me” and the path forward appeared.</description><pubDate>Tue, 27 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Over dinner, my wife asked a simple question: “So what are you going to do about it?”&lt;/p&gt;
&lt;p&gt;I was reminded of the to me/by me concept from, “&lt;a href=&quot;https://www.penguin.co.uk/books/476151/the-15-commitments-of-conscious-leadership-by-klemp-diana-chapman-jim-dethmer-and-kaley/9781529976076&quot;&gt;the 15 commitments of conscious leadership&lt;/a&gt;”.&lt;/p&gt;
&lt;p&gt;A to me response would be, “I can’t solve this problem because Steve isn’t doing their job properly”.
The thing blocking what you want is in someone else’s control.
You are a helpless victim of circumstance.
The by me response would be, “I should help unblock Steve so that they no-longer block me&amp;quot;.
It’s the same scenario, but reframed so that the control is in our hands.
Blaming Steve feels good in the moment, but gets us no closer to achieving our goals.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note:&lt;/strong&gt; There are two further frames in the model, Through me and As me, but I’m focusing on the first two as they’re the most accessible and actionable.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let’s look at another example.
Your team is slammed with work, burnout is creeping in and mistakes are being made.
A to me leader might say, “The team are making mistakes, my manager hasn’t given me the headcount I need, and product have given us completely unrealistic deadlines!”.
A natural response, but staying there keeps you stuck.
It’s all someone else’s fault.
It’s all happening &lt;em&gt;to&lt;/em&gt; me.&lt;/p&gt;
&lt;p&gt;To take control of the situation, we need to reframe these gripes as a by me action.
“I’ve accepted too much scope on too short of a deadline with not enough people and now my team are burning out and making mistakes.
This is exactly the same scenario, the difference is, we can do something about it.
We can more clearly see our levers.
We can push back on scope, we can extend the deadline, we can request more headcount.&lt;/p&gt;
&lt;p&gt;Of course, we could have done all those things regardless of how we framed our response.
Nothing about our situation has changed, but our mindset has.
We can more easily see our path towards fixing it.
We’re not waiting for someone else to bail us out or change, we’re affecting that change ourselves.&lt;/p&gt;
&lt;p&gt;I haven’t been writing as much as I’d like because I’m a new parent and that takes up a lot of my time.
For the past year, I was seeing this from a to me point of view.
By changing this to a by me point of view (which I &lt;a href=&quot;../finding-time&quot;&gt;wrote about&lt;/a&gt; last month) I have been able to find the time to write again without sacrificing any of the time I spend with my family.&lt;/p&gt;
&lt;p&gt;The next time you catch yourself complaining about something that’s happening to you, try to reframe it to a by-you statement and the path towards solving that problem may become clearer.&lt;/p&gt;
</content:encoded></item><item><title>Say the hard things</title><link>https://sam.beckham.io/wrote/say-the-hard-things/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/say-the-hard-things/</guid><description>A personal story about how candid feedback changed my career path and why delivering difficult feedback matters.</description><pubDate>Sat, 27 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The most career-defining moment of my life happened before my career even started.&lt;/p&gt;
&lt;p&gt;In my first year at college, I studied chemistry, physics, maths, and graphic design.
I wanted to be a scientist and design was an “easy” fourth subject.
One day my chemistry teacher sat me down and asked, “Sam, why are you in this class?” I explained that I wanted a good job, and hoped to become a forensic scientist.
Her response has stuck with me ever since. “But you don’t enjoy it and you’re not very good at it.”&lt;/p&gt;
&lt;p&gt;At the time, I thought this was harsh, uncalled for, and downright rude. I was stunned, but she was right.&lt;/p&gt;
&lt;p&gt;I didn’t enjoy it and, whilst I might get a passing grade, I wasn’t good enough to make a meaningful career from it.
We continued talking and realised my passion was in graphic design.
So I doubled down on that instead. I stopped pursuing chemistry and dove further into design, which took me into the digital art space, then a degree in interactive media design, and ultimately the tech industry where I still thrive today.&lt;/p&gt;
&lt;p&gt;If not for the candor of my tutor that day, I’d likely be stuck in a role that didn’t quite fit. Never fully enjoying my job and never being all that good at it.&lt;/p&gt;
&lt;p&gt;The moral here isn’t about following your dreams, it’s to be candid with your feedback and to pay attention when people are being candid with you.
Great feedback can change your life.
I keep this memory with me when I need to deliver tough feedback to my team members. It can be hard to hear this kind of feedback and even harder to deliver it but the most crucial feedback is often the most difficult to deliver.&lt;/p&gt;
&lt;p&gt;So thank you, Fiona, for telling me what I needed to hear, changing my career, and teaching me the power of candor.&lt;/p&gt;
</content:encoded></item><item><title>Finding Time</title><link>https://sam.beckham.io/wrote/finding-time/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/finding-time/</guid><description>Finding time isn&apos;t about creating it. It&apos;s about choosing where to spend the time you already have.</description><pubDate>Fri, 19 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I don&apos;t have the time to do the things I want to do anymore.&lt;/p&gt;
&lt;p&gt;At least, that&apos;s what I keep telling myself.
I don&apos;t have time to go for a run.
I don&apos;t have time to play my guitar.
I don&apos;t have time to write.
I don&apos;t have time.&lt;/p&gt;
&lt;p&gt;Except, I do have time.
I have time to open LinkedIn for the 15th time to look at the notifications that I didn&apos;t need notifying about.
I have time to flick through YouTube shorts and scoff at the AI slop.
I have time to tap and scroll and tap and scroll and…
I have time.&lt;/p&gt;
&lt;p&gt;New year&apos;s resolutions are cliché, but here&apos;s mine for 2025.
Every time I habitually open my phone, instead of starting a brain-rot session, I&apos;m going to write.
Whatever comes to my mind.
Some of it I&apos;ll edit and publish.
Most of it I won&apos;t.
Maybe I will with this one though.
Maybe, I do have time.&lt;/p&gt;
</content:encoded></item><item><title>One to One Meetings</title><link>https://sam.beckham.io/wrote/one-to-one-meetings/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/one-to-one-meetings/</guid><description>Discover the power of one-on-one meetings for engineering managers. Learn valuable tips, including the importance of customized approaches, prioritizing your team&apos;s agenda, and avoiding status reports. Get a free one-on-one template to enhance your meetings and improve communication with your reports. Build stronger relationships, foster career growth, and optimize your management style.</description><pubDate>Fri, 09 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;One to ones are the single most important meetings a leader will have with their reports.
Here&apos;s some tips (and a free one to one template)&lt;/p&gt;
&lt;h2&gt;No One to One Fits All&lt;/h2&gt;
&lt;p&gt;One to ones are your main tool for building relationships with your reports.
Like all relationships no two are the same.
Every relationship has different needs at different times.
For that reason, there&apos;s no one-size-fits-all when it comes to one to ones.
Every manager, and every report, will have different needs from their one to one.
The secret to finding those needs is iteration.&lt;/p&gt;
&lt;h2&gt;It&apos;s not your meeting&lt;/h2&gt;
&lt;p&gt;This is &lt;strong&gt;&lt;em&gt;their&lt;/em&gt; meeting, not &lt;em&gt;yours&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Spend at least the first half of the meeting talking about whatever they want to talk about.
This could be an issue they&apos;re facing, a discussion about their career, or what they got up to at the weekend.
If you have something you need to talk with them about, that&apos;s fine.
You&apos;ll have time in the second half of the meeting.&lt;/p&gt;
&lt;p&gt;Remember, this is &lt;strong&gt;&lt;em&gt;their&lt;/em&gt; meeting, not &lt;em&gt;yours&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If they need to reschedule it for that week, let them.
If the scheduled time doesn&apos;t work for them anymore, move it.
Better yet, give them the ability to do it themselves and operate a tell-don&apos;t-ask policy.
&amp;quot;Tell me you&apos;re moving the meeting, don&apos;t ask me if you can.&amp;quot;&lt;/p&gt;
&lt;p&gt;Because, this is &lt;strong&gt;&lt;em&gt;their&lt;/em&gt; meeting, not &lt;em&gt;yours&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Don&apos;t let it devolve into a status report.
If they want to update you on where they&apos;re at and discuss potential blockers, that&apos;s fine.
When a one to one turns into a weekly status report, this is usually because it&apos;s what they think you want to hear, not because it&apos;s what they want to talk about.
Try to steer the conversations away from status updates if you can.&lt;/p&gt;
&lt;h2&gt;One to One template&lt;/h2&gt;
&lt;p&gt;Even though it is their meeting, and each meeting is different, starting with a good framework is key.
Here&apos;s the template I use:&lt;/p&gt;
&lt;p&gt;&amp;lt;a href=&amp;quot;https://docs.google.com/document/d/11ieq3d_um05a_Gb_vTQOw5KknAW8jqmEmG_zEU6tjzA/edit?usp=drive_link&amp;quot; target=&amp;quot;_blank&amp;quot; class=&amp;quot;button button--full&amp;quot;&amp;gt;📄 One to One Template&amp;lt;/a&amp;gt;&lt;/p&gt;
&lt;p&gt;You can download it in any format and update it to suit your needs.
If you copy the doc to your drive, you get my my &lt;a href=&quot;/wrote/automate-your-meeting-agendas/&quot;&gt;automated meeting agenda script&lt;/a&gt; included.&lt;/p&gt;
&lt;p&gt;We split the agenda into two sections; sticky info above the break, and weekly agendas below.
Let&apos;s break them down.&lt;/p&gt;
&lt;p&gt;Right at the top is the title.
It&apos;s nothing special, but the order of the names is deliberate.
Their name first, then yours.
This helps set the tone and further emphasize that (say it with me) this is &lt;strong&gt;&lt;em&gt;their&lt;/em&gt; meeting, not &lt;em&gt;yours&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Below that are some useful links.
In this template, there&apos;s a link to the meeting room and a brag document.
These will be different for every report.
They can include important issues, promotion documents, training, or whatever you&apos;ll reference often.
Remember to &lt;a href=&quot;/wrote/keep-the-important-things-within-reach&quot;&gt;keep the important things within reach&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The table below that are the focus areas.
They&apos;re set up to keep the three main areas of focus front-of-mind.
They can be performance goals, but I&apos;d recommend decoupling performance targets from these.
I use them as areas we both need to focus on to help them with their career growth.
Learning a new topic, preparing for a promotion, keeping an eye on work/life balance, etc.
By keeping them at the top of the document, you&apos;re less likely to forget them.
Check in with them regularly, and if there&apos;s ever a lull in communication, they&apos;re a great ice breaker.&lt;/p&gt;
&lt;p&gt;Next up is action items.
This is where I like to store any promises we made to each other during the meeting.
It&apos;s great for ephemeral tasks that like outside the usual issue/ticketing system.
At the start of the next meeting, take a quick look at these and make sure you&apos;re keeping your promises to each other.
Keep each other accountable for this.&lt;/p&gt;
&lt;p&gt;Below the line break is the bread-and-butter of one to ones, the agenda.
Make sure to have next week&apos;s agenda ready to go.
When a thought pops into your mind during the week, you can drop it into the agenda to discuss at the next meeting.
You can do this at the end of each meeting, or you can &lt;a href=&quot;/wrote/automate-your-meeting-agendas&quot;&gt;automate it&lt;/a&gt; if you&apos;re using Google docs.
New entries get added at the top so you have a record of all the past meetings for reference.
Be sure to take notes as you go.
This can be a tough habit to get into (and something I&apos;m working on myself) but your future self will thank you for it.&lt;/p&gt;
&lt;h2&gt;Informal by default, formal when it matters&lt;/h2&gt;
&lt;p&gt;Try to keep it informal by default.
By having a formal structure, you can have informal conversations and still get things done.
Sometimes conversations need to get more serious, but if you make them informal by default you&apos;ll both get a lot more out of them.
One to ones are your best tool for building relationships, so use them to do that.&lt;/p&gt;
&lt;p&gt;What do you like to include in your one to one documents?
Let me know on &lt;a href=&quot;https://twitter.com/intent/tweet?url=https%3A%2F%2Fsam.beckham.io%2Fwrote%2Fone-to-one-meetings&quot;&gt;Twitter&lt;/a&gt;!&lt;/p&gt;
</content:encoded></item><item><title>Experimenting with AI</title><link>https://sam.beckham.io/wrote/experimenting-with-ai/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/experimenting-with-ai/</guid><description>AI is everywhere now. Here&apos;s how I leveraged POCs and practical AI applications to increase my AI literacy as an Engineering Manager.</description><pubDate>Fri, 02 Jun 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The world has gone crazy for AI.
AI discussions are dominating keynotes, product releases, and Twitter threads.
But what does building with AI actually look like?
I wanted to learn, so I &lt;a href=&quot;/wrote/starting-small/&quot;&gt;started small&lt;/a&gt; and spent a day experimenting.&lt;/p&gt;
&lt;h2&gt;A simple AI experiment&lt;/h2&gt;
&lt;p&gt;I needed an experiment that was small enough to be shippable in a day, but large enough to challenge me.
I decided to update the recommendation feature on this blog.
The previous algorithm suggested the three latest articles.
It did the job, but wasn&apos;t too smart.
It was the perfect target for my AI experiments.
It was simple to understand, but would  a deeper understanding of AI to get it done.&lt;/p&gt;
&lt;h2&gt;Getting familiar with AI&lt;/h2&gt;
&lt;p&gt;I wanted to create a some POCs (proofs of concept) to help me learn.
The first step was to get the OpenAI API running in my project.
I kept it simple and asked it to, &amp;quot;tell me a joke&amp;quot;.
After following the getting started guide (and some configuration) I got it a response.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Q: What did the fish say when it hit the wall?&lt;/p&gt;
&lt;p&gt;A: Dam!&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;–&apos;text-davinci-003&apos;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By doing this, I learned that requests are made of tokens.
Each token is a snippet of text, usually the length of a word.
There&apos;s a limit on the number of tokens you can send and receive in each API call.
The longer the prompt, the less room for the response.
If you set this limit too low, or make the prompt too big, you get incomplete responses.&lt;/p&gt;
&lt;h2&gt;Proving the Concept&lt;/h2&gt;
&lt;p&gt;By updating the prompt from, &amp;quot;Tell me a joke&amp;quot;, I could turn it into something useful.
I passed a list of article titles and asked for the three most related ones.
After some finessing, I landed on the following prompt:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const prompt = `
  Given the title of an article is &amp;quot;${article_title}&amp;quot;.
  Which three articles from the following array of article titles are the most related?
  
  ${JSON.stringify(article_titles)}.

  Return your answer in the following JSON format:
  { &amp;quot;recommendations&amp;quot;: [&amp;quot;one&amp;quot;, &amp;quot;two&amp;quot;, &amp;quot;three&amp;quot;] }
`
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I learned that writing prompts like &lt;a href=&quot;https://cucumber.io/docs/bdd/&quot;&gt;BDD tests&lt;/a&gt; is quite effective.
The AI was more likely to understand the question if I laid it out clearly.&lt;/p&gt;
&lt;p&gt;To make the result parsable, it was crucial to provide a format.
Asking it to, &lt;em&gt;&amp;quot;return the answer in JSON&amp;quot;&lt;/em&gt; was not enough.
I needed to provide an example response to get a more reliable result.
More reliable, but not completely reliable.&lt;/p&gt;
&lt;p&gt;Here&apos;s what I got when asking for related articles for &amp;quot;&lt;a href=&quot;/wrote/increasing-your-focus-with-pomodoro/&quot;&gt;Increase You Focus With Pomodoro&lt;/a&gt;&amp;quot;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;recommendations&amp;quot;: [
    &amp;quot;increase your focus with pomodoro&amp;quot;
    &amp;quot;automate your meeting agendas&amp;quot;,
    &amp;quot;find what makes you productive&amp;quot;
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Though it was obvious in hindsight, the most related article was the article itself.
This was easy to fix by filtering it out of the list before passing it up.
The POC worked well, but there were a few problems I wanted to address:&lt;/p&gt;
&lt;h3&gt;1. It wasn&apos;t reliable&lt;/h3&gt;
&lt;p&gt;Since this was chat-based, the outcome wasn&apos;t reliable.
It worked 80% of the time, but often gave a poor response.
It had a habit of adding extra text around the JSON, making it harder to parse.
Switching from the &lt;code&gt;text-davinci-003&lt;/code&gt; model to the more chat-focused &lt;code&gt;gpt-3.5-turbo&lt;/code&gt; model helped, but didn&apos;t completely fix it.
I would need to write a more robust response parser if I were to move this from POC to production-ready code.&lt;/p&gt;
&lt;h3&gt;2. The recommendations weren&apos;t great&lt;/h3&gt;
&lt;p&gt;The recommendations were okay, but they were a bit naive.
Since I was only sending the titles of the articles, we weren&apos;t giving the AI much data to work with.
For example: &amp;quot;&lt;a href=&quot;/wrote/running-a-conference/&quot;&gt;Running a Conference&lt;/a&gt;&amp;quot; would recommend, &amp;quot;&lt;a href=&quot;/wrote/running-the-jamstack-on-gitlab/&quot;&gt;Running the JamStack on GitLab&lt;/a&gt;&amp;quot;, instead of the more obvious, &amp;quot;&lt;a href=&quot;/wrote/starting-a-meetup/&quot;&gt;Starting a Meetup&lt;/a&gt;&amp;quot;.
To get better results, I&apos;d need to give the AI more data.&lt;/p&gt;
&lt;h3&gt;3. There were too many API calls&lt;/h3&gt;
&lt;p&gt;The OpenAI API isn&apos;t free.
Up to this point I had only spent a few cents, but at scale this could get expensive.
Running this for every article—and passing more data per article—would increase costs.
I needed to reduce and cache these calls wherever possible.&lt;/p&gt;
&lt;h2&gt;Using OpenAI Embeddings&lt;/h2&gt;
&lt;p&gt;After a bit more research into the issues above, I discovered &lt;a href=&quot;https://platform.openai.com/docs/guides/embeddings&quot;&gt;embeddings&lt;/a&gt;.
Instead of writing a prompt for every article, I could send them all to the embedding endpoint.
This would return a multi-dimensional graph with all the articles plotted on it.
The closer the points are on the graph, the more related they are.&lt;/p&gt;
&lt;p&gt;To understand how embeddings work, we need to simplify what they&apos;re doing.&lt;/p&gt;
&lt;p&gt;Imagine all the articles plotted on a standard 2D chart.
On each axis is a different topic.
There&apos;s &amp;quot;leadership&amp;quot; on one and &amp;quot;engineering&amp;quot; on another.
We can plot all the articles on this chart based on how much the content within them relates to each topic.
When we look at this chart, we can see the ones that are closer together are more related to each other.
The ones that are further apart, will have less in common.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/experimenting-with-ai/2d-embedding-chart.png&quot; alt=&quot;A scatter chart showing the relationships between articles when plotted against Leadership and Engineering topics&quot;&gt;&lt;/p&gt;
&lt;p&gt;Comparing two topics doesn&apos;t give us much.
To get more accurate information, we can add a third axis.
This one measures the relation to &amp;quot;productivity&amp;quot;.
Since the axis needs to be orthogonal to the other two, we need to jump into the third dimension to visualize it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/experimenting-with-ai/3d-embedding-chart.gif&quot; alt=&quot;A 3D scatter chart showing the relationships between articles when plotted against Leadership, Engineering, and Productivity topics&quot;&gt;&lt;/p&gt;
&lt;p&gt;We can still get the distance between points, but now we&apos;re comparing across three dimensions.
OpenAI uses thousands of dimensions to create embeddings, but the concept is the same.
The closer two nodes are, the more related they are.&lt;/p&gt;
&lt;p&gt;This approach solves all our issues.
We get more accurate, reliable, recommendations with one API call.
Because of this, we can afford to send more data to make the recommendations better.
Since this is no-longer chat based, the response is a structured data format.
The embedding data may be different if we ran it again, but the data structure would be the same.&lt;/p&gt;
&lt;h2&gt;Sending the right data to the AI&lt;/h2&gt;
&lt;p&gt;We can send more data to the API, but which data do we send?
We could send the whole article, but we would soon hit the token limit.
Luckily, ChatGPT is great at summarizing and categorizing text.
We can use this to our advantage and ask it to generate tags for all our articles.
By sending tags instead of the full article, we send less data but still get the point of the article across.
Because I was only doing this once, I used the ChatGPT app.
This came with the added benefit of using the more powerful &lt;code&gt;GPT4&lt;/code&gt; engine that isn&apos;t available to us on the API.&lt;/p&gt;
&lt;p&gt;Here&apos;s the prompt I wrote:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Given the following markdown article, please suggest five tags formatted as yaml:

{ARTICLE_CONTENT}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice I&apos;m using the BDD test style again.
I didn&apos;t provide an example response, so the results weren&apos;t reliable.
Since this was using the ChatGPT app though, it didn&apos;t matter too much.
It had the context of the previous chat messages so I could refine the result.
When it returned the results in the wrong format, I would ask it to, &lt;em&gt;&amp;quot;reformat the response as yaml&amp;quot;&lt;/em&gt; and it fixed it up.
I could also refine the suggestions by saying, &lt;em&gt;&amp;quot;swap {TAG_NAME} for another suggestion&amp;quot;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Here were the suggestions for this article:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yml&quot;&gt;- AI experimentation
- recommendation feature
- OpenAI API
- embeddings
- article tagging
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It took a while to generate all the tags, but it was a one-time operation.
Once I had all the tags, I wrote a script that fetched all the articles and extracted their tags.
I then sent an array of these to the embedding endpoint and got all the data back to run comparisons against later.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;{
  input: [
    &amp;quot;Experimenting with AI: AI experimentation, recommendation feature, OpenAI API, embeddings, article tagging&amp;quot;,
    &amp;quot;Increase your focus with pomodoro: Productivity, Time Management, Focus Technique, Pomodoro Technique, Distraction Management&amp;quot;,
    &amp;quot;Running a Conference: conference, event organization, sponsorship, diversity fund, speaker payment&amp;quot;,
    //… 
  ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Cosine similarity formula&lt;/h2&gt;
&lt;p&gt;Our brains can&apos;t handle graphs in dimensions higher than the three we live in, but computers have no problem with it.
Using the &lt;a href=&quot;https://en.wikipedia.org/wiki/Cosine_similarity&quot;&gt;cosine similarity formula&lt;/a&gt;, we can get the distance between two points in any number of dimensions.
Letting the &lt;a href=&quot;https://www.npmjs.com/package/compute-cosine-similarity&quot;&gt;compute-cosine-similarity&lt;/a&gt; npm package do the heavy-lifting, made computing similarity a breeze.
To get the recommended articles, I loop through all the articles and calculate their similarity to the current article.
Then I sort the array by similarity, remove the first result, and return the next three.
This is all done against the dataset we generated previously, so it&apos;s really fast.&lt;/p&gt;
&lt;h2&gt;Takeaways&lt;/h2&gt;
&lt;p&gt;This approach solved all the issues with the first POC.
It&apos;s much more reliable since we&apos;re dealing with deterministic data.
There&apos;s only one API call that&apos;s made once every few weeks.
Most importantly, the recommendations are much better.
They&apos;re not perfect, but they&apos;re good enough.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;// For &amp;quot;Running a Conference&amp;quot;
{
  &amp;quot;recommendations&amp;quot;: [{
    &amp;quot;title&amp;quot;: &amp;quot;Starting a Meetup&amp;quot;,
    &amp;quot;path&amp;quot;: &amp;quot;/wrote/starting-a-meetup/&amp;quot;,
    &amp;quot;similarity&amp;quot;: 0.8543
  },{
    &amp;quot;title&amp;quot;: &amp;quot;All Meetings are Optional&amp;quot;,
    &amp;quot;path&amp;quot;: &amp;quot;/wrote/all-meetings-are-optional/&amp;quot;,
    &amp;quot;similarity&amp;quot;: 0.8363
  },{
    &amp;quot;title&amp;quot;: &amp;quot;Automate Your Meeting Agendas&amp;quot;,
    &amp;quot;path&amp;quot;: &amp;quot;/wrote/automate-your-meeting-agendas/&amp;quot;,
    &amp;quot;similarity&amp;quot;: 0.7954
  }]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Recommendations are a nice feature, but the point of this was to learn more about AI.
I&apos;m an engineering manager so I don&apos;t need to be a guru, but I still need to know what I&apos;m talking about.
By going through a practical application of AI, I&apos;m better prepared for conversations with my engineers as we dive in to &lt;a href=&quot;https://www.youtube.com/watch?v=ejWeMdVz8Nk&quot;&gt;AI at GitLab&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If I&apos;ve made any incorrect assumptions, or could have done this better, reach out on &lt;a href=&quot;https://mastodon.social/@samdbeckham&quot;&gt;Mastodon&lt;/a&gt;, or &lt;a href=&quot;https://twitter.com/samdbeckham&quot;&gt;Twitter&lt;/a&gt; and tell me about it.
I&apos;m always happy to learn.&lt;/p&gt;
</content:encoded></item><item><title>Chief of Staff: 28 Days Later</title><link>https://sam.beckham.io/wrote/chief-of-staff-28-days-later/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/chief-of-staff-28-days-later/</guid><description>I&apos;m a third of the way through my Acting Chief of Staff to the CTO rotation. Here&apos;s what I&apos;ve learned so far.</description><pubDate>Mon, 29 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;m a third of the way through my &lt;a href=&quot;/wrote/acting-chief-of-staff-to-the-chief-technology-officer&quot;&gt;Acting Chief of Staff to the CTO&lt;/a&gt; rotation.
Here&apos;s what I&apos;ve learned so far.&lt;/p&gt;
&lt;p&gt;My day-to-day includes all the tasks listed in &lt;a href=&quot;https://about.gitlab.com/job-families/engineering/acting-cos-to-the-cto/&quot;&gt;the job description&lt;/a&gt;.
But to describe this role as a set of tasks doesn&apos;t give it justice.
When asking folks what a Chief of Staff does, I got the typical, &amp;quot;it depends&amp;quot;.
This is a very self-driven role and you need to work out how to be effective.
It&apos;s been quite freeing, though I do miss my usual team.
Three months is a long time to be away, and not much time to on-board.&lt;/p&gt;
&lt;h2&gt;Giving CREDIT to our values&lt;/h2&gt;
&lt;p&gt;GitLab&apos;s core set of &lt;a href=&quot;https://about.gitlab.com/handbook/values/&quot;&gt;values&lt;/a&gt; drive everything we do.
They spell out, &amp;quot;CREDIT&amp;quot; and stand for; Collaboration, Results, Efficiency, Diversity, Iteration, and Transparency.
We live these values at every level.
They are not just words on a (virtual) wall.&lt;/p&gt;
&lt;p&gt;Whilst I look to these values in my regular role, they are much more important at this level of the company.
If leadership expect the rest of the company to live by these values, they need to champion them.&lt;/p&gt;
&lt;h3&gt;Collaboration&lt;/h3&gt;
&lt;p&gt;A key aspect of this role is helping others collaborate.
When one department or team member needs something, help them find where to go to get it.
All whilst remaining as async as possible.
This could be tracking training participants, raising awareness of an initiative, or anything in-between.&lt;/p&gt;
&lt;p&gt;One of the tools we have for this is the Engineering Week in Review.
It&apos;s an internal newsletter/document that anyone in the company can read or contribute to.
My role is to promote and curate it so the right people see the right messages at the right time.&lt;/p&gt;
&lt;h3&gt;Results&lt;/h3&gt;
&lt;p&gt;Results are right at the top of our &lt;a href=&quot;https://about.gitlab.com/handbook/values/#hierarchy&quot;&gt;values hierarchy&lt;/a&gt;.
With this being more of a supporting role, measuring results can be tricky.
The &amp;quot;acting&amp;quot; aspect of this role requires a bias for action.
You&apos;ve only got three months in this job so if you want something doing, you had better start soon and move quick.&lt;/p&gt;
&lt;p&gt;An example of this is the Engineering off-site.
It&apos;s towards the end of the quarter, but requires a lot of planning.
Rather than wait until the last month to start, I started in week two.
I started by blocking out the time on everyone&apos;s calendars and iterated from there.
By &lt;a href=&quot;/wrote/starting-small.html&quot;&gt;starting small&lt;/a&gt;, I got the ball rolling and made future collaboration much easier.&lt;/p&gt;
&lt;p&gt;Start early and worry about the details later.&lt;/p&gt;
&lt;h3&gt;Efficiency&lt;/h3&gt;
&lt;p&gt;This role only lasts three months, so you need to be as efficient as possible.
&lt;a href=&quot;/wrote/automation&quot;&gt;Automation&lt;/a&gt; has helped.
I&apos;ve &lt;a href=&quot;/wrote/automate-your-meeting-agendas&quot;&gt;automated agendas&lt;/a&gt;, created issue templates, and helped set up tracking for some OKRs.
If a computer can do it faster than a human, I&apos;m going to try to automate it.&lt;/p&gt;
&lt;p&gt;My 1:1 meetings with the VPs are incredibly efficient.
They&apos;re busy folks and sync time with them is expensive.
It pays to be as async as possible and come prepared to these meetings.
I have reoccurring items, focus areas, and actionables as I do with every 1:1.
I just lean on them more and make sure they&apos;re up-to date.
If there&apos;s nothing to talk about, we skip the meeting.
It&apos;s a little different to what I&apos;m used to with 1:1s, but efficiency is key.&lt;/p&gt;
&lt;h3&gt;Diversity, Inclusion, and Belonging&lt;/h3&gt;
&lt;p&gt;Collaboration works best when everyone is included and feels like they belong.
We want to make sure everyone knows that they can voice their thoughts and concerns to the CTO.
Eric (our CTO) is fantastic at this, and I&apos;ve seen many contrarian questions asked in his office hours.
They&apos;re always met with understanding and reason, no matter the topic, or who&apos;s asking.
I love this, and want to showcase this more to folks in the company.
I helped with this by re-wording the CTO office hours description with an emphasis on collaboration and inclusion.
If you&apos;re a GitLab employee reading this, come join us in the next office hours and share what&apos;s on your mind.&lt;/p&gt;
&lt;h3&gt;Iteration&lt;/h3&gt;
&lt;p&gt;I&apos;ve written about &lt;a href=&quot;/wrote/starting-small&quot;&gt;iteration&lt;/a&gt; before but it goes doubly so in this role.
If I spend too long thinking about what to do, my tenure will be over and I&apos;ll have done nothing.&lt;/p&gt;
&lt;p&gt;Organizing the Engineering offsite is one of my tasks as Chief of Staff to the CTO.
It reminds me of &lt;a href=&quot;/wrote/running-a-conference.html&quot;&gt;organizing a conference&lt;/a&gt;, or &lt;a href=&quot;/wrote/starting-a-meetup.md&quot;&gt;starting a meetup&lt;/a&gt;.
Just with much less marketing, and a much shorter time-frame.
The only way to eat this elephant is one bite at a time.
We started by finding a time that worked for all the attendees and blocked it on their calendars.
Then we moved to looking for a city to host it in.
Later we&apos;ll look at venues, hotels, flights, and the agenda.&lt;/p&gt;
&lt;p&gt;One. Bite. At. A. Time.&lt;/p&gt;
&lt;h3&gt;Transparency&lt;/h3&gt;
&lt;p&gt;When explaining this role to friends and family, they expected I would get access to, &lt;em&gt;&amp;quot;secret company information&amp;quot;&lt;/em&gt;.
This is not the case.
Since GitLab lives by its transparency value, there&apos;s no information I have now that I wouldn&apos;t have had in my previous role.
I just have the time to dig into it and look at it.&lt;/p&gt;
&lt;p&gt;I&apos;m being as transparent as possible throughout this process.
Not only with posts like this one, but with most aspects of the work.
If you want to see what I&apos;m working on and continue to follow my journey, take a look at the &lt;a href=&quot;https://gitlab.com/gitlab-com/chief-of-staff-cto&quot;&gt;public GitLab project&lt;/a&gt;.
If you want to ask me any questions about the role, check the links in the footer and get in touch.
If you work at GitLab and you&apos;re interested in doing this role yourself, &lt;a href=&quot;https://about.gitlab.com/handbook/engineering/cto-staff/#registration-process&quot;&gt;register for it&lt;/a&gt;, or come speak to me.&lt;/p&gt;
</content:encoded></item><item><title>Acting Chief of Staff to the Chief Technology Officer</title><link>https://sam.beckham.io/wrote/acting-chief-of-staff-to-the-chief-technology-officer/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/acting-chief-of-staff-to-the-chief-technology-officer/</guid><description>Acting Who to the what now?</description><pubDate>Mon, 01 Aug 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Today, I take on a new role.
A role with an expiry date.
A role that has me working with the highest levels of engineering leadership at GitLab.
A role with far too many words in the title.
From August 1st till November 1st, I&apos;ll be the &lt;a href=&quot;https://about.gitlab.com/job-families/engineering/acting-cos-to-the-cto/&quot;&gt;Acting Chief of Staff &lt;em&gt;to&lt;/em&gt; the CTO&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;What is an Acting Chief of Staff to the CTO?&lt;/h2&gt;
&lt;p&gt;It&apos;s an unusual title.
It reminds me of Dwight Schrute being the &amp;quot;Assistant &lt;em&gt;to&lt;/em&gt; the Regional Manager&amp;quot;.
Let&apos;s dissect it and talk about what it means.&lt;/p&gt;
&lt;p&gt;A CoS (Chief of Staff) is often used in government and military, but has increased in popularity in the tech industry.
They work with an executive (usually the CEO) to help them be more effective.
This could be running meetings, advancing initiatives, solving disputes, etc.
It depends on the skills of the CoS and the needs of the executive.&lt;/p&gt;
&lt;p&gt;A good way to think of it is like the &lt;a href=&quot;https://gameofthrones.fandom.com/wiki/Hand_of_the_King&quot;&gt;Hand of the King&lt;/a&gt; from Game of Thrones.
Hopefully there&apos;s a few less beheadings, but the general idea is the same.
A CoS is an adviser, liaison, and can (in some cases) make decisions on the executive&apos;s behalf.&lt;/p&gt;
&lt;p&gt;The CoS role is usually to the CEO of a company.
We have a permanent CoS (&lt;a href=&quot;https://gitlab.com/streas&quot;&gt;Stella&lt;/a&gt;) for our CEO (&lt;a href=&quot;https://gitlab.com/sytses&quot;&gt;Sid&lt;/a&gt;).
However, this particular role is, &amp;quot;…to the CTO…&amp;quot; and supports our Chief Technology Officer, Eric.
Otherwise, everything else is the same.&lt;/p&gt;
&lt;p&gt;Another key difference is that this is an &lt;em&gt;&amp;quot;acting&amp;quot;&lt;/em&gt; role.
I won&apos;t be &amp;quot;acting&amp;quot; in a traditional sense.
In this instance, acting means, &amp;quot;temporary&amp;quot;.
I&apos;ll walk like a CoS, talk like a CoS, and do all the things a CoS does.
But on paper, I&apos;ll still be an Engineering Manager.
After three months, I&apos;ll go right back to my old role.&lt;/p&gt;
&lt;h2&gt;Why am I taking this role?&lt;/h2&gt;
&lt;p&gt;This role gives me insight into the upper levels of the company, and I get to see how a C-level executive operates.
It helps me see if this level of management is where I want to end up.
It allows me to build empathy for upper management and see how and why they make decisions.
The role is quite new, so I get to help shape it, and grow it for the next folks.&lt;/p&gt;
&lt;p&gt;The temporary nature of this role offers me a level of reassurance too.
All being well, I&apos;ll have spent three months in one of the best learning opportunities to come my way.
If not, I&apos;ll have lost nothing but time.&lt;/p&gt;
&lt;h2&gt;I have no idea what I&apos;m doing&lt;/h2&gt;
&lt;p&gt;Once again, I&apos;ve found myself in a role where &lt;a href=&quot;/wrote/i-have-no-idea-what-im-doing&quot;&gt;I have no idea what I&apos;m doing&lt;/a&gt;.
But that&apos;s where I thrive.
I&apos;m far more comfortable outside my comfort zone than I am within it.
I would encourage you to step out your comfort zone and &lt;a href=&quot;/wrote/public-speaking-is-scary&quot;&gt;do something that scares you&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As I usually do, I&apos;ll learn and share all I can.
If you&apos;re a Chief of Staff yourself, I want to hear from you.
If you know someone who is, please put them in touch.
I only get three months at this, but I want to give it a good run.&lt;/p&gt;
</content:encoded></item><item><title>Increase Your Focus with Pomodoro</title><link>https://sam.beckham.io/wrote/increasing-your-focus-with-pomodoro/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/increasing-your-focus-with-pomodoro/</guid><description>The Pomodoro technique isn&apos;t novel, or complicated. It&apos;s simple, and it works. Here&apos;s how it helps me focus.</description><pubDate>Fri, 24 Jun 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The Pomodoro technique isn&apos;t novel, or complicated.
It&apos;s simple, and it works.
Here&apos;s how it helps me focus.&lt;/p&gt;
&lt;h2&gt;What is the Pomodoro technique?&lt;/h2&gt;
&lt;p&gt;The beauty of the Pomodoro technique is in its simplicity.
You can sum it up in one sentence:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Work on one thing (and one thing only) for 25 minutes, then have a five minute break.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There&apos;s &lt;a href=&quot;https://francescocirillo.com/pages/pomodoro-technique&quot;&gt;a little more to it&lt;/a&gt;, but that one sentence gets you 80% of the way there.
The key is to force yourself to focus on &lt;strong&gt;a single task&lt;/strong&gt; for the full 25 minutes.
No checking email, no responding to slack messages, no scrolling Twitter, nothing.
Focus on that one task and that one task only.&lt;/p&gt;
&lt;p&gt;It&apos;s surprising how much you get done by having sole focus on one task for a set amount of time.
Spending precious brain power on context-switching slows us down.&lt;/p&gt;
&lt;p&gt;After 25 minutes, take a 5 minute break.
Not just a break from the task, but a proper break.
Go make a cup of tea, stand outside, or get up and walk about.
It&apos;s like a rest period at the gym.
Do whatever helps your brain recover.&lt;/p&gt;
&lt;p&gt;It&apos;s recommended to take a longer, 25 minute break after 3 or 4 rounds of Pomodoro.
These focus sessions can feel intense.
Don&apos;t burn yourself out.&lt;/p&gt;
&lt;h2&gt;It&apos;s not all-or-nothing&lt;/h2&gt;
&lt;p&gt;If you&apos;re inclined to do so, you can use the Pomodoro technique all day.
Chunk your whole day into 25 minute focus sessions and work through each one.
For some folks, this works wonders.
For others, it doesn&apos;t.
As I have &lt;a href=&quot;/wrote/find-what-makes-you-productive&quot;&gt;mentioned before&lt;/a&gt;, everyone is different and your results may vary.&lt;/p&gt;
&lt;p&gt;I use it more sporadically.
It&apos;s a tool I use when I want to really focus on one particular task.&lt;/p&gt;
&lt;p&gt;For example, I know I want to spend a couple of hours working on this post.
So I&apos;ll dedicate four Pomodoro sessions to writing it.
Two for the first draft, one for editing it, and one for publishing and making final tweaks.
These won&apos;t all be back-to-back though.
I like to have some time between the first draft and the edit to come at it fresh.
Between the second and third Pomodoro, I&apos;ll work on something else.&lt;/p&gt;
&lt;h2&gt;Time-box the time-sinks&lt;/h2&gt;
&lt;p&gt;This technique not only helps you focus, but it helps to time-box certain activities.
In writing this post, I know I only have the appetite to spend a couple hours on it.
I have other things to do and don&apos;t want to spend all day on it.
Time-boxing it to four Pomodoro sessions ensures I don&apos;t go down a rabbit-hole and while away at it all day.
Knowing my own mind, I would start on this in the morning and before I know it I&apos;d be looking up and it&apos;s the end of the day.
Anyone who&apos;s played &lt;a href=&quot;https://www.destructoid.com/civilization-beyond-earth-makes-weekends-disappear/&quot;&gt;Civilization&lt;/a&gt; will know exactly what I&apos;m talking about.
Having a 25-minute timer helps to pull me out of my own head.&lt;/p&gt;
&lt;p&gt;There it goes now, see you in five!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you&apos;re struggling to get this working for you, these tips might help:&lt;/p&gt;
&lt;h3&gt;1. Do not disturb&lt;/h3&gt;
&lt;p&gt;Turn on &amp;quot;do not disturb&amp;quot;, put your phone in the other room, or use a focus app.
Do whatever you need to do to put a barrier between you and your distractions.
These notifications will still be there when your 25 minutes is up.
Don&apos;t let the pings, bleeps, and bloops distract you from what you&apos;re focusing on.&lt;/p&gt;
&lt;h3&gt;2. Block out time on your calendar&lt;/h3&gt;
&lt;p&gt;Block some time on your calendar for &amp;quot;focus time&amp;quot;.
This lets people know not to bother you during that time.
Or, at the very least, tells them exactly why you&apos;re not responding to their messages.
&lt;a href=&quot;/wrote/take-control-of-your-calendar&quot;&gt;Take control of your own time&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;3. Use a physical timer&lt;/h3&gt;
&lt;p&gt;It&apos;s called the Pomodoro technique because traditionally, it uses a Pomodoro timer.
These are small kitchen timers in the shape of a tomato.
Or, &lt;a href=&quot;https://translate.google.com/?sl=it&amp;amp;tl=en&amp;amp;text=pomodoro&amp;amp;op=translate&quot;&gt;if you&apos;re Italian&lt;/a&gt;, a Pomodoro.&lt;/p&gt;
&lt;p&gt;Sure there&apos;s a load of Pomodoro apps, but most require you to have your phone with you.
See point 1 for why this is a bad idea.
Plus, it&apos;s kinda fun to have a physical timer.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/increasing-your-focus-with-pomodoro/timer.jpg&quot; alt=&quot;A traditional, physical Pomodoro timer&quot;&gt;
&lt;em&gt;&lt;a href=&quot;https://www.flickr.com/photos/149561324@N03/37941061684&quot;&gt;Egg timer in tomato shape for Pomodoro Technique&lt;/a&gt; by &lt;a href=&quot;http://foto.wuestenigel.com/?utm_source=37941061684&amp;amp;utm_campaign=FlickrDescription&amp;amp;utm_medium=link&quot;&gt;Marco Verch&lt;/a&gt;, licensed under &lt;a href=&quot;https://creativecommons.org/licenses/by/2.0/&quot;&gt;CC by 2.0&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;4. Distracted? Start again&lt;/h3&gt;
&lt;p&gt;Find yourself distracted during your focus period?
Maybe you let an email notification pull you in, or a passing thought took hold.
Start the timer again.
Whether you&apos;re 2 minutes in or 20.
Start the timer again.
This helps annoy you into focusing next time and not fall back into old habits.&lt;/p&gt;
&lt;h3&gt;5. Don&apos;t take it too serious&lt;/h3&gt;
&lt;p&gt;Counter to all the advice above, maybe the best way to get this to work for you is to care less.
We&apos;re all different and for some people the pressure of being forced to focus is all they can focus on.
There are no rules here; &lt;a href=&quot;/wrote/find-what-makes-you-productive&quot;&gt;do what works for you&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Give it a go&lt;/h2&gt;
&lt;p&gt;Search for this technique and you&apos;ll find hundreds of Pomodoro apps.
Don&apos;t bother with them.
The beauty of this technique is its simplicity.
Use what you have, find a task to focus on and set a timer for 25 minutes.
Grab that old egg-timer out of the drawer, use your watch, or yell, &amp;quot;Alexa! Set a timer for 25 minutes!&amp;quot;.
Whatever gets you started.&lt;/p&gt;
&lt;p&gt;As ever, I&apos;m interested to hear your thoughts.
Have you done this before and loved it?
Did you hate it?
Are you eager to try it?
Give it a go and join the discussion below.&lt;/p&gt;
&lt;p&gt;What&apos;s stopping you?&lt;/p&gt;
</content:encoded></item><item><title>Starting small</title><link>https://sam.beckham.io/wrote/starting-small/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/starting-small/</guid><description>The secret to getting something done is simple. Go ahead and do it.</description><pubDate>Sat, 07 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The secret to getting something done is simple. &amp;lt;br/&amp;gt; Go ahead and do it.&lt;/p&gt;
&lt;h2&gt;Boring Solutions&lt;/h2&gt;
&lt;p&gt;At GitLab we embrace &lt;a href=&quot;https://about.gitlab.com/handbook/values/#boring-solutions&quot;&gt;boring solutions&lt;/a&gt;. We look for the smallest possible thing we can ship that gets us on the right path.
For an example, take a look at the Pipeline Authoring Group&apos;s &lt;a href=&quot;https://docs.gitlab.com/ee/ci/pipeline_editor/&quot;&gt;Pipeline Editor&lt;/a&gt;.
We wanted to build a new editor that would help users create, edit, and update their pipeline configurations.
When we started discussing it, we thought big:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;Wouldn&apos;t it be cool if we could visualize the pipeline you were building in &lt;strong&gt;real time&lt;/strong&gt;?&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;Imagine writing a pipeline config with &lt;strong&gt;syntax highlighting&lt;/strong&gt;, &lt;strong&gt;auto suggestions&lt;/strong&gt;, and all the other features our IDE&apos;s give us!&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;Could we build a pipeline &lt;strong&gt;visually&lt;/strong&gt; and have the editor convert everything back into a yaml configuration file?&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&amp;quot;What if we had a &lt;strong&gt;library of common components&lt;/strong&gt; that we could include right into our configurations from the editor?&amp;quot;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;With all those ideas in our minds, we started thinking small.
What was the boring solution?
What was the smallest possible thing we could ship that set us on the right path to iterate towards all the great features we dreamed up?&lt;/p&gt;
&lt;p&gt;Our boring solution?
A text area.&lt;/p&gt;
&lt;p&gt;We dialled everything back and introduced the feature as a &lt;a href=&quot;https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46119&quot;&gt;readonly text editor&lt;/a&gt; that loaded in your &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; configuration.
After that, we allowed you to edit it, then &lt;a href=&quot;https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47083&quot;&gt;commit it those changes&lt;/a&gt; into your repo.
It wasn&apos;t fancy, or groundbreaking.
It had none of the awesome features we originally intended for it.
It was everything it needed to be, and nothing else.
It was boring.&lt;/p&gt;
&lt;h2&gt;Iterate&lt;/h2&gt;
&lt;p&gt;The key part of a boring solution is that it puts you on the path to iterate.
Without this crucial step, our pipeline editor would still be little more than a text area.
It&apos;s been a little while since we shipped our boring solution, and we&apos;ve iterated on it from there.
We&apos;ve added a lot of the features we originally planned out and many more we hadn&apos;t thought about.
It&apos;s now a key part of the pipeline experience in GitLab and is a truly awesome feature.&lt;/p&gt;
&lt;p&gt;Starting small and gradually adding functionality offered several benefits:
Firstly, there was something useful that we could start gathering feedback on after a matter of weeks.
The more feedback we got, the more we added to it.
The more we added to it, the more people used it.
The more people used it, the more feedback we got.
The more informed we were, the better our feature developed.&lt;/p&gt;
&lt;p&gt;Little bits, over time.
With something useful at each step.&lt;/p&gt;
&lt;h2&gt;Not just software&lt;/h2&gt;
&lt;p&gt;This idea extends beyond software.
It&apos;s served me well in many aspects of my life and career.
Another example comes from &lt;a href=&quot;/wrote/starting-a-meetup&quot;&gt;starting our meetup&lt;/a&gt;, &lt;a href=&quot;https://frontendne.co.uk&quot;&gt;Frontend NE&lt;/a&gt;.
When starting Frontend NE, we talked about all the things it could become and everything we wanted to achieve with it.
We talked about conferences, speakers, online courses, and all sorts of things.
But we knew if we were going to start this thing, we should start small.
So we started a Twitter account, rented a free back-room in a co-working space and had &lt;a href=&quot;https://www.youtube.com/watch?v=-jh0rHHvIzw&quot;&gt;one of the organizers give a talk&lt;/a&gt;.
The bare-minimum.&lt;/p&gt;
&lt;p&gt;From there, we iterated.
We got a better website, a ticketing system, a bigger room, better AV equipment, sponsors, merch, seasoned speakers, and more.
Each part, gradually, over time.&lt;/p&gt;
&lt;p&gt;Five years later and we were in a much bigger space with a regular turnout of 100 folks.
We&apos;d ran two sold-out conferences and had a semi-successful &lt;a href=&quot;https://www.youtube.com/c/FrontendNE/videos?view=0&amp;amp;sort=p&amp;amp;flow=grid&quot;&gt;YouTube channel&lt;/a&gt; with (almost) all our talks recorded and uploaded.
We would never have had this if we hadn&apos;t started small.
We wouldn&apos;t have achieved the success we had if we hadn&apos;t iterated.&lt;/p&gt;
&lt;h2&gt;Throw it away&lt;/h2&gt;
&lt;p&gt;Another benefit of starting small is that it makes it much easier to throw away things that don&apos;t work.
If we held our first meetup and no one showed up, we wouldn&apos;t have lost much.
A little bit of time and a small amount of money, but nothing compared to if we started big and then realized there was no appetite for it.
Starting small gives you a safer space to make mistakes and pivot.&lt;/p&gt;
&lt;p&gt;Having small iterations allows you to test out ideas.
Maybe you&apos;re adding a feature no one needs, or doesn&apos;t really solve the problem you thought it would.
With small iterations, that&apos;s fine.
You can remove it, or pivot on the idea with relatively little time wasted.&lt;/p&gt;
&lt;p&gt;Don&apos;t be afraid to throw things away.&lt;/p&gt;
&lt;h2&gt;What&apos;s stopping you?&lt;/h2&gt;
&lt;p&gt;So where could a boring solution help you?
What are you procrastinating on that you could just strip back and get started today?&lt;/p&gt;
&lt;p&gt;What&apos;s stopping you?&lt;/p&gt;
</content:encoded></item><item><title>Take Control of Your Calendar</title><link>https://sam.beckham.io/wrote/take-control-of-your-calendar/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/take-control-of-your-calendar/</guid><description>You own your calendar, don&apos;t let your calendar own you.</description><pubDate>Fri, 25 Feb 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I love &lt;a href=&quot;/wrote/all-meetings-are-optional/&quot;&gt;async weeks&lt;/a&gt;, but they&apos;re a temporary fix.&lt;/p&gt;
&lt;p&gt;They&apos;re the crash diet of the remote work world.
Sure you lose the weight, but you gain it all back once you return to your usual routine.
The healthier solution for the long-term is to change your meeting (or eating) habits.&lt;/p&gt;
&lt;p&gt;I wanted to own my calendar and have more time to focus without feeling like I need to resort to an async week.
I&apos;ll still have async weeks—we&apos;ve committed to doing one per quarter—but I&apos;d rather not &lt;em&gt;need&lt;/em&gt; them.&lt;/p&gt;
&lt;h2&gt;Analyzing the Calendar&lt;/h2&gt;
&lt;p&gt;The first step in cleaning up my calendar was to assess the current state.
When starting this process, my calendar looked like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/take-control-of-your-calendar/calendar_before.svg&quot; alt=&quot;My chaotic calendar before I started taking control&quot;&gt;&lt;/p&gt;
&lt;p&gt;I&apos;ve removed the text to keep things confidential, but this is my actual calendar from a few weeks ago.
It&apos;s a mess.
There&apos;s a lot of meetings and they&apos;re all over the place.
Some of those meetings were important and un-missable.
Some of them weren&apos;t important at all and my non-attendance wasn&apos;t even noticed.
But they all looked the same.&lt;/p&gt;
&lt;p&gt;In Lara Hogan&apos;s essential book, &lt;a href=&quot;https://resilient-management.com/&quot;&gt;Resilient Management&lt;/a&gt; she states:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;I began color-coding my calendar events based on the kind of brain I was going to be using during that time.&amp;quot; — Lara Hogan&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This exercise is helpful to see where you spend your time.
You can also glance at your calendar and get a feel for the kind of day you&apos;re going to have.&lt;/p&gt;
&lt;p&gt;I colored my calendar based on the following mapping:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&amp;lt;code style=&amp;quot;background-color: #d50000&amp;quot;&amp;gt;Red&amp;lt;/code&amp;gt; – Interviews&lt;/li&gt;
&lt;li&gt;&amp;lt;code style=&amp;quot;background-color: #8e24aa&amp;quot;&amp;gt;Violet&amp;lt;/code&amp;gt; – 1:1 with reports/manager&lt;/li&gt;
&lt;li&gt;&amp;lt;code style=&amp;quot;background-color: #7986cb&amp;quot;&amp;gt;Indigo&amp;lt;/code&amp;gt; – 1:1 with peers&lt;/li&gt;
&lt;li&gt;&amp;lt;code style=&amp;quot;background-color: #039be5&amp;quot;&amp;gt;Blue&amp;lt;/code&amp;gt; – Group meetings I&apos;m leading&lt;/li&gt;
&lt;li&gt;&amp;lt;code style=&amp;quot;background-color: #0b8043&amp;quot;&amp;gt;Green&amp;lt;/code&amp;gt; – Group meetings I&apos;m not leading&lt;/li&gt;
&lt;li&gt;&amp;lt;code style=&amp;quot;background-color: #f6bf26&amp;quot;&amp;gt;Yellow&amp;lt;/code&amp;gt; – Optional group meetings&lt;/li&gt;
&lt;li&gt;&amp;lt;code style=&amp;quot;background-color: #f4511e&amp;quot;&amp;gt;Orange&amp;lt;/code&amp;gt; – Coffee chats&lt;/li&gt;
&lt;li&gt;&amp;lt;code style=&amp;quot;background-color: #a79b8e&amp;quot;&amp;gt;Gray&amp;lt;/code&amp;gt; – New events (default color)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/take-control-of-your-calendar/calendar_colored.svg&quot; alt=&quot;Color-coding my calendar&quot;&gt;&lt;/p&gt;
&lt;p&gt;This is a much more useful view.
It&apos;s still a mess, but a well-labelled mess.
I can more clearly see where I&apos;m spending my time.&lt;/p&gt;
&lt;p&gt;Looking at the week in retrospect with the colors applied, I got a few bits of information:&lt;/p&gt;
&lt;h3&gt;1. I had a few meetings too close to my lunch break&lt;/h3&gt;
&lt;p&gt;There&apos;s a couple of occasions where meetings sandwiched my lunch break.
This usually resulted in me skipping lunch as I get wrapped up in taking notes, writing follow-ups, and prepping for the afternoon.
If I did manage to get lunch, I often had to sneak mouthfuls in during the next meeting.
That&apos;s not a good look.&lt;/p&gt;
&lt;h3&gt;2. I worked a 12 hour day on Thursday&lt;/h3&gt;
&lt;p&gt;I shouldn&apos;t do that.
I was a zombie in the latter half of that day and for most of the next one.
This was down to poor management of my interview schedule.
To accommodate candidates in APAC (Asia-Pacific) timezones, I opened my calendar up earlier on Tuesday and Thursday.
However, I didn&apos;t adjust the meetings in the latter part of those days to counteract this.
Tuesday was a 10 hour day for similar reasons.&lt;/p&gt;
&lt;h3&gt;3. I spent 30% of my time in meetings, but it felt like much more&lt;/h3&gt;
&lt;p&gt;This is due to the spread of meetings.
The largest block of uninterrupted work (excluding Friday) was 3 hours.
After that, there&apos;s a couple blocks of 2 hours and the rest was 30 minutes here and there.
That&apos;s not enough time to settle in and focus on deep-work.&lt;/p&gt;
&lt;h3&gt;4. There were a few meetings I didn&apos;t respond to&lt;/h3&gt;
&lt;p&gt;Most of these were company-wide meetings that I didn&apos;t attend, or plan to.
They were optional and I&apos;m sure my presence or response wasn&apos;t missed, but that&apos;s besides the point.
It made it a lot harder to see the meetings I did have as they were often overlapping and taking up valuable space.&lt;/p&gt;
&lt;h2&gt;Fixing the issues&lt;/h2&gt;
&lt;p&gt;These observations gave me a good starting point to set up some rules to follow.
They needed to be simple and memorable, as they will dictate how I organize my calendar going forward.&lt;/p&gt;
&lt;h3&gt;1. Longer lunch breaks&lt;/h3&gt;
&lt;p&gt;I won&apos;t actually take a 2-hour lunch break.
But by blocking out 2 hours each day for lunch, I&apos;ve given myself a lot more flexibility.
It&apos;s scheduled in my calendar every day and no one can add a meeting on top of it.
It also prevents me sandwiching my lunch between two meetings and skipping lunch as a result.
Plus, if I need to take extra time on the odd day, I can do that.&lt;/p&gt;
&lt;h3&gt;2. No meetings in the morning&lt;/h3&gt;
&lt;p&gt;Most of the folks I work with are in AMER (North, Central and South America).
Our overlap is in my afternoon so I can schedule all my meetings after lunch.
This gives me all morning, every day, to get my focus work done and dedicate my afternoon to meetings.&lt;/p&gt;
&lt;p&gt;There are some exceptions.
Some of the folks I work with are in APAC and I&apos;ll have to meet with them earlier.
Bunching them all on the same day will maximize focus time.&lt;/p&gt;
&lt;h3&gt;3. Group like-meetings together&lt;/h3&gt;
&lt;p&gt;Another benefit of color-coding the events is to highlight context-switching.
In &lt;a href=&quot;https://resilient-management.com/&quot;&gt;Resilient Management&lt;/a&gt;, Lara recommends:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;Try grouping meetings together to avoid context-switching, or scatter particularly draining events throughout your week.&amp;quot; — Lara Hogan&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using the colors I applied earlier makes this a lot easier.
Grouping events of the same (or similar) color together reduces context-switching.&lt;/p&gt;
&lt;h3&gt;4. Say &amp;quot;No&amp;quot; to meetings I&apos;m not attending&lt;/h3&gt;
&lt;p&gt;This is common courtesy, but it also helps clean out the visual clutter from my calendar.
Especially when paired with setting my calendar to hide declined events.&lt;/p&gt;
&lt;h3&gt;5. No meetings on Fridays&lt;/h3&gt;
&lt;p&gt;I already had this rule.
In-fact, it&apos;s a general rule at GitLab.
We call them &lt;a href=&quot;https://about.gitlab.com/handbook/communication/#focus-fridays&quot;&gt;Focus Fridays&lt;/a&gt; and they&apos;re awesome.
I love this rule, let&apos;s keep it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;After applying these rules, and doing a bit of calendar shuffling, my calendar for this week looked like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/take-control-of-your-calendar/calendar_after.svg&quot; alt=&quot;My, much tidier, calendar for this week&quot;&gt;&lt;/p&gt;
&lt;p&gt;It&apos;s stunning.
Clear, focused mornings; walled off with a hefty block of OOO for a more flexible lunch.
Followed by an afternoon of contextually-grouped meetings, with an easy start and end to the week.&lt;/p&gt;
&lt;p&gt;There&apos;s 12.5 hours of meetings in there.
This is down ~35% from the 19 hours of meetings in the other week.
10 of those hours are due to me not currently interviewing.
The remaining 6.5 is from declining meetings I don&apos;t need to attend.&lt;/p&gt;
&lt;p&gt;There&apos;s still a few things I&apos;d like to iterate and improve on.
I bunched my APAC meetings together, but they still go outside my usual working hours.
They&apos;re also on a day were I have meetings right up until the end of my usual hours.
This means that instead of being able to shift my day forward an hour on those days, I end out working that extra hour.
This isn&apos;t a huge problem, but if I can sort it, I should.&lt;/p&gt;
&lt;p&gt;There&apos;s also a bit of clutter on Thursday.
The checkered meetings are ones I&apos;ve responded with, &amp;quot;maybe&amp;quot;.
They&apos;re group meetings where I&apos;ll check the agenda 10 minutes before and see if it&apos;s worth tuning into or not.
I should be more decisive here, but I&apos;ll see how it goes.
At least I&apos;ve responded with something on these events.
I&apos;m getting there.&lt;/p&gt;
&lt;h2&gt;Keeping it up&lt;/h2&gt;
&lt;p&gt;New meetings are colored gray to make them easy to spot.
As soon as I see these, I should triage them.
I need to respond, assign them a color, and consider if it fits my rules.
If a meeting doesn&apos;t fit the rules, I should determine if I&apos;m willing to make an exception or request we move it.&lt;/p&gt;
&lt;p&gt;As with everything, this is an ever-evolving process.
I will continue to experiment with my scheduling if something doesn&apos;t feel right.&lt;/p&gt;
&lt;p&gt;With increased focus-time and less context switching, I&apos;m ready to make every week (almost) as productive as an async week.
I&apos;d recommend you try it out and see how this works for you.&lt;/p&gt;
&lt;p&gt;Remember; you own your calendar, don&apos;t let your calendar own you.&lt;/p&gt;
</content:encoded></item><item><title>Writing to Your Future Self</title><link>https://sam.beckham.io/wrote/writing-to-your-future-self/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/writing-to-your-future-self/</guid><description>Do your future-self a favour and write down today what you want to read tomorrow.</description><pubDate>Fri, 24 Dec 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;We&apos;re coming close to the end of another year and it&apos;s time to self-reflect.
How can we accurately remember all we did in the last year?
What if we could reach out to our past-selves and ask them?&lt;/p&gt;
&lt;p&gt;Whilst we can&apos;t travel back in time, we can leave something for our future-selves to discover.
This is what I&apos;ve been doing in 2021.
I&apos;ve been keeping a journal of my management journey.
My accomplishments, my mistakes, how I&apos;m feeling, and where I want to improve.
It&apos;s hastily typed, full of spelling errors, and not for public consumption; but it&apos;s the most useful document I have.&lt;/p&gt;
&lt;p&gt;I started this as a daily thing, but it became cumbersome and I&apos;d go weeks without adding to it.
So I iterated and came up with a process that prompted me to fill it in weekly.
Every Friday I ask myself the following questions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;How do you feel about the past week?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What progress did I make on my top priority?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What is the top priority next week?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;What was my biggest success or failure this week?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How confident do I feel as a manager?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;They&apos;re all free-text and I can write as little or as much as I please.&lt;/p&gt;
&lt;p&gt;Like most projects, I over-engineered it.
I used bash prompts to answer the questions and auto-commit the file to a repo.
Then I use &lt;a href=&quot;https://docs.gitlab.com/ee/user/project/pages/&quot;&gt;GitLab pages&lt;/a&gt; to build out the repo into a &lt;strong&gt;private&lt;/strong&gt; website (see public &lt;a href=&quot;https://samdbeckham.gitlab.io/week-in-review-template/&quot;&gt;example&lt;/a&gt;).
This process helps me focus and makes it difficult to do any real editing of the posts.
It prevents me from spending too long poring over what I&apos;ve written and trying to make it perfect.
The entries are supposed to capture my mood in the moment.
The less editing the better.&lt;/p&gt;
&lt;h2&gt;For your eyes only&lt;/h2&gt;
&lt;p&gt;Whilst I advocate transparency in most matters, this one should be confidential.
It&apos;s a 1:1 with yourself and you should be comfortable to say what&apos;s on your mind.
Keeping it opaque prevents you from overthinking and worrying about other readers.
You can rant, rave, swear, and be as contrarian as you like.
This is your document for you, and you alone.&lt;/p&gt;
&lt;p&gt;With that said, I recently shared some select passages with another Engineering Manager.
They are in their first year as an EM and I&apos;m helping them through some of their challenges.
Being able to share certain passages from when I was having a tough time helped to show them they weren&apos;t alone.
It helped curb their imposter syndrome a little knowing I&apos;d been through the same thing.
This is a topic for another day though.&lt;/p&gt;
&lt;h2&gt;Reflect&lt;/h2&gt;
&lt;p&gt;As cathartic as furiously typing into the void is, it&apos;s much more helpful if you go back and read what you wrote.
After all, past us went to all the effort to &lt;strong&gt;write it down&lt;/strong&gt;, the least future us can do is &lt;strong&gt;read it&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Management is a long-game and it can be tricky to step back and see the whole picture.
Being able to read back through your year (and beyond) gives you the opportunity to spot mistakes you made.
You can watch yourself make poor decisions and learn how to better avoid them.
You can marvel at your own resilience and pay attention to how you pulled yourself out of any pitfalls.
The most cathartic thing by far, is watching yourself struggle with tasks that you now find simple.
It&apos;s a great tool for seeing how far you&apos;ve come on your journey and how you can continue to improve.&lt;/p&gt;
&lt;h2&gt;New Year, new you&lt;/h2&gt;
&lt;p&gt;If you didn&apos;t start doing this a year ago, there&apos;s not a lot to reflect on.
But why not start now?&lt;/p&gt;
&lt;p&gt;To make it easier to start, I&apos;ve made the starter for the system I use public.
You can have it as a &lt;a href=&quot;https://docs.google.com/document/d/1kAf3H8uGNaeP6OmHgtZUzh7jUYKlAIEyZacuMfe0V6U/edit?usp=sharing&quot;&gt;Google Doc&lt;/a&gt;, or fork the &lt;a href=&quot;https://gitlab.com/samdbeckham/week-in-review-template&quot;&gt;over-engineered version&lt;/a&gt; I use.
Use whichever will work the easiest for you and allow you to &lt;a href=&quot;/wrote/keep-the-important-things-within-reach/&quot;&gt;keep it within reach&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Do your future self a favour and start writing to them today.&lt;/p&gt;
</content:encoded></item><item><title>All Meetings are Optional</title><link>https://sam.beckham.io/wrote/all-meetings-are-optional/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/all-meetings-are-optional/</guid><description>I started to feel like I couldn&apos;t finish the work I needed to do because meetings were getting in the way. So I declined all my meetings for a week and went async.</description><pubDate>Fri, 26 Nov 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I started to feel like I couldn&apos;t finish the work I needed to do because meetings were getting in the way.
So I declined all my meetings for a week and went async.&lt;/p&gt;
&lt;p&gt;When doing all-remote, async communication is key.
We have to think about typically synchronous things (like meetings) in a different way.
At GitLab, &lt;s&gt;all&lt;/s&gt; most meetings are optional and have an agenda ready ahead-of-time that anyone can edit.
You can attend meetings asynchronously and work on your own schedule.
Turning the usual way of thinking about meetings on its head puts people back on a level playing field.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;quot;The beauty of asynchronous is that team members can contribute to meetings that occur while they sleep.&amp;quot; — GitLab&apos;s &lt;a href=&quot;https://about.gitlab.com/company/culture/all-remote/asynchronous/#asynchronous-meeting-participation&quot;&gt;All-Remote handbook&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Having an &lt;a href=&quot;../automate-your-meeting-agendas&quot;&gt;active agenda ahead of time&lt;/a&gt; allows people to contribute to the meeting asynchronously.
This has been great for me as it allows me to contribute to meetings that occur outside my working hours.
It allows me to hire and manage folks in APAC (Asia-Pacific) timezones, which I&apos;m &lt;a href=&quot;https://grnh.se/602d58d62us&quot;&gt;currently doing&lt;/a&gt;.
It also allows me to focus on getting things done, without the usual meeting interruptions.
That is exactly what I did last week.
We call it an &lt;a href=&quot;https://about.gitlab.com/handbook/marketing/corporate-marketing/all-remote/#async-weeks&quot;&gt;async week&lt;/a&gt;, and they&apos;re fantastic.&lt;/p&gt;
&lt;p&gt;I&apos;d still &amp;quot;attend&amp;quot; meetings by adding my points to the agenda and watching the discussions on the recording.
I just don&apos;t have to be there at the exact time they were happening.
Recording meetings felt weird at first, but you get used to it.
Being able to watch them at 2x speed and skip the points that don&apos;t apply to you are absolute game-changers.&lt;/p&gt;
&lt;p&gt;A crucial step with async week is to &lt;strong&gt;let people know you&apos;re doing it&lt;/strong&gt;.
You&apos;ll likely have a few meetings where you&apos;ll be missed if you don&apos;t show up.
It also prevents people from scheduling meetings with you for that week.
Let people know, and over-communicate your intentions.
I did this with a cross-posted slack message and brought it up in my usual meetings the week before.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/all-meetings-are-optional/slack-message.png&quot; alt=&quot;Hey folks! I’m taking an async week to catch up on my backlog and focus on hiring. I’ve declined all my meetings for the week but I’ll still be here if you need me and will be checking all the agendas for updates. If we have to meet, that’s not a problem. Just let me know and I’ll be there. Happy Friday and I’l see y’all on the other side!&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, it&apos;s the cathartic process of declining all your meetings.
Clear, calendar, bliss.
You can then &lt;a href=&quot;../find-what-makes-you-productive/&quot;&gt;plan your workload&lt;/a&gt; with ease and revel in all the free time you&apos;ve given yourself.&lt;/p&gt;
&lt;p&gt;I used this week to burn though my backlog, but it also gave me a new outlook on the meetings I do have.
I couldn&apos;t do an async week every week, but there&apos;s a few meetings I don&apos;t need to attend as often, or at all.
These meetings can pile up.
My next step; get brutal with my regularly scheduled calendar events.
But that&apos;s a topic for another day.&lt;/p&gt;
&lt;p&gt;This wouldn&apos;t work without our company-wide stance of async-first communication.
Huge props to &lt;a href=&quot;https://twitter.com/darrenmurph&quot;&gt;Darren&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/jessicareeder&quot;&gt;Jessica&lt;/a&gt;, and our remote team for helping foster a culture that allows us to take weeks like this.
Check out our &lt;a href=&quot;https://about.gitlab.com/company/culture/all-remote/asynchronous/&quot;&gt;all-remote handbook&lt;/a&gt; for tips on how to do this.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Side note:&lt;/strong&gt; I made a desktop wallpaper to remind me that, &amp;quot;all meetings are optional&amp;quot;. &lt;a href=&quot;/downloads/all_meetings.png&quot;&gt;Check it out&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title>Find What Makes You Productive</title><link>https://sam.beckham.io/wrote/find-what-makes-you-productive/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/find-what-makes-you-productive/</guid><description>Create and cultivate the productivity workflow that works for you</description><pubDate>Mon, 01 Nov 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In my never-ending quest to find the secret of infinite productivity, I&apos;ve realized one thing:
No one method works for everyone.&lt;/p&gt;
&lt;p&gt;I&apos;ve read the usual heavy-hitters like, &lt;a href=&quot;https://amzn.to/3mrY70k&quot;&gt;Getting Things Done&lt;/a&gt;, &lt;a href=&quot;https://amzn.to/3Cqyeni&quot;&gt;Eat That Frog&lt;/a&gt;, and &lt;a href=&quot;https://amzn.to/3Ctg6cD&quot;&gt;The 7 Habits of Highly Effective people&lt;/a&gt;.
I&apos;ve listened to hours of podcasts, and talked with folks from all over the place.
I&apos;ve tried this, that, and the other thing.
My mistake was thinking too prescriptively.&lt;/p&gt;
&lt;p&gt;This was all good advice, but they were insights into what worked for the people that wrote them.
I am not those people, and (most likely) neither are you.&lt;/p&gt;
&lt;p&gt;The real secret to unlocking your productivity is trying different methods and picking the bits that work for you.
Create your own franken-methodology then continually assess and iterate upon it.
What works for you today may not always work as your life changes, your priorities shift, or you take on different responsibilities.&lt;/p&gt;
&lt;h2&gt;My (current) process&lt;/h2&gt;
&lt;p&gt;My current process is a hodge-podge of other methodologies that work for me now.
It has changed a lot and it will change again.
Use it as inspiration and look deeper and see what works for you.
Build your own productivity monster!&lt;/p&gt;
&lt;p&gt;I use &lt;a href=&quot;https://todoist.com&quot;&gt;todoist&lt;/a&gt; to collate all my tasks in one place.
These come from GitLab issues, emails, conversations, and random thoughts in my own brain.
To maintain my sanity I keep them all in one place; that place is todoist.
The important thing for me is that I can add these tasks fast, from anywhere.
I make sure to &lt;a href=&quot;/wrote/keep-the-important-things-within-reach&quot;&gt;keep it within reach&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I triage my tasks according to the &lt;a href=&quot;https://www.themuse.com/advice/a-better-todo-list-the-135-rule&quot;&gt;1-3-5 rule&lt;/a&gt;.
I plan for the week and iterate on that plan daily.
I delegate some tasks and abandon the tasks that don&apos;t matter.
The remaining tasks get a priority label (&lt;code&gt;P1&lt;/code&gt;, &lt;code&gt;P2&lt;/code&gt; or &lt;code&gt;P3&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Each day has &lt;strong&gt;only one&lt;/strong&gt; &lt;code&gt;P1&lt;/code&gt; task.
This is my most important task of the day.
I do it first and &lt;a href=&quot;https://amzn.to/3Cqyeni&quot;&gt;Eat That Frog&lt;/a&gt; before moving on to my other tasks.
If anything unexpected comes up in the afternoon I&apos;ll likely have already done the important thing that day.&lt;/p&gt;
&lt;p&gt;There are &lt;strong&gt;three&lt;/strong&gt; &lt;code&gt;P2&lt;/code&gt; tasks.
These tasks are likely to get done, but can be pushed along a day or two if needed.
If a task gets pushed along too many times, I will re-asses it.
If it&apos;s important, I&apos;ll bump it up to a &lt;code&gt;P1&lt;/code&gt; and make sure to eat it first thing the next morning.
If it&apos;s not important, it goes onto the backlog.&lt;/p&gt;
&lt;p&gt;Finally, there are &lt;strong&gt;five&lt;/strong&gt; &lt;code&gt;P3&lt;/code&gt; tasks.
These are of similar importance to &lt;code&gt;P2&lt;/code&gt; tasks but are a lot quicker to do.
If I have a spare few minutes between meetings, or I finish another task early, Ill pick one of these up.&lt;/p&gt;
&lt;p&gt;All these tasks are time-boxed with a &lt;a href=&quot;https://amzn.to/2Zwo5XQ&quot;&gt;pomodoro timer&lt;/a&gt;.
This helps me focus on the task at hand and prevents me going too deep into a rabbit-hole on some of the more open ended tasks.&lt;/p&gt;
&lt;p&gt;I try to be as transparent as possible with my task-list.
I &lt;a href=&quot;https://twitter.com/samdbeckham/status/1364192807276212224&quot;&gt;created a web app&lt;/a&gt; that scrapes my todo list for the current day and displays it for ~everyone~ the whole company to see.
The app also helps me communicate my task list in slack using our Geekbot standup.&lt;/p&gt;
&lt;p&gt;This method seems clinical and prescriptive.
That&apos;s because it is.
In all honesty, I deviate from it more than I stick to it.
But having this plan in place helps me stay on track, even if I need to wander off that track every now and again.&lt;/p&gt;
&lt;h2&gt;The Important Thing&lt;/h2&gt;
&lt;p&gt;The important thing to note is not what I do.
It&apos;s that I&apos;ve taken aspects of all sorts of different methodologies to build one that works &lt;em&gt;for me&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;I used to get distracted a lot and spend more time on tasks that interested me.
I combatted this using &lt;a href=&quot;https://amzn.to/3Cqyeni&quot;&gt;Eat That Frog&lt;/a&gt; and the &lt;a href=&quot;https://amzn.to/2Zwo5XQ&quot;&gt;pomodoro timer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I used to feel overwhelmed at the amount of tasks I had.
I combatted this by collating them all into one place.&lt;/p&gt;
&lt;p&gt;I used to agree to do things verbally, then completely forget about them.
I combatted this by keeping my task-list &lt;a href=&quot;/wrote/keep-the-important-things-within-reach&quot;&gt;within reach&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There&apos;s more I still need to improve on, but I&apos;ll do so iteratively.
Experiment, iterate, and find what works for you.&lt;/p&gt;
</content:encoded></item><item><title>Keep the important things within reach</title><link>https://sam.beckham.io/wrote/keep-the-important-things-within-reach/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/keep-the-important-things-within-reach/</guid><description>Make sure there&apos;s as few steps as possible between you and your most important tasks</description><pubDate>Tue, 26 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The best advice I received when learning to play guitar, was to &lt;strong&gt;keep it within reach&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Don&apos;t put it away, in a bag, in a cupboard, or in a room you don&apos;t go in.
Keep it to hand so that when you get a spare few minutes you pick it up and play it.
Make sure there are as few steps as possible between whatever you&apos;re doing and playing the guitar.
Do this and you&apos;ll practice more, learn faster, and be a better player.&lt;/p&gt;
&lt;p&gt;This extends to my day-to-day life, especially at work.
I need to make sure there&apos;s as few steps as possible between me and my most important tasks.
For me, these tasks are usually:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#adding-items-to-my-todo-list&quot;&gt;Adding items to my todo list&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#accessing-my-11-agendas&quot;&gt;Accessing my 1:1 agendas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#searching-the-gitlab-handbook&quot;&gt;Searching the GitLab handbook&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#finding-bookmarks&quot;&gt;Finding bookmarked GitLab issues or MRs&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For most of these tasks I use &lt;a href=&quot;https://www.alfredapp.com/&quot;&gt;Alfred&lt;/a&gt;.
Alfred is a Mac app that predates the built-in spotlight search and offers many similar features.
You can create your own workflows with simple flowchart based logic, or break out into code and make them as powerful as you need.
The majority of mine fall into the former category as I&apos;m a firm believer in the boring solution.&lt;/p&gt;
&lt;h2&gt;Adding items to my todo list&lt;/h2&gt;
&lt;p&gt;I have a regimented system for managing my todos.
The heart of it requires me to add todos to an inbox for later triaging.
Usually, I&apos;m adding todos mid-meeting or mid-conversation.
The faster I can do this, the better.&lt;/p&gt;
&lt;p&gt;I used to use &lt;a href=&quot;https://github.com/moranje/alfred-workflow-todoist&quot;&gt;Alfred Workflow Todoist&lt;/a&gt; for this.
It&apos;s a little buggy though, and the Todoist Mac app has a much nicer shortcut so now I use that directly.
In a couple of keystrokes, I can start typing in whatever I need to do and send it to my todo list inbox.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/easy-access-to-the-important-things/todoist.gif&quot; alt=&quot;Using Todoist&apos;s quick-add function&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Accessing my 1:1 agendas&lt;/h2&gt;
&lt;p&gt;I have &lt;a href=&quot;/wrote/automate-your-meeting-agendas&quot;&gt;automated the creation of my meeting agendas&lt;/a&gt; but I still need to access them quickly.
This could be to add items to the agenda, look up past items, or have it open during a meeting.
I tried handling this with bookmarks (which I still do for other things) but I needed even faster access.
This required a custom workflow.
Thankfully, Alfred has a built in List Filter method.
I used this to set up a list of all my meeting agenda urls, making them searchable by title.
All I need to do is type &lt;code&gt;11 che…&lt;/code&gt; and I get my 1:1 with Cheryl, or &lt;code&gt;11 auth…&lt;/code&gt; for the Pipeline Authoring group meeting.
Hitting enter opens up the agenda and we&apos;re away.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/easy-access-to-the-important-things/11-dial-m-for-mireya.png&quot; alt=&quot;Searching through my 1:1 documents&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Searching the GitLab handbook&lt;/h2&gt;
&lt;p&gt;The GitLab handbook is the source of all knowledge for everything GitLab.
Unfortunately, the search functionality isn&apos;t amazing (though it is getting better).
Fortunately, it&apos;s public so we can use the power of Google site search.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-url&quot;&gt;https://www.google.com/search?q=site:https://about.gitlab.com/handbook/ {query}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All we need to do is replace &lt;code&gt;{query}&lt;/code&gt; with whatever we want to search.
This gives us a Google results page scoped specifically to the GitLab handbook.
Fantastic.&lt;/p&gt;
&lt;p&gt;Alfred makes this even easier.
I can run &lt;code&gt;handbook {query}&lt;/code&gt; in Alfred and it opens my browser with the search results.
It&apos;s simple and boring, but effective.&lt;/p&gt;
&lt;h2&gt;Finding bookmarks&lt;/h2&gt;
&lt;p&gt;I have a lot of links that are important to access quickly, but change on a semi regular basis.
The planning, retrospective, and release post issues for the current milestone.
OKRs, shared goals, hiring trackers, etc.
They&apos;re all links that I&apos;ll need to reference several times, but not as permanent as a 1:1 or meeting agenda.
For these, I use the browser&apos;s built in bookmarks feature.
To make it one step lazier, I use &lt;a href=&quot;https://github.com/nikipore/alfred-firefoxbookmarks&quot;&gt;Alfred Firefox Bookmarks&lt;/a&gt;.
This way, I type &lt;code&gt;ff {query}&lt;/code&gt; into alfred and get a list of all the bookmarks that match that query.
As with most of the others, it&apos;s simple but saves me a lot of time.&lt;/p&gt;
&lt;h2&gt;All the others that I haven&apos;t named&lt;/h2&gt;
&lt;p&gt;These are my most used workflows, but they&apos;re not the only ones I use.
I have one that &lt;a href=&quot;https://alfred-spotify-mini-player.com/&quot;&gt;controls Spotify&lt;/a&gt;, one that starts a &lt;a href=&quot;https://github.com/vitorgalvao/sandwichtimer&quot;&gt;pomodoro timer&lt;/a&gt;, one to search our org chart, and many more.
The point here is not about the actual tools I use.
It&apos;s about the practice of keeping the important things in reach and making repetitive tasks as quick as possible.
Each task on its own will only save me a few seconds to a minute, but I average 50 uses of alfred a day.
It all adds up.&lt;/p&gt;
</content:encoded></item><item><title>Auto Generate Social Images</title><link>https://sam.beckham.io/wrote/auto-generate-social-images/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/auto-generate-social-images/</guid><description>Make your social previews stand out</description><pubDate>Sat, 23 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve put a lot of effort into designing this site, only to share it on social media and be greeted with this monstrosity of a preview:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/auto-generated-social-images/ugly-preview.png&quot; alt=&quot;An ill-formed social share of a previous article&quot;&gt;&lt;/p&gt;
&lt;p&gt;These previews are generated with &lt;a href=&quot;https://ogp.me/&quot;&gt;open graph tags&lt;/a&gt;.
Little bits of metadata that tell social networks (and other sites) about your site.
They take parameters like, title, description, image, and a few others.
There&apos;s a lot of uses for these, but social previews is the most common.
I had a few set up for this site, but they were poorly configured.
Which is why we see the hot mess in the above screenshot.&lt;/p&gt;
&lt;p&gt;There were some configuration changes I had to make, such as the description being set to &lt;code&gt;undefined&lt;/code&gt;, but the main thing I wanted was preview images.
Images really make your posts stand out in a social feed.
I didn&apos;t want to pair a generic stock image with each post; nor did I want to use the same image for every post.
I wanted each image to be unique, and meaningful.
Something like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/social_images/auto-generate-social-images.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Lovely stuff.
It matches the style and tone of the blog nicely.
It will stand out in any social media feed.
It&apos;s &lt;strong&gt;entirely auto generated&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That&apos;s right.
There&apos;s no Photoshop, Figma, Gimp, or any image editor of any sort used here.
If I change the background color or title of this post, the image changes right along with it.
It&apos;s all done using JavaScript canvas and generated at build time.&lt;/p&gt;
&lt;p&gt;I cobbled this together after reading, &amp;quot;&lt;a href=&quot;https://flaviocopes.com/canvas-node-generate-image/&quot;&gt;How to create and save an image with Node.js and Canvas&lt;/a&gt;&amp;quot;.
If you want to go more in-depth, I&apos;d recommend reading this article.
A lot of my code was &lt;s&gt;copy/pasted from&lt;/s&gt; inspired by it.
With this script, I can pass it a title and a background color and it will generate and write an image to my filesystem.
I&apos;ll no-doubt tweak and update this over time so you can view the up-to-date source &lt;a href=&quot;https://gitlab.com/samdbeckham/sam.beckham.io/blob/main/bin/generateSocialImage.js&quot;&gt;on GitLab&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because I&apos;m using Gridsome to generate this site, I can hook into the &lt;code&gt;api.onCreateNode()&lt;/code&gt; lifecycle hook and make sure an image is generated for each post.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;api.onCreateNode((options) =&amp;gt; {
  if (options.internal.typeName === &amp;quot;Article&amp;quot;) {
    const { title, background } = options;
    generateSocialImage({ title, background });
  }
  return options;
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With a little tweaking though, there&apos;s no reason you couldn&apos;t use this node script on a regular node server, or as a serverless function.
Jason Lengstorf has written another &lt;a href=&quot;https://www.learnwithjason.dev/blog/auto-generate-social-image&quot;&gt;great atricle&lt;/a&gt; on a similar approach.&lt;/p&gt;
&lt;p&gt;All that&apos;s left is to tell the social tags where the image is.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;meta
  property=&amp;quot;og:image&amp;quot;
  content=&amp;quot;https://sam.beckham.io/social_images/auto-generate-social-images.png&amp;quot;
/&amp;gt;
&amp;lt;meta
  name=&amp;quot;twitter:image&amp;quot;
  content=&amp;quot;https://sam.beckham.io/social_images/auto-generate-social-images.png&amp;quot;
/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when we share this post on Twitter (other social media sites are available), we get a much nicer preview image.
Why don&apos;t you &lt;a href=&quot;http://www.twitter.com/share?url=https://sam.beckham.io/wrote/auto-generate-social-images&quot;&gt;share this article&lt;/a&gt; yourself to see it in action!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/auto-generated-social-images/pretty-preview.png&quot; alt=&quot;A much nicer social preview&quot;&gt;&lt;/p&gt;
</content:encoded></item><item><title>Automate Your Meeting Agendas</title><link>https://sam.beckham.io/wrote/automate-your-meeting-agendas/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/automate-your-meeting-agendas/</guid><description>If you use Google Docs for your meeting or 1:1 agendas, here&apos;s a way to automate them. No more copy/pasting agenda templates.</description><pubDate>Tue, 05 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve wrestled with far too many Google docs, for far too many meeting agendas, for far too long.
There must be an easier way.&lt;/p&gt;
&lt;p&gt;After a year or so in engineering management, I&apos;ve run a lot of meetings.
Every meeting should have an agenda, and every agenda should be filled ahead of time.
For repeating meetings, I was copy-pasting agenda templates every week.
Because this task is manual and I&apos;m a lowly human, I often forgot to do it and frantically added the agenda 10 minutes before the meeting.
It was a tedious, repetitive, and boring task; something computers are great at.&lt;/p&gt;
&lt;p&gt;We use Google docs for our meeting agendas so everyone can contribute in real-time.
This also means we can use Google scripts to introduce some automation.
So that&apos;s exactly what I did.
Better yet, I created a library so you can use it too.&lt;/p&gt;
&lt;h2&gt;How to use it&lt;/h2&gt;
&lt;p&gt;You can add this to any Google doc and it should work fine.
The only thing you need to have in your document is a horizontal line separating the heading from the agenda section.
If the code won&apos;t run, this is likely the reason.&lt;/p&gt;
&lt;p&gt;Open the document you want to add the script to, then go to &lt;code&gt;Extensions &amp;gt; Apps Script&lt;/code&gt;.
This should load up the Google Script window and let you start entering some code.
Before we start writing anything, we&apos;ll want to add the &lt;code&gt;MeetingUtils&lt;/code&gt; library.
Click on the &lt;code&gt;+&lt;/code&gt; sign next to &lt;code&gt;Libraries&lt;/code&gt; and enter the ID: &lt;code&gt;1ODNAyDAGqdLk1yfrkXOpoBLvO8OVvxie-xzCToiestMx8uBpCnaSjQD9&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After that, it&apos;s as simple as adding some variables, creating the function, and setting up a schedule.&lt;/p&gt;
&lt;p&gt;For a 1:1 meeting, use the &lt;code&gt;nextOneToOne()&lt;/code&gt; function.
It takes the name of your report, your name, and the day of the meeting.
This day is numeric where &lt;code&gt;sunday = 0&lt;/code&gt;, but you can use the constants included in the library to make it a little easier to read.
See the &lt;a href=&quot;#options&quot;&gt;full range of options&lt;/a&gt; at the bottom of the post.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function addNextAgenda() {
  MeetingUtils.nextOneToOne({
    reportName: &amp;quot;Fred&amp;quot;,
    managerName: &amp;quot;Sam&amp;quot;,
    meetingDay: MeetingUtils.getConstants().WEDNESDAY,
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For a group meeting (or similar) use the &lt;code&gt;nextGroupMeeting()&lt;/code&gt; function.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;function addNextAgenda() {
  MeetingUtils.nextGroupMeeting({
    meetingDay: MeetingUtils.getConstants().WEDNESDAY,
    sections: [&amp;quot;Announcements&amp;quot;, &amp;quot;Discussion&amp;quot;], // You can add as many sections as you like here
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once that&apos;s done, make sure your function can run by selecting the &lt;code&gt;addNextAgenda&lt;/code&gt; function (or whatever you named it) and hitting, &amp;quot;run&amp;quot;.
You may need to do the permissions dance to give the script access to edit your document.
Now, whenever you run that function, it creates a meeting agenda item for the next selected day.&lt;/p&gt;
&lt;p&gt;This is only semi-automated right now.
To fully automate this, we need to create a schedule that runs every week.
Head over to the &lt;code&gt;triggers&lt;/code&gt; tab on the far left and add a repeating trigger.
You can set it to run on all sorts of events, but the most useful one is the time-driven week timer.
I like to set mine to run at midnight the night after each meeting.
This way there&apos;s almost a full week for people to add their agenda items.
Do what works for you though.&lt;/p&gt;
&lt;p&gt;That&apos;s all you need to automate this boring task and get back to doing the interesting things.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Options&lt;/h2&gt;
&lt;p&gt;There are a few different options you can use.
The defaults will work fine, but with a few tweaks, this script is much more versatile.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;nextOneToOne(OPTIONS)&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;By default, this generates a typical 1:1 agenda in the format:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;## YYYY-MM-DD

### Report Name

1.

### Manager Name

1.
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;| Option                 | Description                                                                                                                                  | Required | Default |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- |
| `reportName`           | The name of the report                                                                                                                       | `true`   | -       |
| `managerName`          | The name of the manager                                                                                                                      | `true`   | -       |
| `meetingDay`           | The day of the meeting in numerical format where `sunday = 0`. The script uses this to determine when the next occurrence of the meeting is. | `false`  | `0`     |
| `useHumanReadableDate` | When `true`, changes the date format from `2021-10-11` to `October 11th 2021`                                                                | `false`  | `false` |
| `questionOfTheDay`     | When `true`, adds a randomly selected question of the day to each agenda. This is still experimental.                                        | `false`  | `false` |
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;nextGroupMeeting(OPTIONS)&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This is a less-tailored version of the 1:1 template, generating an agenda item in the format:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;## YYYY-MM-DD

### Section 1

1.

### Section 2

1.
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;| Option                 | Description                                                                                                                                 | Required | Default                           |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------------------------- |
| `meetingDay`           | The day of the meeting in numerical format where `sunday = 0`. The script uses this to determine when the next occournce of the meeting is. | `false`  | `0`                               |
| `sections`             | An array of all the sections you want to include in the agenda. There&apos;s no limit to this.                                                   | `false`  | `[&amp;quot;Announcements&amp;quot;, &amp;quot;Discussion&amp;quot;]` |
| `useHumanReadableDate` | When `true`, changes the date format from `2021-10-11` to `October 11th 2021`                                                               | `false`  | `false`                           |
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>Owning my content again</title><link>https://sam.beckham.io/wrote/owning-my-content-again/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/owning-my-content-again/</guid><description>Adding webmentions to my gridsome site</description><pubDate>Mon, 07 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Medium, we had fun, but you&apos;ve changed. A beautiful reading experience tarnished by paywalls, advertisements, and popovers. I want my content back on my own platform.&lt;/p&gt;
&lt;p&gt;Owning my own platform gives me freedom. Freedom to tweak the code and eek out those extra milliseconds of performance. Freedom to add whatever features I want, and remove those that I don&apos;t. But most of all, the freedom of knowing it won&apos;t ever change or disappear, unless I want it to.&lt;/p&gt;
&lt;p&gt;It does come with a few downsides. The biggest two being discoverability and collaboration. I can write all the posts I want, but no one will see them unless they actively look for them.&lt;/p&gt;
&lt;p&gt;With a couple of extra additions to this site, I may have solved these problems. I just had to use something old, something new, something borrowed, and something blue.&lt;/p&gt;
&lt;h2&gt;Something old&lt;/h2&gt;
&lt;p&gt;Back in the good-old-days we all had our own blogs. People were still able to discover our posts by using &lt;a href=&quot;https://www.copyblogger.com/what-the-heck-is-rss/&quot;&gt;RSS feeds&lt;/a&gt;. You could subscribe to the RSS feeds of you favourite blogs and your RSS reader would collate them all. It&apos;s a bit like Podcasts. You subscribe to the stations you want to listen to. Then your podcast player displays all the new podcasts from your favourite stations. In fact, it&apos;s exactly like podcasts. Because RSS is what they use to manage this.&lt;/p&gt;
&lt;p&gt;Unfortunately, using RSS for blogging died off a little in recent years. But as more and more people want to own their own data again, they&apos;re regaining popularity.&lt;/p&gt;
&lt;p&gt;So, in the sprit of boosting RSS back to the top, I created a feed for this blog. This site is running on Gridsome which made it easy to add an RSS feed. All I needed to do was hook up &lt;a href=&quot;https://github.com/darthmeme/gridsome-plugin-rss&quot;&gt;&lt;code&gt;gridsome-plugin-rss&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;module.exports = {
  plugins: [
    {
      use: &amp;quot;gridsome-plugin-rss&amp;quot;,
      options: {
        contentTypeName: &amp;quot;SanityPost&amp;quot;,
        latest: true,
        feedOptions: {
          title: SITE_NAME,
          feed_url: `${GRIDSOME_BASE_PATH}/rss.xml`,
          site_url: GRIDSOME_BASE_PATH,
        },
        feedItemOptions: (node) =&amp;gt; ({
          title: node.title,
          description: node.description,
          url: `${GRIDSOME_BASE_PATH}/wrote/${node.slug.current}`,
          date: node.publishedAt,
        }),
      },
    },
  ],
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I dropped in the default config, tweaked it to match my own site, ran &lt;code&gt;yarn build&lt;/code&gt; to give it a test, and success! Sort of. The good news was, the feed was there and all my posts were in it. The bad news was, they were in a completely random order. After a little digging I realised they were all alphabetised on their UUIDs. A lovely order, but an entirely useless one. This was because &lt;code&gt;gridsome-plugin-css&lt;/code&gt; sorted posts by &lt;code&gt;node.date&lt;/code&gt; and my Sanity implementation doesn&apos;t have a &lt;code&gt;date&lt;/code&gt; field. It&apos;s a little more granular and has &lt;code&gt;_createdAt&lt;/code&gt; , &lt;code&gt;_updatedAt&lt;/code&gt; , and &lt;code&gt;publishedAt&lt;/code&gt; . The one I wanted was &lt;code&gt;publishedAt&lt;/code&gt; , but there was no way to tell the plugin this information. Yet.&lt;/p&gt;
&lt;p&gt;The best thing about open source is that everyone can contribute. I found a problem with the plugin and took it upon myself to &lt;a href=&quot;https://github.com/darthmeme/gridsome-plugin-rss/pull/11&quot;&gt;fix it&lt;/a&gt;. A couple of changes to the codebase and I could pass in &lt;code&gt;dateField: &amp;quot;publishedAt&amp;quot;&lt;/code&gt; which orders our posts by the correct date field. Joy!&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://sam.beckham.io/rss.xml&quot;&gt;RSS feed&lt;/a&gt; is up-and-running. It&apos;s nothing fancy, but it gets the job done.&lt;/p&gt;
&lt;h2&gt;Something New&lt;/h2&gt;
&lt;p&gt;The best posts are the ones that spark a conversation. But how do we allow those discussions on a static site? I could add Disquss, or use FaaS (Functions as a Service) to let people post comments. But it&apos;s not quite what I want. Usually, I prefer using &lt;a href=&quot;https://about.gitlab.com/handbook/values/#boring-solutions&quot;&gt;the boring solution&lt;/a&gt;. But this time I went for the shiny option. It&apos;s my platform, I&apos;ll do what I want.&lt;/p&gt;
&lt;p&gt;The shiny solution here is a new standard called &lt;a href=&quot;https://indieweb.org/Webmention&quot;&gt;Webmentions&lt;/a&gt;. In essence, they&apos;re a list of all the places that &amp;quot;mentioned&amp;quot; your post. If you Tweet out your post on Twitter, that&apos;s a mention. If someone responds to that Tweet, that&apos;s a mention. If someone likes, or retweets that Tweet, that&apos;s a mention too. Then all you do is take that list, filter it, and render it to your site as &amp;quot;comments&amp;quot;. This isn&apos;t just Twitter either. It works for other sites too, but for simplicity, I&apos;ll stick with Twitter for now.&lt;/p&gt;
&lt;p&gt;Getting this list wasn&apos;t too hard. I followed the instructions on &lt;a href=&quot;https://mxb.dev/blog/using-webmentions-on-static-sites/&quot;&gt;Max Böck&apos;s post&lt;/a&gt; to the letter. If you want them on your site too, I&apos;d start there.&lt;/p&gt;
&lt;p&gt;Once they were set up, I had to integrate them into Gridsome. Unfortunately, Max uses eleventy, so I could only use his post as guidance. There are also no Gridsome plugins for Webmentions yet, so I had to go alone on this one.&lt;/p&gt;
&lt;p&gt;If you want to see exactly how I did it, I&apos;d recommend looking at the &lt;a href=&quot;https://gitlab.com/samdbeckham/sam.beckham.io/merge_requests/4/diffs&quot;&gt;Merge Request&lt;/a&gt; (that&apos;s what we call Pull Requests at GitLab). This whole blog is public, so you can dig in and have a proper look at the code. If you want the cliff notes, the whole thing was done in three steps:&lt;/p&gt;
&lt;h3&gt;1. Add the Webmentions feed into the Gridsome API&lt;/h3&gt;
&lt;p&gt;This is probably the most complex part. I needed to take the API provided by webmention.io and expose it on the GraphQL endpoint in Gridsome. This was done by adding the following code to &lt;code&gt;gridsome.server.js&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const axios = require(&amp;quot;axios&amp;quot;);

const API_ORIGIN = &amp;quot;https://webmention.io/api/mentions.jf2&amp;quot;;
const { GRIDSOME_WEBMENTIONS_TOKEN } = process.env;

module.exports = function(api) {
  api.loadSource(async (store) =&amp;gt; {
    const { data } = await axios.get(API_ORIGIN, {
      params: {
        token: GRIDSOME_WEBMENTIONS_TOKEN,
      },
    });

    const mentions = store.addCollection(&amp;quot;mentions&amp;quot;);

    for (const item of data.children) {
      mentions.addNode(item);
    }
  });
};
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. Pull the mentions into a &lt;code&gt;PostComments.vue&lt;/code&gt; component&lt;/h3&gt;
&lt;p&gt;Once the Webmentions data was available on the GraphQL endpoint, I could pull it into the project. Webmentions collates, likes, retweets, mentions, and replies. But I&apos;m only interested in replies for now so I filtered everything else out using &lt;code&gt;wm_property&lt;/code&gt; .&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-graphql&quot;&gt;query {
  comments: allMentions(
    sortBy: &amp;quot;published&amp;quot;
    filter: { wm_property: { eq: &amp;quot;in-reply-to&amp;quot; } }
  ) {
    edges {
      node {
        id
        author {
          name
          photo
          url
        }
        content {
          text
        }
        published(format: &amp;quot;MMMM Do, YYYY&amp;quot;)
        url
        wm_target
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Unfortunately, Gridsome isn&apos;t able to pass javascript variables into GraphQL queries just yet. Which means I couldn&apos;t filter the mentions by post. This query returns all the mentions for all the posts. To get around this, I requested &lt;code&gt;wm_target&lt;/code&gt; which gave me the url to the post linked to that specific mention. All I needed to do was filter out the ones I didn&apos;t need after I loaded the mentions. Then I had a nice, clean array of &amp;quot;comments&amp;quot; that I could loop over and render as I please.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;computed: {
    comments() {
        return (
            this.$static.comments &amp;amp;&amp;amp;
            this.$static.comments.edges
            .filter(comment =&amp;gt; comment.wm_target.match(this.postSlug))
            .map(comment =&amp;gt; comment.node)
        );
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Re-build the site when new comments are posted&lt;/h3&gt;
&lt;p&gt;Because the comments get baked in at build-time, new mentions won&apos;t be rendered until I re-build the site. All I had to do there was set up a new pipeline trigger and pass the webhook URL to webmention.io. Whenever I get a new mention, webmention.io calls the webhook, GitLab triggers a build, and my site is redeployed. There&apos;s a potential 10-30 minute delay, but it&apos;s a small price to pay. Besides, the conversation is happening on Twitter, I&apos;m just re-rendering it on this site.&lt;/p&gt;
&lt;h2&gt;Something Borrowed&lt;/h2&gt;
&lt;p&gt;The RSS feed is a great first step towards discoverability, but I want to get my posts in front of a bigger audience. This is something Medium gave me for free and one of the main reasons I switched to using it. But there is another way.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dev.to&quot;&gt;Dev. to&lt;/a&gt; is a similar platform to Medium, but with a lot of the junk removed. If I didn&apos;t want to own my own data, this would be the platform I&apos;d use. But just because it&apos;s not my primary platform, doesn&apos;t mean I can&apos;t borrow it when I want to. Dev. to can automatically cross-post your items to their platform. All you have to do is pass it your RSS feed. It&apos;s a good job we&apos;ve just added one of those!&lt;/p&gt;
&lt;p&gt;If you&apos;re reading this post on &lt;a href=&quot;https://dev.to/samdbeckham&quot;&gt;Dev. to&lt;/a&gt;, then this process worked!&lt;/p&gt;
&lt;h2&gt;Something Blue&lt;/h2&gt;
&lt;p&gt;I&apos;ll be honest, this is where the analogy falls down. How about a lovely, blue footer?&lt;/p&gt;
&lt;p&gt;I&apos;m just getting back into writing again. I hope to continue to add little improvements to this blog and write about them as I go. If you end out using any of these techniques on your own sites, let me know!&lt;/p&gt;
</content:encoded></item><item><title>Running the JAMstack on GitLab</title><link>https://sam.beckham.io/wrote/running-the-jamstack-on-gitlab/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/running-the-jamstack-on-gitlab/</guid><description>The JAMstack has piqued my interest. Not because it&apos;s fast, secure, or totally hot right now. But because it got me thinking, &quot;We could run that on GitLab&quot;</description><pubDate>Wed, 02 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The JAMstack has piqued my interest. Not because it&apos;s fast, secure, or totally hot right now. But because it got me thinking, &amp;quot;We could run that on GitLab&amp;quot;.&lt;/p&gt;
&lt;p&gt;These thoughts cross my mind a lot. GitLab is such a versatile tool that it has endless applications. I use GitLab to run a conference, keep track of my wedding plans, and even help create GitLab. It&apos;s almost definitely a case of &lt;a href=&quot;https://en.wikipedia.org/wiki/Law_of_the_instrument&quot;&gt;Maslow&apos;s Hammer&lt;/a&gt; where, &lt;em&gt;&amp;quot;…everything looks like a nail&amp;quot;&lt;/em&gt;. But who cares, I&apos;m eyeing up a JAMstack shaped nail right now, with my GitLab branded hammer in hand.&lt;/p&gt;
&lt;h2&gt;What is the JAMstack?&lt;/h2&gt;
&lt;p&gt;Before we dig into what I did, let&apos;s explain what the JAMstack is. The acronym itself stands for &lt;strong&gt;J&lt;/strong&gt;avascript, &lt;strong&gt;A&lt;/strong&gt;PIs, and &lt;strong&gt;M&lt;/strong&gt;arkup. Which on its own, could describe almost any website. Here&apos;s a quote from the top of &lt;a href=&quot;https://jamstack.org/&quot;&gt;https://jamstack.org/&lt;/a&gt; that explains it better:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A modern architecture —&lt;br&gt;
Create fast and secure sites and dynamic apps with &lt;strong&gt;J&lt;/strong&gt;avaScript, &lt;strong&gt;A&lt;/strong&gt;PIs, and prerendered &lt;strong&gt;M&lt;/strong&gt;arkup, served without web servers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The key part here is &lt;strong&gt;&amp;quot;served without web servers&amp;quot;&lt;/strong&gt;. JAMstack sites are static. They do all the compiling at build time, not at runtime. It&apos;s often confused with isomorphic websites built with &lt;a href=&quot;https://nextjs.org/&quot;&gt;Next&lt;/a&gt;, &lt;a href=&quot;https://nuxtjs.org/&quot;&gt;Nuxt&lt;/a&gt;, or similar. But the concept is entirely different. We&apos;re not rendering pages on the server, then hydrating them once they get to the frontend. We&apos;re building the pages once (at build time) then serving up those static pages at runtime. This makes for a blazing fast website with little to no server costs.&lt;/p&gt;
&lt;h2&gt;Let&apos;s do this&lt;/h2&gt;
&lt;p&gt;If you hadn&apos;t already guessed, the project I created on the JAMstack is the blog you&apos;re reading right now. It looks and behaves in much the same way that it did previously, it&apos;s just a lot faster, and easier to update.&lt;/p&gt;
&lt;p&gt;The first thing I needed to do was pick a static site generator. I had a look at &lt;a href=&quot;https://www.gatsbyjs.org/&quot;&gt;Gatsby&lt;/a&gt; and &lt;a href=&quot;https://www.11ty.io/&quot;&gt;Eleventy&lt;/a&gt;, but ultimately settled on &lt;a href=&quot;https://gridsome.org/&quot;&gt;Gridsome&lt;/a&gt;. It&apos;s based on &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue.js&lt;/a&gt; and integrates with &lt;a href=&quot;https://graphql.org/&quot;&gt;GraphQL&lt;/a&gt;, which is something I&apos;ve been wanting to look into for a while. This seemed like the perfect excuse.&lt;/p&gt;
&lt;p&gt;With the site generator chosen, I needed to work out where to store my data. When this site was running on Jekyll, I used markdown files stored in the repo. Whilst this worked well enough, I wanted a little more flexibility. Something that required a CMS. I chose &lt;a href=&quot;https://www.sanity.io/&quot;&gt;Sanity&lt;/a&gt; based on a recommendation from &lt;a href=&quot;https://twitter.com/jamiebradley234&quot;&gt;Jamie Bradley&lt;/a&gt;. Sanity is a headless CMS with a GraphQL output layer, a perfect fit for my needs.&lt;/p&gt;
&lt;p&gt;With those two chosen, I had everything I needed to get started developing locally. I moved over all my old posts to Sanity, which was a lot harder than I expected. I wish there was an easy way to convert markdown to Sanity blocks (Sanity&apos;s rich text editor) but I had to do it all manually. I guess the one upside to my low output on this blog is that there weren&apos;t too many posts to migrate.&lt;/p&gt;
&lt;p&gt;I already had a lot of the components of my blog written in Vue from when I tried to move it over to &lt;a href=&quot;https://vuepress.vuejs.org/&quot;&gt;VuePress&lt;/a&gt;. A Vue based static site generator that ended out being unfit for purpose. I copied these components over, tweaked them to fit, and added my GraphQL layer. Then I was good to go.&lt;/p&gt;
&lt;p&gt;Once I was ready to deploy, I copied the example &lt;a href=&quot;https://gridsome.org/docs/deploy-to-gitlab/&quot;&gt;&lt;code&gt;.gitlab-ci&lt;/code&gt;&lt;/a&gt; file from Gridsome&apos;s documentation and pushed the site to GitLab. This triggered the build process on GitLab&apos;s CI pipeline and built out the static site to GitLab pages. After two painless DNS additions, I had my domain hooked up to GitLab pages with &lt;a href=&quot;https://about.gitlab.com/2019/07/22/gitlab-12-1-released/#automatic-https-for-pages-with-lets-encrypt&quot;&gt;automatic SSL certs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With very little set up—which consisted more of copy/pasting than any real hard work—I had my blog up-and-running. When I pushed a change to the &lt;code&gt;master&lt;/code&gt; branch, GitLab&apos;s CI pipeline would trigger a build, regenerate all the static files, and re-deploy my website. This was the boring solution. The smallest possible change I could make to get my blog migrated to the JAMstack with GitLab.&lt;/p&gt;
&lt;h2&gt;Iterating on the Boring Solution&lt;/h2&gt;
&lt;p&gt;The boring solution was great, but are were a few small tweaks I could do make to make the process a little nicer.&lt;/p&gt;
&lt;p&gt;Because my content was in Sanity, GitLab wasn&apos;t aware of any changes I made to it. The content publised on the website would be the content from Sanity at the time of the most recent build. I could manually trigger the pipeline after I published a change to pull in the latest data, but I&apos;m far too lazy for that. I needed to automate this. Thankfully, GitLab allows you to create &lt;a href=&quot;https://docs.gitlab.com/ee/ci/triggers/&quot;&gt;pipeline triggers&lt;/a&gt; that can listen to a webhook and start a pipeline every time it&apos;s used. On the Sanity side of things, you can &lt;a href=&quot;https://www.sanity.io/docs/data-store/webhooks#adding-webhook&quot;&gt;call that webhook&lt;/a&gt; every time you publish a post. Now, whenever I publish a post, it triggers the pipeline then the website is re-built and deployed. It&apos;s not as instant as a usual CMS set up but it only takes a minute or so, and it only has to happen once.&lt;/p&gt;
&lt;p&gt;I&apos;m also a bit of a stickler for performance. The boring solution was fast, but still fell down on a few points. I&apos;ve fixed them all now and it&apos;s blazing fast. I&apos;ll save the story of how I did that for another day. To summarise, I minify, lazy-load, pre-fetch, and cache all of the things. I also added in a service worker for good measure and that sweet &lt;a href=&quot;https://sam.beckham.io/wrote/greased-lightning&quot;&gt;offline first&lt;/a&gt; experience.&lt;/p&gt;
&lt;h2&gt;Serverless functions&lt;/h2&gt;
&lt;p&gt;Whilst this site has no need for serverless functions (Functions as a Service, FaaS), they are a large part of the JAMstack. Static websites are great for sites with little user interaction beyond reading information. But what if your site needed to be more complex? What if you needed to allow users to log in, make purchases, or post content? This is where serverless functions come in. They&apos;re API endpoints that (when called) spin up a VM, run some code, then disappear again until they&apos;re needed next time. There are a lot of different platforms that offer this service. AWS Lambda is the biggest right now, but there&apos;s also Azure Functions, Google Cloud Functions, and a load of other providers that offer functions as a service. All of these integrate nicely with &lt;a href=&quot;https://about.gitlab.com/2018/12/11/introducing-gitlab-serverless/&quot;&gt;GitLab Serverless&lt;/a&gt; should the need arise.&lt;/p&gt;
&lt;p&gt;If you want a more in-depth look at how FaaS can be used with the JAMstack, take a look at this section of, &amp;quot;&lt;a href=&quot;https://youtu.be/OUbkm4AH9g4?t=1498&quot;&gt;Are you being servered&lt;/a&gt;&amp;quot; by Phil Hawksworth. Then go back to the beginning and watch the entire talk. It&apos;s a great example of what you can do with the JAMstack.&lt;/p&gt;
&lt;h2&gt;Have a go yourself&lt;/h2&gt;
&lt;p&gt;If you want to have a go at building your own JAMstack website on GitLab, I&apos;ve made &lt;a href=&quot;https://gitlab.com/samdbeckham/sam.beckham.io&quot;&gt;this project&lt;/a&gt; completely public. You can look at the &lt;a href=&quot;https://gitlab.com/samdbeckham/sam.beckham.io/tree/master&quot;&gt;code&lt;/a&gt;, clone the project yourself, and even watch my &lt;a href=&quot;https://gitlab.com/samdbeckham/sam.beckham.io/pipelines&quot;&gt;pipelines&lt;/a&gt;. If GitLab&apos;s not your thing, head on over to &lt;a href=&quot;https://www.staticgen.com/&quot;&gt;staticgen.com&lt;/a&gt;, pick a generator, and get your site up and running in seconds on &lt;a href=&quot;https://www.netlify.com/&quot;&gt;Netlify&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Edit&lt;/h2&gt;
&lt;p&gt;Since releasing this post, I decided that Sanity was not for me.
It was an extra dependency that didn&apos;t always play nice with my pipelines and due to the nature of the JAMstack, I didn&apos;t always know when it wasn&apos;t working.
Besides, for what I needed, markdown is fine.&lt;/p&gt;
&lt;p&gt;I&apos;ve removed Sanity and will continue to write my posts in Markdown.&lt;/p&gt;
</content:encoded></item><item><title>Going transparent</title><link>https://sam.beckham.io/wrote/going-transparent/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/going-transparent/</guid><description>I&apos;ve started a new role at GitLab as a Frontend Engineer and will be doing all my work out in the open.</description><pubDate>Wed, 23 May 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As of today, I&apos;ll be &lt;a href=&quot;https://www.youtube.com/watch?v=fA9niWjui68&amp;amp;feature=youtu.be&amp;amp;t=22s&quot;&gt;going transparent&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&apos;ve started a new role at GitLab as a Frontend Engineer and will be doing all my work out in the open. Every issue, every commit, every comment, all publicly viewable on my &lt;a href=&quot;https://gitlab.com/samdbeckham&quot;&gt;Gitlab profile&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I use Gitlab a lot. I use it for &lt;a href=&quot;https://frontendne.co.uk&quot;&gt;Frontend NE&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/playlist?list=PLQnVLZV0MsRKVTJvKDTFsyWYRLn499JP6&quot;&gt;IHNIWID&lt;/a&gt;, and at &lt;a href=&quot;https://bytemark.co.uk&quot;&gt;Bytemark&lt;/a&gt;. You rarely get the chance to work on something you use every day. I&apos;m very humbled to be given this opportunity. Not only is Gitlab&apos;s software great, but their values are too. They come from an open source background so everything is public. From all the code that makes up GitLab, to how they calculate employee salaries.&lt;/p&gt;
&lt;p&gt;Being transparent comes with many benefits. As a new starter, I could look through the company handbook, see what my team is working on, and get a feel for the volume and pace of work. Going forward, it means my code will be open to scrutiny from my peers, the public, and Gitlab customers. Whilst a scary thought, it does mean that I&apos;ll be more diligent with the code I output. I&apos;ll put more thought in to the Merge Requests I make, and be more clear and precise in my issue comments. In turn, I&apos;ll become a better developer.&lt;/p&gt;
&lt;p&gt;Unfortunately this does mean that I&apos;ve had to leave Bytemark. They&apos;ve been very good to me over the last couple of years and I&apos;ll miss them all dearly. They&apos;re hiring for my old job, so if you&apos;re a front-end dev looking for a new challenge, &lt;a href=&quot;https://careers.bytemark.co.uk/&quot;&gt;take a look&lt;/a&gt;, and tell them I said, &amp;quot;Hi&amp;quot;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn.sanity.io/images/zmu7yd1l/production/efe934740cddf1f616df19f26e3b611f11261a19-622x682.png?w=622&amp;amp;q=100&amp;amp;fit=max&amp;amp;auto=format&amp;amp;dpr=2&quot; alt=&quot;The GitLab Tanuki logo&quot;&gt;&lt;/p&gt;
</content:encoded></item><item><title>Running a Conference</title><link>https://sam.beckham.io/wrote/running-a-conference/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/running-a-conference/</guid><description>Running a conference is 24% blood, 62% sweat, 15% tears, and a pinch of being so overworked you forget how to count to 100; but it&apos;s worth it.</description><pubDate>Tue, 01 May 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Running a conference is 24% blood, 62% sweat, 15% tears, and a pinch of being so overworked you forget how to count to 100.
But it&apos;s worth it.&lt;/p&gt;
&lt;p&gt;We recently wrapped on &lt;a href=&quot;https://2018.frontendne.co.uk&quot;&gt;Frontend NE: The conference 2018&lt;/a&gt;, and I&apos;m happy to say it was a resounding success.
&lt;a href=&quot;https://twitter.com/NikkitaFTW/status/982204431369318400&quot;&gt;Speakers&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/bytemark/status/983351836638924804&quot;&gt;sponsors&lt;/a&gt;, and &lt;a href=&quot;https://twitter.com/wtomcarter/status/982017051429687296&quot;&gt;attendees&lt;/a&gt; alike have said nothing but positive things, so we did something right.
The mighty Christian Heilmann wrote a &lt;a href=&quot;https://christianheilmann.com/2018/04/10/this-was-frontendne-2018-well-from-my-pov/&quot;&gt;lovely article&lt;/a&gt; that sums up the day.&lt;/p&gt;
&lt;p&gt;After running one successful conference I feel I&apos;m totally qualified to write the definitive list on conference organisation…
Just kidding.
I still have a lot to learn, but here&apos;s what I&apos;ve learned so far.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://res.cloudinary.com/samdbeckham/image/upload/c_crop,e_auto_contrast,f_auto,g_center,h_1020,q_auto,w_1020/v1524241927/DaWRSEuX4AA9gmX_uqli7v.jpg&quot; alt=&quot;Photo Courtesy of Bytemark&quot;&gt;&lt;/p&gt;
&lt;h2&gt;It&apos;s just business&lt;/h2&gt;
&lt;p&gt;A conference is a business, so run it like one.
I&apos;m not saying you have to wear a suit and explain to people &lt;a href=&quot;https://www.youtube.com/watch?v=StIcRH_e6zQ&quot;&gt;what it is that you do here&lt;/a&gt;.
But you need to do some basic things to make sure you&apos;re covered.
Register your business, get an accountant, and have a separate bank account.
You&apos;re going to be dealing with a lot of money from a lot of sources.
Self-funding and working out the tax later is not going to cut it.&lt;/p&gt;
&lt;p&gt;As soon as we decided to go ahead with the conference, we hired an accountant and started a Limited Company.
We used that to open a bank account and hooked up our accounting software.
Getting this all set up ahead of time was crucial.
We could now pay people and take in sponsorship with relative ease.&lt;/p&gt;
&lt;h2&gt;Get some sponsors&lt;/h2&gt;
&lt;p&gt;You don&apos;t &lt;strong&gt;have&lt;/strong&gt; to do this, but it helps.
If you can get sponsorship early on, you don&apos;t have to worry as much about selling tickets to break-even.
As long as you&apos;re up-front about what you&apos;re offering, companies will be happy to help out.
Take a look at our (now outdated) &lt;a href=&quot;https://2018.frontendne.co.uk/sponsorship.html&quot;&gt;sponsorship page&lt;/a&gt; for some ideas.
We started with several sponsorship types, but in the end we only used one.&lt;/p&gt;
&lt;p&gt;To price our sponsorship, we worked out how much money we needed to run an MVC (minimum viable conference) for 50 people.
Then we split that cost amongst 6 sponsorship packages.
That way, if everything went terribly and barely anyone bought a ticket, we were covered.
This MVC consisted of, venue hire, A/V hire and speaker costs.
Nothing more.&lt;/p&gt;
&lt;h2&gt;Pay your speakers&lt;/h2&gt;
&lt;p&gt;I shouldn&apos;t have to say this, but a surprising amount of conferences don&apos;t do it.
Your speakers are the main reason people are attending your conference, so pay them.
Pay for their travel, pay for their accommodation, and pay for their time.&lt;/p&gt;
&lt;p&gt;At Frontend NE we paid &lt;strong&gt;all&lt;/strong&gt; our speakers.
Including travel from their door to ours, accommodation close to the venue, and a speaking fee of £1, 000.
We offered every speaker the exact same package, regardless of age, experience, gender, or anything else.
They could also donate some (or all) of their fee to our diversity fund.&lt;/p&gt;
&lt;h2&gt;Have a diversity/student fund&lt;/h2&gt;
&lt;p&gt;A diversity fund pays for tickets, travel, and accommodation for underrepresented people.
This meant that anyone could attend the conference.
Regardless of their race, religion, gender, education level, or financial status.
We borrowed this concept from Remy Sharp&apos;s &lt;a href=&quot;https://2017.ffconf.org/scholarship&quot;&gt;FFconf&lt;/a&gt; which explains it much better than I could.&lt;/p&gt;
&lt;p&gt;Through our diversity fund, we managed to pay for several people to attend our conference.
Not only did this help them, it helped make our conference a lot more diverse and welcoming.
If you do one of these yourself, be sure not to label them, or give them &amp;quot;special&amp;quot; tickets.
This could send the wrong message.&lt;/p&gt;
&lt;h2&gt;Don&apos;t have special tickets&lt;/h2&gt;
&lt;p&gt;Early bird, late bird, student bird, big bird, it&apos;s all too much.
I understand the reasoning behind these ticketing systems, but they&apos;re not for me.
As an attendee I feel undue pressure at the checkout.
As an organiser, I don&apos;t like the cashflow problems it introduces.
We pay the same per-head cost for each person that attends the conference.
So with one ticket we know exactly how many we need to sell to break even.&lt;/p&gt;
&lt;h2&gt;Budget&lt;/h2&gt;
&lt;p&gt;Budgeting and being frugal are often confused, but are not the same thing.
I&apos;m not saying you should cut corners and spend money only when necessary.
Just be aware of what you&apos;re spending and make sure you account for everything.
The last thing you want is to be out of pocket at the end of it all.&lt;/p&gt;
&lt;p&gt;I&apos;m pretty terrible at budgeting.
I leave that to my partner, both in life and in business (not the same person).
Colin handled the budgeting for the conference.
He was the man to ask if you needed to know how much we could spend on things.
This budget saved our skin a few times, and helped a lot when negotiating prices.&lt;/p&gt;
&lt;h2&gt;No man is an island&lt;/h2&gt;
&lt;p&gt;That is to say, don&apos;t do this alone.
Frontend NE is a three-man operation and we have other people that help out with various things all the time.
There&apos;s just too much work for one person to do alone.
We&apos;ve been running a successful meet up together for three years now.
Each of us has a slightly different skill-set that compliments each other&apos;s.
We all have full time jobs, and some of us have families too.
So having other people you can rely on is crucial.&lt;/p&gt;
&lt;p&gt;Huge thank you to &lt;a href=&quot;https://twitter.com/htmlandbacon&quot;&gt;Colin&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/tempertemper&quot;&gt;Martin&lt;/a&gt; for doing this with me and putting up with my bullshit.
You&apos;re the best.&lt;/p&gt;
&lt;h2&gt;Ask for help&lt;/h2&gt;
&lt;p&gt;We had the benefit of having a meet up behind us.
We knew a lot of people we could ask to come and speak, we had an audience to sell to, and we&apos;d already looked at countless venues, caterers, and vendors.
But running a conference is very different to &lt;a href=&quot;/wrote/starting-a-meetup&quot;&gt;running a meetup&lt;/a&gt;
So we asked for help.
We got great advice from other conference organisers up and down the country.
We asked them to tell us about the good, the bad, and the ugly parts of running a conference.
We asked them about what worked for them, what didn&apos;t, and what they&apos;d do different next time.
Then we asked them to try and talk us out of it.
Thankfully, they couldn&apos;t.&lt;/p&gt;
&lt;h2&gt;Get insured&lt;/h2&gt;
&lt;p&gt;Back in December, the venue we had booked for the conference pulled out.
They told us that they were no-longer honoring any bookings made for 2018 and we had to find an alternative venue.
If we hadn&apos;t found another venue, the whole conference would have had to have been cancelled.&lt;/p&gt;
&lt;p&gt;Then in March, the beast-from-the-east hit the toon.
This was a fairly big snow storm, which ground a lot of the North of England to a halt.
It also meant we had to cancel our meetup for the first time ever.
If the storm hit a month later, we would have had to cancel the conference.&lt;/p&gt;
&lt;p&gt;There are a lot of reasons why a conference would need to be cancelled.
Taking out cancellation insurance can ease the financial side of things should the worst-case happen.
If we did have to cancel, we&apos;d be covered for the costs involved in rescheduling.&lt;/p&gt;
&lt;h2&gt;Make a run-sheet&lt;/h2&gt;
&lt;p&gt;You spend a lot of time planning everything out for the conference, but on the day you&apos;re going to forget something.
To combat this, we made a run sheet.
Everyone had their own tasks to be completed at certain times.
No only did this help us in knowing what we had to do, it helped us know what othe other organisers were doing.
This way, everything that needed to be done got done, and no one did anything that someone else had already done.&lt;/p&gt;
&lt;p&gt;&amp;lt;Tweet id=&amp;quot;981930970952716291&amp;quot; /&amp;gt;&lt;/p&gt;
&lt;h2&gt;Have fun&lt;/h2&gt;
&lt;p&gt;In an almost contradictory twist to my initial point, don&apos;t treat this like a job.
We don&apos;t rely on the conference to put food on our tables.
We don&apos;t take any money from it at all.
We do it because we love it.
This means we can make decisions based on what we&apos;d like to see ourselves, and not what would make us money.
We ran the conference in a brewery, hired out a bowling alley, and rented golf carts.
Not because they would sell tickets, but because we could afford them and they were fun.
The more money we made from ticket sales, the more fun things we added to the conference.&lt;/p&gt;
&lt;h2&gt;Thank you&lt;/h2&gt;
&lt;p&gt;I&apos;ve no-doubt missed off a lot of things in this post.
It&apos;s been a very hectic year and a lot of work has been put in by a lot of people.&lt;/p&gt;
&lt;p&gt;I want to end with a thank you.
Thank you to &lt;a href=&quot;https://twitter.com/anthonysterling&quot;&gt;Anthony Sterling&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/gavinelliott&quot;&gt;Gavin Elliot&lt;/a&gt; for their sage advice in conference organisation.
Thank you to &lt;a href=&quot;https://twitter.com/vlh&quot;&gt;Val Head&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/LeonieWatson&quot;&gt;Léonie Watson&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/Jack_Franklin&quot;&gt;Jack Franklin&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/html5test&quot;&gt;Niels Leeheer&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/NikkitaFTW&quot;&gt;Sarah Viera&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/ianfeather&quot;&gt;Ian Feather&lt;/a&gt;, and &lt;a href=&quot;https://twitter.com/codepo8&quot;&gt;Christian Heilman&lt;/a&gt; for being amazing speakers and wonderful people.
Thanks to &lt;a href=&quot;https://twitter.com/NickEVM&quot;&gt;Nick Murphy&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/kaspars_z&quot;&gt;Kaspars Žarinovs&lt;/a&gt; for volunteering their time to us every month.
Thank you to &lt;a href=&quot;https://twitter.com/bytemark&quot;&gt;Bytemark&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/tombola&quot;&gt;Tombola&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/Scott_Logic&quot;&gt;Scott Logic&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/SaleCycle&quot;&gt;Sale Cycle&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/accentureuk&quot;&gt;Accenture&lt;/a&gt;, and &lt;a href=&quot;https://twitter.com/sageuk&quot;&gt;Sage&lt;/a&gt; for sponsoring the event.
Thank you to all the staff at the &lt;a href=&quot;https://twitter.com/wylambrewery&quot;&gt;Wylam Brewery&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/Lane7_&quot;&gt;Lane 7&lt;/a&gt; for being gracious hosts and keeping everything running behind the scenes.&lt;/p&gt;
&lt;p&gt;Most important of all, thank you to all our attendees, and the Frontend NE community.
You&apos;re the reason we put these events on and seeing you get value out of them makes all the blood, sweat, and tears worth it.&lt;/p&gt;
&lt;p&gt;So, who&apos;s up for a &lt;a href=&quot;http://eepurl.com/c5ab35&quot;&gt;sequel&lt;/a&gt;?&lt;/p&gt;
</content:encoded></item><item><title>Deep Copy and the Immutability Issue</title><link>https://sam.beckham.io/wrote/deep-copy-and-the-immutability-issue/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/deep-copy-and-the-immutability-issue/</guid><description>In the latest episode of, &quot;I Have No Idea What I&apos;m Doing&quot; I learned that everything I thought I knew about immutability in Javascript was a lie.</description><pubDate>Mon, 26 Feb 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In the latest episode of, &amp;quot;&lt;a href=&quot;https://www.youtube.com/watch?v=v6FQrXHv2h8&amp;amp;index=7&amp;amp;list=PLQnVLZV0MsRKVTJvKDTFsyWYRLn499JP6&quot;&gt;I Have No Idea What I&apos;m Doing&lt;/a&gt;&amp;quot; I learned that everything I thought I knew about immutability in Javascript was a lie.&lt;/p&gt;
&lt;p&gt;Okay, so I&apos;m being dramatic.
Not everything was a lie.
But a fundamental part of my understanding was incorrect.
After speaking to a few people about the issue, it seems this was a shared misconception.&lt;/p&gt;
&lt;p&gt;This all stems from a subtle, yet fundamental difference in how we copy objects in javascript.
Deep copying and shallow copying.&lt;/p&gt;
&lt;p&gt;Deep copying is what we want for true immutable data.
It is a copy of all the values of an object, and all the values of all the objects within it.
Shallow copying—on the other hand—is a copy of all the values of an object, with references to all the objects within it.
This is what tripped me up.&lt;/p&gt;
&lt;p&gt;To understand the problem, we need to look at &lt;strong&gt;three ways of copying objects&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Referencing&lt;/h2&gt;
&lt;p&gt;Okay, so let&apos;s strip this all the way back.
Let&apos;s create a mutable reference to an object.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const initialObject = {
  name: &amp;quot;Sam&amp;quot;,
  twitter: &amp;quot;@samdbeckham&amp;quot;,
};
const newObject = initialObject;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is bad for immutability because any changes to &lt;code&gt;newObject&lt;/code&gt; reflect in &lt;code&gt;initialObject&lt;/code&gt; like so:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;newObject.twitter = &amp;quot;@frontendne&amp;quot;;
console.log(initialObject.twitter); // @frontendne
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this example, &lt;code&gt;newObject&lt;/code&gt; is a reference to &lt;code&gt;initialObject&lt;/code&gt; .
So whenever we get or set data on either of these objects it is also applied to the other object.
This is useful in a lot of different ways, but not great for immutability.&lt;/p&gt;
&lt;h2&gt;Shallow copying&lt;/h2&gt;
&lt;p&gt;This is the most common form of copying data in an immutable manner.
We utilise the spread operator to create a copy of &lt;code&gt;initialObject&lt;/code&gt; .
If you&apos;ve used redux before, you&apos;ll have seen this inside your reducers.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const initialObject = {
  name: &amp;quot;Sam&amp;quot;,
  twitter: &amp;quot;@samdbeckham&amp;quot;,
};
const newObject = {
  ...initialObject,
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It&apos;s a subtle change, but the &lt;code&gt;...&lt;/code&gt; makes all the difference.
&lt;code&gt;newObject&lt;/code&gt; is no-longer linked to &lt;code&gt;initialObject&lt;/code&gt; .
It&apos;s now a copy of the data and an entirely new object.
So if we make the same change we did earlier, we get the following result:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;newObject.twitter = &amp;quot;@frontendne&amp;quot;;
console.log(initialObject.twitter); // @samdbeckham
console.log(newObject.twitter); // @frontendne
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Modifying the data on &lt;code&gt;newObject&lt;/code&gt; doesn&apos;t affect &lt;code&gt;initialObject&lt;/code&gt; anymore.
We can go about our day, modifying &lt;code&gt;newObject&lt;/code&gt; and &lt;code&gt;initialObject&lt;/code&gt; remains clean.&lt;/p&gt;
&lt;p&gt;But this is a shallow copy, and the immutability is only one level deep.
To show this, we need an object inside our &lt;code&gt;initialObject&lt;/code&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const initialObject = {
  name: &amp;quot;Sam&amp;quot;,
  social: {
    twitter: &amp;quot;@samdbeckham&amp;quot;,
    youtube: &amp;quot;frontendne&amp;quot;,
  },
};
const newObject = {
  ...initialObject,
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At first glance, this &lt;code&gt;newObject&lt;/code&gt; looks like an immutable copy of &lt;code&gt;initialObject&lt;/code&gt; but look what happens when we do this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;newObject.social.twitter = &amp;quot;@frontendne&amp;quot;;

console.log(initialObject.social.twitter); // @frontendne
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sadly, the immutability is only skin deep.
As soon as we go down another level, we&apos;re back to referencing values.
If we were to open up &lt;code&gt;newObject&lt;/code&gt; , it would look a bit like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const newObject = {
  name: &amp;quot;Sam&amp;quot;,
  social: initialObject.social,
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can get around this issue by shallow copying one level deeper and defining &lt;code&gt;newObject&lt;/code&gt; like so:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const newObject = {
  ...initialObject,
  social: {
    ...initialObject.social,
  },
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is how it&apos;s usually dealt with in redux, but it only adds one more level of immutability.
If there are any other nested objects they will still be stored as references.
You can see how (with certain data structures) this could get messy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;_Note:&lt;/strong&gt; &lt;code&gt;Object.assign()&lt;/code&gt; and &lt;code&gt;Object.freeze()&lt;/code&gt; have the same shallow copying issues as spread. _&lt;/p&gt;
&lt;h2&gt;Deep Copying&lt;/h2&gt;
&lt;p&gt;Finally, we get to deep copying.
Deep copying offers us true object immutability.
We can change &lt;strong&gt;any&lt;/strong&gt; value in an object—no matter how deeply nested it is—and it won&apos;t mutate the data we copied it from.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const initialObject = {
  name: &amp;quot;Sam&amp;quot;,
  social: {
    twitter: &amp;quot;@samdbeckham&amp;quot;,
    youtube: &amp;quot;frontendne&amp;quot;,
  },
};
const newObject = deepCopy(initialObject);

newObject.social.twitter = &amp;quot;@frontendne&amp;quot;;

console.log(initialObject.social.twitter); // @samdbeckham
console.log(newObject.social.twitter); // @frontendne
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hooray! We&apos;re immutable!&lt;/p&gt;
&lt;p&gt;Unfortunately, Javascript doesn&apos;t have a function called &lt;code&gt;deepCopy()&lt;/code&gt; so we&apos;ve had to make our own; and it isn&apos;t pretty.
There&apos;s no &amp;quot;nice&amp;quot; way to handle deep copying in Javascript.
Das Surma wrote a &lt;a href=&quot;https://dassur.ma/things/deep-copy/&quot;&gt;article on deep copy&lt;/a&gt; which has a few good examples, here are some of the simpler ones.&lt;/p&gt;
&lt;h3&gt;JSON&lt;/h3&gt;
&lt;p&gt;This is the most concise and easy to understand method, and it looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const deepCopy = (object) =&amp;gt; JSON.parse(JSON.stringify(object));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First we turn the object into a JSON string with &lt;code&gt;JSON.stringify()&lt;/code&gt; then we convert that string back into an object with &lt;code&gt;JSON.parse()&lt;/code&gt; .
Stringifying the data throws out all references, making the returned object completely immutable.
But, if there are any references we need to keep inside this object, they&apos;re gone.
If we have any maps, regex, dates, or other special types; they&apos;re gone.
If we have any cyclic objects inside the object (which we shouldn&apos;t) the whole thing breaks and throws &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value&quot;&gt;an error&lt;/a&gt;.
So it&apos;s not very robust.&lt;/p&gt;
&lt;h3&gt;Data Laundering&lt;/h3&gt;
&lt;p&gt;If you don&apos;t want want to deal with the issues the JSON parser brings, there are a few—albeit hacky—methods you can can use.
These all revolve around pasing our data to a service, then querying that service to pull our cleaned data back out.
It&apos;s like money laundering, only with data, and nowhere near as cool.&lt;/p&gt;
&lt;p&gt;For example, we can utilise the notification API:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const deepCopy = (object) =&amp;gt;
  new Notification(&amp;quot;&amp;quot;, {
    data: object,
    silent: true,
  }).data;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This triggers a notification, silences it, then returns the data from that notification.
Unfortunately, the user needs to be able to receive notifications for this to work.&lt;/p&gt;
&lt;p&gt;We can also utilise the history API and the &lt;code&gt;messageChannel&lt;/code&gt; in similar ways.
But they all have their downsides.&lt;/p&gt;
&lt;h2&gt;What do now?&lt;/h2&gt;
&lt;p&gt;Deep copying is a bit of a heavy-handed approach to immutability.
Being aware of the gotchas of shallow copying should be enough to see you through most problems.
You can use the nested spread method outlined above to fix any problem areas.
If this approach is starting to get unwieldy, you should aim to improve your data structure first.&lt;/p&gt;
&lt;p&gt;If you absolutely &lt;strong&gt;need&lt;/strong&gt; deep copying, then fear not.
There&apos;s an &lt;a href=&quot;https://github.com/whatwg/html/issues/793&quot;&gt;issue on the HTML spec&lt;/a&gt; that hopes to address this, with the introduction of &lt;code&gt;structuredClone()&lt;/code&gt; .
The more visibility this gets, the more likely it is to be implemented.
Until then, I&apos;d suggest using a library like &lt;a href=&quot;https://facebook.github.io/immutable-js/&quot;&gt;Immutable.js&lt;/a&gt; to handle your immutability.
Or grab the &lt;code&gt;cloneDeep()&lt;/code&gt; helper from the &lt;a href=&quot;https://lodash.com/docs/4.17.5#cloneDeep&quot;&gt;underscore&lt;/a&gt; library for a quick-fix.&lt;/p&gt;
&lt;p&gt;If you&apos;re up for a challenge, try coming up with your own solution to deepCopy.
My friend Niall had a lot of fun &lt;a href=&quot;https://twitter.com/JAMXCORE/status/965716621896667137&quot;&gt;playing with some ideas on Twitter&lt;/a&gt;.
I&apos;d be interested to see what you all come up with.&lt;/p&gt;
</content:encoded></item><item><title>I Have No Idea What I&apos;m Doing</title><link>https://sam.beckham.io/wrote/i-have-no-idea-what-im-doing/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/i-have-no-idea-what-im-doing/</guid><description>Everything we have learned is something we knew nothing about at some point. We all have to start somewhere.</description><pubDate>Thu, 30 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Everything we have learned is something we knew nothing about at some point. We all have to start somewhere.&lt;/p&gt;
&lt;p&gt;When learning a new technology I often look for a getting started guide, read some docs, or watch a talk by an expert. Then I&apos;ll start playing with some examples, maybe make a demo app, and slowly pull it into a production workflow. This is a great way to learn, I have no issues with it. However it&apos;s a very solitary practice.&lt;/p&gt;
&lt;p&gt;Recently I joined a group of people in reading &lt;a href=&quot;http://eloquentjavascript.net/&quot;&gt;Eloquent JS&lt;/a&gt;. It&apos;s a book I&apos;d been meaning to read for a long time, but hadn&apos;t gotten round to. Each week we would read a chapter (or two), then discuss it in a dedicated slack channel. We&apos;d share examples, help each other out, and talk about our own understanding of the chapters. This was true collaborative learning. I haven&apos;t learned in this way since I was at university and I forgot how much I missed the social side of learning.&lt;/p&gt;
&lt;p&gt;This got me thinking. What if we learned by watching other people learn? Instead of watching experts tell you how to do something. We get to see common mistakes people make and how they overcome them. We get to see the thought process behind a concept. We get to see that AHA! moment as something finally clicks into place and everything makes sense. We get to learn through the eyes of another learner.&lt;/p&gt;
&lt;h2&gt;Watch me learn&lt;/h2&gt;
&lt;p&gt;I have decided to share my learning experience with the world. I started using &lt;a href=&quot;https://vuejs.org/&quot;&gt;Vue&lt;/a&gt; quite recently and I want to learn more about it. Specifically, I want to learn all about &lt;a href=&quot;https://vuex.vuejs.org/en/&quot;&gt;VueX&lt;/a&gt;. I used Vue to build &lt;a href=&quot;https://phmuseum.com/&quot;&gt;a website&lt;/a&gt; way back in the olden days of 2015 but it&apos;s come a long way since then.&lt;/p&gt;
&lt;p&gt;Every fortnight I&apos;ll be publishing a new video documenting myself learning VueX and creating my very first app with it. &lt;a href=&quot;https://youtu.be/OQuWEtpDS-0&quot;&gt;Episode 0&lt;/a&gt; is available now where I talk a little about what I&apos;m doing and pour over the VueX documentation. The video quality is poor, the audio quality is worse, and my presentation skills are lacking. But none of that matters. Like everything, they&apos;ll all get better with practice.&lt;/p&gt;
&lt;p&gt;So join me on my journey. Come watch me fail spectacularly, then re-write everything once I know the correct way to do it. Comment on where I&apos;m going wrong so we can lift each other up and learn together. I&apos;m going to hold my hand up and proudly say, &amp;quot;I have no idea what I&apos;m doing, yet&amp;quot;.&lt;/p&gt;
</content:encoded></item><item><title>Starting a Meetup</title><link>https://sam.beckham.io/wrote/starting-a-meetup/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/starting-a-meetup/</guid><description>Last week I attended the Web Community Leaders Summit (UK/IE) at the Google offices in London.</description><pubDate>Thu, 29 Jun 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last week I attended the Web Community Leaders Summit (UK/IE) at the Google offices in London.&lt;/p&gt;
&lt;p&gt;I was representing &lt;a href=&quot;https://frontendne.co.uk&quot;&gt;Frontend NE&lt;/a&gt; amongst &lt;a href=&quot;https://twitter.com/rupertwhitehead/status/878490488487243776&quot;&gt;community leaders&lt;/a&gt; from the UK and Ireland.
We talked about our meetups, the issues we faced, and how we overcame those issues.
It was a day of sharing and a great relief to hear that most of them had the same challenges we did in running a meetup.
The day inspired me to write this post:
A story of how Frontend NE began, where it ended up, and where we plan to take it &lt;a href=&quot;https://2018.frontendne.co.uk&quot;&gt;next&lt;/a&gt;.
With all our failures and successes along the way.&lt;/p&gt;
&lt;h2&gt;The Set-Up&lt;/h2&gt;
&lt;p&gt;An &lt;a href=&quot;https://twitter.com/samdbeckham&quot;&gt;Englishman&lt;/a&gt;, an &lt;a href=&quot;https://twitter.com/htmlandbacon&quot;&gt;Irishman&lt;/a&gt;, and a &lt;a href=&quot;https://twitter.com/tempertemper&quot;&gt;Scotsman&lt;/a&gt; walked into a bar…&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/frontendne/one-tweet-to-start-it-all.png&quot; alt=&quot;A screenshot of the tweet that started it all. Colin&apos;s account is private so I couldn&apos;t embed it. &quot;&gt;&lt;/p&gt;
&lt;p&gt;After a Tweet from Colin (who isn&apos;t actually Irish) we met up at the local Brew Dog and sat down over a few beers.
We had a long discussion about meetups—and the lack thereof—in Newcastle.
There were a few that had come and gone, but we wanted better.
We wanted a consistent meetup for Front end developers, with great talks and a better community.
Several beers later, we decided to &lt;a href=&quot;https://xkcd.com/927/&quot;&gt;start our own&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Later that night we registered a Mailchimp account and set up a newsletter signup on a holding page.
Then tweeted it out so there was no going back.&lt;/p&gt;
&lt;p&gt;&amp;lt;Tweet id=&amp;quot;565516838449475584&amp;quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;Right from the start we knew consistency was key.
The original plan was to have it bimonthly, but that got confusing.
&lt;a href=&quot;https://en.oxforddictionaries.com/explore/bimonthly&quot;&gt;Bimonthly&lt;/a&gt; means both, twice a month, and once every two months.
English can be a strange language.
We changed it to monthly and checked &lt;a href=&quot;https://www.techdiary.co.uk/ne&quot;&gt;tech diary&lt;/a&gt; for clashes with other meetups.
The first Thursday of the month was our new date and we drilled that date into everyone&apos;s heads.
It&apos;s right after pay day, it&apos;s easy to remember, and it falls on &lt;a href=&quot;https://en.wikipedia.org/wiki/Star_Wars_Day&quot;&gt;Star Wars day&lt;/a&gt; once every few years.&lt;/p&gt;
&lt;p&gt;Armed with our new date, we booked a venue.
&lt;a href=&quot;http://campusnorth.co.uk/&quot;&gt;Campus North&lt;/a&gt; hosted a lot of meetups in the past, so we approached them first.
They allowed us to use their back room, provided we showed a slide of their sponsors during the event.
We set a date for the first Thursday of the following month, &lt;a href=&quot;https://frontendne.co.uk/events/2015-04-02&quot;&gt;April 2nd 2015&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;All we had left, was to find a speaker.
We set up a &lt;a href=&quot;https://www.typeform.com/&quot;&gt;typeform&lt;/a&gt; survey as a make-shift call for speakers and sent it out to our growing mailing list.
We pestered anyone and everyone that would listen, and put links to the CFP anywhere that would let us.
Then we sat back and waited for the proposals to come in.
We got a lot of submissions.
Some of them were spam, some of them were nonsense, but the majority of them were potential candidates.
This allowed us to create a backlog and start booking people in for the first few meetups.
We wanted to book as far ahead as we could so it wouldn&apos;t fizzle out.&lt;/p&gt;
&lt;p&gt;Somewhere along the way (I forget the chronology of all this) we found some sponsors.
As with the rest of this process, we leaned on our friends to help us out.
&lt;a href=&quot;https://twitter.com/jamiefdhurst?lang=en&quot;&gt;Jamie Hurst&lt;/a&gt; agreed to pick up the pizza tab, whilst &lt;a href=&quot;http://www.peacockcarter.com/&quot;&gt;Peacock Carter&lt;/a&gt; brought along some drinks.
We could never have gotten started without the help of these people and are ever grateful to them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/frontendne/stickers.jpg&quot; alt=&quot;Our first batch of Stickers&quot;&gt;&lt;/p&gt;
&lt;p&gt;We had a date, a venue, some sponsors, and speakers.
Now we could get into promoting the event.
We designed a logo, ordered stickers, extended the website, and set up &lt;a href=&quot;http://ti.to&quot;&gt;tito&lt;/a&gt; so we could sell tickets for the event.
Every opportunity we got to talk about the event, we seized.
Partly to promote it, but also due to our own excitement.
We had wanted something like this for a while now and there was a decent amount of interest for it.&lt;/p&gt;
&lt;h2&gt;The First Thursday in April&lt;/h2&gt;
&lt;p&gt;We announced that we would be releasing (free) tickets a week before our first event.
The room we hired could only fit 30 people comfortably, so we made 30 tickets available.
We hoped for 20 people, expected 15, and would have been happy with 10.
The tickets released at 1:00pm on the 26th of March.
When we checked back 2 hours later, they were all gone.
Every single one.&lt;/p&gt;
&lt;p&gt;30 people may not seem like a lot, but it was far more than we were expecting.
We certainly didn&apos;t expect a sellout.
People were tweeting us asking for more tickets to be released.
We realized we were on to something.
People wanted this almost as much as we did.&lt;/p&gt;
&lt;p&gt;The venue would only allow us 50 people due to the fire regulations.
So we released another 20 tickets the following day at 1pm.
An hour later, they had all gone again.&lt;/p&gt;
&lt;p&gt;We packed out the venue.
I had to stand outside the door to fit people in.
We had two great talks, which we recorded by propping up an iPhone, on a beer bottle, on a ladder, at the back of the room.&lt;/p&gt;
&lt;p&gt;&amp;lt;Tweet id=&amp;quot;583696616588238849&amp;quot; /&amp;gt;&lt;/p&gt;
&lt;p&gt;The quality is understandably terrible, but you can see both talks on &lt;a href=&quot;https://www.youtube.com/frontendne&quot;&gt;our YouTube channel&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=-jh0rHHvIzw&quot;&gt;Speedy, Solid, Semantic layout; with Susy&lt;/a&gt; - Martin Underhill&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=e5W-o-AxZUQ&quot;&gt;CSS to SCSS&lt;/a&gt; - Rob Walker&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In writing this post I went back through my archived notebooks (yes, I archive my notebooks).
I then realized how much we put into starting this thing up.
None of it seemed like hard work at the time because we had a genuine passion for what we were doing.&lt;/p&gt;
&lt;p&gt;If I could give three pieces of advice for anyone wanting to start a meetup themselves, they would be this:&lt;/p&gt;
&lt;h4&gt;Be passionate, and find other passionate people to help you&lt;/h4&gt;
&lt;p&gt;If you&apos;re not that into this, it won&apos;t get done.
It&apos;s hard to find the time (and motivation) for the event, so having more than one organizer is crucial.
They&apos;re there to pick up your slack and keep you motivated.
Just be sure to pick up theirs too.&lt;/p&gt;
&lt;h4&gt;Be consistent&lt;/h4&gt;
&lt;p&gt;This isn&apos;t always possible, but having a consistent date for your meetup is important.
If people know when your event is without having to be told, you&apos;re on to a winner.
It also helps with planning future meetups.
We can book up events as far into the future as we like because we know when every event will be.&lt;/p&gt;
&lt;h4&gt;Plan ahead&lt;/h4&gt;
&lt;p&gt;When we started Frontend NE, we planned the first two meetups at the same time.
We were going through the CFP anyway, so we contacted a few people and got all the booking out of the way there and then.
Now we go a step further and book up several months in advance.
We&apos;re currently booked up until 2018, with March and April&apos;s slots already filled.
Now we can sit back, and not have to worry about whether we&apos;ll have speakers for the next event(s).
Leaving us with more time to sort out the fun stuff.&lt;/p&gt;
&lt;p&gt;There&apos;s still a lot more of this story to tell.
Attracting bigger sponsors, the ever evolving video process, the loss of our venue, and much more.
But I&apos;ll follow up on all that in another post(s).&lt;/p&gt;
&lt;p&gt;Till next time!&lt;/p&gt;
</content:encoded></item><item><title>Greased Lightning</title><link>https://sam.beckham.io/wrote/greased-lightning/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/greased-lightning/</guid><description>There&apos;s something satisfying about tweaking and refining a product. Over the last few years, I&apos;ve been making my blog progressively faster.</description><pubDate>Mon, 18 Jul 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There&apos;s something satisfying about tweaking and refining a product. Over the last few years, I&apos;ve been making &lt;a href=&quot;https://sam.beckham.io&quot;&gt;my blog&lt;/a&gt; progressively faster.&lt;/p&gt;
&lt;p&gt;It&apos;s been more of a passive, than an active task. I just chip away at certain parts when I find a new technique, or I feel a part of the site needs improvement. I&apos;ve &lt;a href=&quot;https://aerotwist.com/blog/flip-your-animations/&quot;&gt;FLIP&lt;/a&gt;ped &lt;a href=&quot;https://github.com/samdbeckham/blog/blob/master/dev/_assets/scripts/components/pageTransition.js&quot;&gt;my animations&lt;/a&gt; to make them more performant. I&apos;ve set smarter caching in my nginx config. I even minified my HTML (every little helps). But recently I made a change that took my load time from an already impressive 600ms, and halved it. To put that in perspective, it takes around 350ms to blink your eye. It loads that fast that if you blink, you&apos;ll miss it. This gets even more impressive when you throttle the connection. On a regular 2G connection my site would load in just under 2 seconds. That&apos;s not too bad, but after my most recent update I got that time down to 300ms. Yep, 300ms on even the slowest of internet connections. In fact, to go one further, it even loads when the connection is so slow, it doesn&apos;t exist. 300ms to load the site, when you&apos;re completely offline.&lt;/p&gt;
&lt;p&gt;If you hadn&apos;t worked it out yet, I&apos;ve just added a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API&quot;&gt;service worker&lt;/a&gt; to my site. As far as service workers go, this one is pretty simple. Once it&apos;s installed, it caches the most used files on the site; the JS, CSS, and index.html. If you then visit any of the articles, it caches them as well. This allows us to design for an &lt;a href=&quot;http://offlinefirst.org/&quot;&gt;offline first&lt;/a&gt; experience. Let me show you how it&apos;s done.&lt;/p&gt;
&lt;h2&gt;Setting the right environment&lt;/h2&gt;
&lt;p&gt;First off, in order to run the service worker, we need to add SSL certificates on our website. I used &lt;a href=&quot;https://letsencrypt.org/&quot;&gt;let&apos;s encrypt&lt;/a&gt; because it was free and I could get it up and running relatively quickly. There are lots of other ways to do it, choose whatever works best for you. As long as we have an SSL cert and can serve our site over &lt;code&gt;https://&lt;/code&gt; , we&apos;re golden.&lt;/p&gt;
&lt;p&gt;If you&apos;re just running this locally, you don&apos;t need to worry about this step. I would recommend using Chrome Canary as (at the point of writing this) there&apos;s a lot more tools for debugging the service worker. You&apos;ll find them all under the &apos;Applications&apos; tab in developer tools.&lt;/p&gt;
&lt;h2&gt;Installation&lt;/h2&gt;
&lt;p&gt;So, we&apos;ve got our secure environment set up, we need to install our service worker. Let&apos;s create a simple javascript file that notifies us of it&apos;s presence.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;console.log(&amp;quot;Service worker, reporting for duty!&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next up, we have to install the service worker. Just pop the following block into your main javascript file and be sure to update the path to your service worker.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;if (navigator.serviceWorker) {
  navigator.serviceWorker.register(&amp;quot;/path/to/serviceWorker.js&amp;quot;, {
    scope: &amp;quot;/&amp;quot;,
  });
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Include this script somewhere on your page and it should find the service worker and install it.
Notice we&apos;ve wrapped the function in an if statement. This just checks the browser supports service workers before trying to install one. If the support isn&apos;t there, the service worker doesn&apos;t get installed and the website goes about it&apos;s day as if nothing happened. Progressive enhancement, done.&lt;/p&gt;
&lt;p&gt;If this is all set up correctly, you should see a message from your service worker in the console. If you navigate to the application tab in developer tools you should see the service worker ticking away as well.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/greased-lightning/console-log.png&quot; alt=&quot;The installed service worker&quot;&gt;&lt;/p&gt;
&lt;p&gt;We&apos;ve installed our service worker, but it doesn&apos;t do a great deal. Let&apos;s hook into the install event and start caching pages.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;self.addEventListener(&amp;quot;install&amp;quot;, (event) =&amp;gt; {
  event.waitUntil(
    caches
      .open(&amp;quot;static-v3.5.1&amp;quot;) // Namespaced on site version number
      .then((cache) =&amp;gt;
        cache.addAll([
          &amp;quot;/scripts/vendor/modernizr.js&amp;quot;,
          &amp;quot;/scripts/main.js&amp;quot;,
          &amp;quot;/css/screen.css&amp;quot;,
          &amp;quot;/wrote&amp;quot;,
        ])
      )
  );
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&apos;s break this down. First off, we hook in to the install event. &lt;code&gt;event.waitUntil()&lt;/code&gt; tells our service worker to wait until all the actions inside that function are completed before finishing the install process and moving into the &lt;code&gt;installed&lt;/code&gt; state.
The installation we wish to perform is to store all the pages we want to cache. &lt;code&gt;caches.open(&apos;static-v3.5.1&apos;)&lt;/code&gt; opens a cache named &lt;code&gt;static-v3.5.1&lt;/code&gt; . Using promises, and &lt;code&gt;.then()&lt;/code&gt; I added my css, js and a couple of key pages to the newly opened cache.&lt;/p&gt;
&lt;p&gt;That&apos;s the installation process done. Like any other installation process, it only has to be done once. If we reload this page, this process gets skipped as we&apos;ll already have all our files in the cache. This is where we run into our first problem, cache invalidation.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There are only two hard things in Computer Science: cache invalidation and naming things.
-- Phil Karlton&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The plan for this service worker is to serve the files from the cache, instead of requesting them from the server. We haven&apos;t told it to do that yet, but it creates a problem that is best fixed early on. Let&apos;s say we update our site&apos;s CSS file. When we refresh the page, the service worker kicks in and loads the cached CSS file, which is now out of date. Bugger.&lt;/p&gt;
&lt;p&gt;Luckily, Chrome has us covered. Just jump back into the service workers tab we were in earlier and hit, &lt;code&gt;[] update on reload&lt;/code&gt; . This will cause Chrome to reload the service worker and re-install itself when you refresh the page, bringing the updated files into the cache. However, we can&apos;t set this flag on our users&apos; browsers. This is why I used the version number of my site when I created the cache. Because I use &lt;a href=&quot;http://semver.org/&quot;&gt;semver&lt;/a&gt;, I can be sure that any releases to my site will have a different version number, and therefore a different service worker cache. When I update the site, you initially see the old one whilst the new one installs in the background. Then the next time you load the site, the new one is all ready and waiting in the new cache for you. This does mean we need to do a little housekeeping, but we&apos;ll get to that later. Back to the good stuff!&lt;/p&gt;
&lt;h2&gt;Request hijacking&lt;/h2&gt;
&lt;p&gt;The service worker is installed, the files are cached, our service worker is primed and ready. This is where the real magic of the service worker comes in to play. Normally, when a browser requests a file it goes straight off to the server. The server hears the request, finds the requested file, and sends it back to the browser. With a service worker, you can intercept this request.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;self.addEventListener(&amp;quot;fetch&amp;quot;, (event) =&amp;gt; {
  event
    .respondWith
    // Response goes here...
    ();
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We start off by listening for the &lt;code&gt;fetch&lt;/code&gt; event, then we hijack the response with &lt;code&gt;event.respondWith()&lt;/code&gt; . At this point we could return anything and the browser will act as if the request went through as normal. Want to listen for all the image requests and swap them out with pictures of Nick Cage? &lt;a href=&quot;https://gist.github.com/samdbeckham/24bb10c44c5bde99753889a809dfeb49&quot;&gt;You can&lt;/a&gt;. However, we need something more practical.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;event.respondWith(
  caches
    .match(event.request)
    .then((response) =&amp;gt; response || fetch(event.request))
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;caches.match(event.request)&lt;/code&gt; goes and checks our cache for the page that&apos;s being requested. If the cache has our page, &lt;code&gt;response&lt;/code&gt; becomes truthy and we serve up the page from the cache. If the page isn&apos;t in the cache, &lt;code&gt;response&lt;/code&gt; is falsy and we return the original fetch event for the page. This line may look a little confusing, but it&apos;s really just shorthand for:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;.then(function(response) {
    if (response) {
        return response
    } else {
        return fetch(event.request)
    }
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If all goes well, we should be successfully serving our pages from the cache. This is the key to making our site blazing fast on even the spottiest of connections.&lt;/p&gt;
&lt;h2&gt;Cleaning house&lt;/h2&gt;
&lt;p&gt;We tackled the majority of the caching issues earlier, but you&apos;ll soon notice a problem. After a while our caches start building up. We&apos;ll have the current version&apos;s cache, but we&apos;ll also have a load of obsolete caches from previous versions. We never access them, so it&apos;s only right we clean them up. It&apos;s rumoured that this is a feature that will be coming to service workers in the future, but for now we can do it ourselves:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const currentCache = &amp;quot;static-v3.5.1&amp;quot;;

self.addEventListener(&amp;quot;activate&amp;quot;, (event) =&amp;gt; {
  event.waitUntil(
    caches.keys().then((cacheNames) =&amp;gt; {
      return Promise.all(
        cacheNames.map((cacheName) =&amp;gt; {
          if (currentCache !== cacheName) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is mostly taken from &lt;a href=&quot;https://jakearchibald.com/&quot;&gt;Jake Archibald&lt;/a&gt; so all credit goes to him for this one. In fact, I&apos;m pretty sure we can credit the majority of the service worker spec to him. If you wanna look into service workers, look into Jake.&lt;/p&gt;
&lt;h2&gt;Optional extras&lt;/h2&gt;
&lt;p&gt;This is all you need to get started with service workers, but there&apos;s a lot more you could do. I&apos;ve added a few optional extras to my service worker, feel free to &lt;a href=&quot;https://github.com/samdbeckham/blog/blob/master/dev/_assets/scripts/serviceWorker.js&quot;&gt;take a look&lt;/a&gt; at it. These work really well with a good &lt;a href=&quot;https://github.com/samdbeckham/blog/blob/master/dev/manifest.json&quot;&gt;manifest&lt;/a&gt; file and are the backbone of the &lt;a href=&quot;https://developers.google.com/web/progressive-web-apps/&quot;&gt;progressive web app&lt;/a&gt; movement. As ever, have a play about with them and see what you can do.&lt;/p&gt;
</content:encoded></item><item><title>A Sprinkling of Web Components</title><link>https://sam.beckham.io/wrote/a-sprinkling-of-web-components/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/a-sprinkling-of-web-components/</guid><description>At UpFront mini last year, I spoke about sprinkling in Web components</description><pubDate>Thu, 30 Jun 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;At UpFront mini last year, I spoke about &lt;a href=&quot;http://slides.com/samdbeckham/using-polymer-today#/8&quot;&gt;sprinkling in Web components&lt;/a&gt;.
It&apos;s a technique I used myself recently so I thought I&apos;d share my experience with you.&lt;/p&gt;
&lt;p&gt;If you missed &lt;a href=&quot;https://sam.beckham.io/wrote/changing-lanes.html&quot;&gt;my last post&lt;/a&gt;, I have recently started working at &lt;a href=&quot;https://bytemark.co.uk&quot;&gt;Bytemark&lt;/a&gt;.
We&apos;re making a big hiring push at the moment and we needed an unobtrusive way to shout about this on our website(s).
We toyed with a few ideas, but ultimately decided on adding a small, dismissible notification.
I could have written my own markup, styled it with some CSS, added some javascript to trigger and hide the notification, test everything, compile, build.
I &lt;em&gt;could&lt;/em&gt; do that, but it&apos;s a lot of effort, and we developers are intrinsically lazy.&lt;/p&gt;
&lt;p&gt;An off-the-shelf solution was what I wanted.
Something robust, pre-tested and easy to modify.
Web components were that solution.
More specifically the &lt;a href=&quot;https://elements.polymer-project.org/elements/paper-toast&quot;&gt;&lt;code&gt;&amp;lt;paper-toast /&amp;gt;&lt;/code&gt;&lt;/a&gt; element.
It ticked all the boxes and it was a good excuse to start using web components in a production environment.&lt;/p&gt;
&lt;h2&gt;Adding it in&lt;/h2&gt;
&lt;p&gt;Thanks to html imports, adding in this web component was really easy.
It&apos;s a three step process, with an optional fourth step.
Download, import, use, and customise.&lt;/p&gt;
&lt;h3&gt;Step 1&lt;/h3&gt;
&lt;p&gt;The first thing we need to do is get the component.
Polymer uses &lt;a href=&quot;https://bower.io/&quot;&gt;bower&lt;/a&gt; to serve it&apos;s components.
It&apos;s not the most elegant solution, but it does the job.
Fire up your console and run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;bower install --save PolymerElements/paper-toast
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 2&lt;/h3&gt;
&lt;p&gt;Now we have the component in our repo, it&apos;s time to include it on the page.
The &lt;code&gt;&amp;lt;paper-toast /&amp;gt;&lt;/code&gt; element has a few dependencies, including polymer itself, but we don&apos;t need to worry about them.
Thanks to the wonders of html imports, we just need to import the element.&lt;/p&gt;
&lt;p&gt;If we want it to work in more than Chrome and Firefox, we need to include a polyfill.
This polyfill gets installed automatically when we install the &lt;code&gt;&amp;lt;paper-toast /&amp;gt;&lt;/code&gt; element.
We just need to pull it into the head, above the html import for the element. Boom, browser support (&lt;a href=&quot;https://www.polymer-project.org/1.0/docs/browsers&quot;&gt;kind of&lt;/a&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;script src=&amp;quot;bower_components/webcomponentsjs/webcomponents-lite.min.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;link rel=&amp;quot;import&amp;quot; href=&amp;quot;bower_components/paper-toast/paper-toast.html&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 3&lt;/h3&gt;
&lt;p&gt;The element is in the repo, it&apos;s included on the page; it&apos;s time to use it.
For one last time, here&apos;s our one liner.
Blink, and you&apos;ll miss it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;paper-toast id=&amp;quot;careersNotification&amp;quot; text=&amp;quot;We&apos;re hiring!&amp;quot; opened&amp;gt;&amp;lt;/paper-toast&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay, so it&apos;s in there, but it&apos;s not very helpful.
Lets take the text out of the attribute and drop in some html:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;paper-toast id=&amp;quot;careersNotification&amp;quot; opened&amp;gt;
  We&apos;re hiring, visit our
  &amp;lt;a href=&amp;quot;http://careers.bytemark.co.uk&amp;quot;&amp;gt;careers page&amp;lt;/a&amp;gt; to find out more.
&amp;lt;/paper-toast&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 4 (optional)&lt;/h3&gt;
&lt;p&gt;We&apos;ve now done everything you need to get that notification showing up on the page.
But what if we want to change the behaviour? Luckily, polymer and web components make this easy too.
In our case, we wanted the element to be persistent and dismissible.
Easy peasy.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;paper-toast id=&amp;quot;careersNotification&amp;quot; duration=&amp;quot;0&amp;quot; opened&amp;gt;
  We&apos;re hiring, visit our
  &amp;lt;a href=&amp;quot;http://careers.bytemark.co.uk&amp;quot;&amp;gt;careers page&amp;lt;/a&amp;gt; to find out more.
  &amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;careersNotification.toggle()&amp;quot;&amp;gt;close&amp;lt;/a&amp;gt;
&amp;lt;/paper-toast&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All we did was add a &lt;code&gt;duration=&amp;quot;0&amp;quot;&lt;/code&gt; attribute to cancel the timeout and keep the notification on the page.
Then we added a link (though this could be any element).
We gave the link a click handler that calls, &lt;code&gt;careersNotification.toggle()&lt;/code&gt; .
Which, unsurprisingly, toggles the notification.&lt;/p&gt;
&lt;p&gt;There&apos;s a whole lot more you can do with this element.
Just take a look at &lt;a href=&quot;&quot;&gt;the docs&lt;/a&gt; to find out more.&lt;/p&gt;
&lt;h2&gt;Progressive enhancement&lt;/h2&gt;
&lt;p&gt;A lot of people worry about web components and progressive enhancement.
But, the way I see it, this &lt;strong&gt;is&lt;/strong&gt; a progressive enhancement.
We have a website that works great without web components.
If you&apos;re using a browser that can run them, you get a nice notification.
If you&apos;re not, you simply don&apos;t get the notification.
No harm done.
This is a textbook progressive enhancement.
&lt;a href=&quot;http://adactio.com&quot;&gt;Jeremy&lt;/a&gt; would be proud.&lt;/p&gt;
&lt;h2&gt;Playing with Polymer&lt;/h2&gt;
&lt;p&gt;Want to have a play about with some polymer elements yourself? Take a look at the &lt;a href=&quot;https://elements.polymer-project.org/&quot;&gt;Polymer element catalogue&lt;/a&gt; and start pulling something together.
If it&apos;s not for a production app and you don&apos;t want all the hassle that goes with bower, then take a look at &lt;a href=&quot;https://polygit.org/&quot;&gt;polygit&lt;/a&gt;.
Just don&apos;t use polygit for production.
You have been warned.&lt;/p&gt;
</content:encoded></item><item><title>Changing Lanes</title><link>https://sam.beckham.io/wrote/changing-lanes/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/changing-lanes/</guid><description>Throughout my professional career I’ve worked for agencies. I’ve been an employee, a contractor, and a freelancer. But always for an agency.</description><pubDate>Wed, 01 Jun 2016 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Throughout my professional career I’ve worked for agencies.
I’ve been an employee, a contractor, and a freelancer.
But always for an agency.&lt;/p&gt;
&lt;p&gt;I’ve always felt like I’m doing someone else’s work.
There’s a, “Push it out the door” feeling with agency work.
It’s hard to have a sense of ownership and pride over what you do at an agency.
It’s always someone else’s baby, you’re just the nanny.&lt;/p&gt;
&lt;p&gt;What these projects usually lacked, was retrospect.
It was rare that I got to look at a project I’d shipped and think, “How can I improve this?”.
As a result, we skimmed over some important things.
Performance optimisation, extensive testing, documentation, etc.
It’s not that they weren’t there, they were just underdeveloped.
In an ideal world, I could take it upon myself to look into these things, but in reality there wasn’t the budget.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;So, almost a decade down the line, it’s time to move on.
It’s time to move away from the agency model.
It’s time to stop throwing things over the wall and forgetting about them.
It’s time to move onto a different chapter and start looking at making stuff I can be proud of again.&lt;/p&gt;
&lt;p&gt;Now I am a front end engineer at &lt;a href=&quot;https://www.bytemark.co.uk/&quot;&gt;Bytemark&lt;/a&gt;.
I am part of a team that will allow me to continually improve upon the Bytemark suite.
I can look at performance.
I can look at code readability.
I can look at better testing.
I can start fine-tuning everything I do.
I’m excited about this new move; and look forward to creating awesome things, with an &lt;a href=&quot;https://www.bytemark.co.uk/company/team/&quot;&gt;awesome bunch of people&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item><item><title>Automation</title><link>https://sam.beckham.io/wrote/automation/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/automation/</guid><description>For years I’ve been fascinated by automation. Why waste time doing menial tasks when you can program a machine to do them for you?</description><pubDate>Fri, 02 Oct 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;For years I’ve been fascinated by automation. Why waste time doing menial tasks when you can program a machine to do them for you?&lt;/p&gt;
&lt;p&gt;My love for automation began, not with code, but with factory machinery. I would spend hours watching, &apos;How it’s made&apos; on the Discovery Channel. In awe of machines crafting everyday items that are often taken for granted. Things like, &lt;a href=&quot;https://www.youtube.com/watch?v=omLKbKakDoY&quot;&gt;springs&lt;/a&gt;, &lt;a href=&quot;https://www.youtube.com/watch?v=p9HFmle54eQ&quot;&gt;toothbrushes&lt;/a&gt; or &lt;a href=&quot;https://www.youtube.com/watch?v=75bfUmqx82s&quot;&gt;pasta&lt;/a&gt;. I loved how, by running a series of simple tasks, complex objects could be created with ease. Now I port the same principals into my development workflow.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/automation/crayons.gif&quot; alt=&quot;Crayons being wrapped by machinery&quot;&gt;&lt;/p&gt;
&lt;p&gt;I automate everything I can; the creation of projects with &lt;a href=&quot;http://yeoman.io/&quot;&gt;yeoman&lt;/a&gt;, deploying websites with &lt;a href=&quot;http://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks&quot;&gt;git hooks&lt;/a&gt;, even the &lt;a href=&quot;https://gist.github.com/brandonb927/3195465&quot;&gt;setup&lt;/a&gt; of my Mac. Anything I’m going to do more than a few times, I automate.&lt;/p&gt;
&lt;p&gt;Let’s take this website as an example. The first thing I automated was the cloning my Jekyll boilerplate with Yeoman, adding &lt;a href=&quot;http://nvie.com/posts/a-successful-git-branching-model/&quot;&gt;git-flow&lt;/a&gt; in the process. This includes a handful of grunt tasks that; compile and &lt;a href=&quot;https://github.com/nDmitry/grunt-autoprefixer&quot;&gt;auto-prefix&lt;/a&gt; my (s)css, &lt;a href=&quot;https://github.com/FWeinb/grunt-svgstore&quot;&gt;sprite my SVGs&lt;/a&gt;, &lt;a href=&quot;https://github.com/stephenmathieson/grunt-jslint&quot;&gt;lint&lt;/a&gt; my javascript, compile my blog with &lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt;, run a local development server, and &lt;a href=&quot;https://github.com/gruntjs/grunt-contrib-watch&quot;&gt;watch&lt;/a&gt; that server for changes. This allows me to develop the site without having to worry about running all these tasks myself. I just type grunt in the command line and it all gets taken care of. It even reloads the page for me across any devices that are currently on the site.&lt;/p&gt;
&lt;p&gt;When I’m ready to deploy, I start a release branch on git flow, run &lt;code&gt;grunt build&lt;/code&gt; (which minifies, compresses and optimises the site) then push everything up to the repo. I have a deploy script running on my server that picks up that release and pulls the repo down automatically. I don’t even need to SSH into my server. I just push to my repo and my code takes care of the rest.&lt;/p&gt;
&lt;p&gt;Using this type of automation not only saves time, but eliminates a lot of mistakes. When I automate things I put tests in place for that help me catch any errors before they go anywhere near production.&lt;/p&gt;
&lt;p&gt;Give a man a fish and he’ll eat for a day; teach a man to fish and he’ll eat for a lifetime; automate the fishing process and you’ll feed the world.&lt;/p&gt;
</content:encoded></item><item><title>Public Speaking is Scary</title><link>https://sam.beckham.io/wrote/public-speaking-is-scary/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/public-speaking-is-scary/</guid><description>Alongside spiders, heights, and clowns; public speaking is one of the most common fears.</description><pubDate>Fri, 02 Oct 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Alongside spiders, heights, and clowns; public speaking is one of the most common fears. The official term for it is &lt;a href=&quot;http://www.fearof.net/fear-of-public-speaking-phobia-glossophobia/&quot;&gt;Glossophobia&lt;/a&gt;, and it’s ranked as the 13th most common fear in the world. Which is even worse news if you’re &lt;a href=&quot;http://www.fearof.net/fear-of-the-number-13-phobia-triskaidekaphobia/&quot; title=&quot;Fear of The Number 13 Phobia – Triskaidekaphobia&quot;&gt;triskaidekaphobic&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This fear is one that I share myself. I am petrified of public speaking. The idea of standing up in a room full of my peers and sharing my thoughts, terrifies me. At least, it used to.&lt;/p&gt;
&lt;p&gt;At the beginning of 2015 I decided to face my fears. I wrote a talk proposal and sent it off to any and every event that would take it. I heard nothing but rejections for months. Then — in April — I was invited to give my talk at Scotland JS. I couldn’t believe it. Someone actually wanted to hear what I had to say. I was still nervous. But I consoled myself with the idea that it was only going to be in front of a handful of JS developers. Scotland JS sounded like the perfect little meet up to cut my public speaking teeth on. Unfortunately I had myself confused with &lt;a href=&quot;http://edinburghjs.org/&quot;&gt;Edinburgh JS&lt;/a&gt;. &lt;a href=&quot;http://scotlandjs.com/&quot;&gt;Scotland JS&lt;/a&gt; was not a small meet up. It was a two day conference. With over 300 attendees. Fuck.&lt;/p&gt;
&lt;p&gt;But I’m not a quitter. I came close to telling them that I’d made a huge mistake and I had no idea what I was doing. But I wanted to be speaking at conferences eventually, why not jump in the deep end and see what happens?&lt;/p&gt;
&lt;h3&gt;Writing the talk&lt;/h3&gt;
&lt;p&gt;I spent the next few weeks researching. Not only the topic of my talk, but public speaking in general. I did an &lt;a href=&quot;https://www.edx.org/course/introduction-public-speaking-uwashingtonx-comm220x2&quot;&gt;introduction to public speaking&lt;/a&gt; course on edX. I followed &lt;a href=&quot;http://zachholman.com/&quot;&gt;Zach Holman&lt;/a&gt;’s brilliant series of posts and videos on &lt;a href=&quot;http://speaking.io&quot;&gt;Speaking.io&lt;/a&gt;. I watched endless hours of my favourite speakers, taking notes on their styles and techniques. I wanted to be ready. I wanted to be more prepared than anyone had ever been for anything.&lt;/p&gt;
&lt;p&gt;It was roughly a week till the conference and I felt good. I’d gathered enough knowledge to feel I could really take a run at this and come through on top. The only thing left to do now was write the actual presentation. I had the outline, I knew what I wanted to say. I just needed the slides. So I opened up Keynote and got to work. Six hours later and I had finished. The title slide. This was going to be harder than I thought.&lt;/p&gt;
&lt;p&gt;I slept on it and asked around the next day for advice. It was around this time I stumbled across &lt;a href=&quot;http://www.slides.com&quot;&gt;Slides&lt;/a&gt;. I had no idea Keynote was so bad till I started using Slides. I set up some templates, ported over some key phrases from my outline, and had a basic slide deck in a couple of hours. It used HTML, CSS and Javascript to create the presentation. As a front end developer, I felt right at home.&lt;/p&gt;
&lt;p&gt;I also made the decision to avoid live coding entirely. Live coding is the soufflé of the developer world. Unless you’re a grand-master, don’t even try it. If something’s going to go wrong with your talk, it’s &lt;a href=&quot;http://speaking.io/prep/live-demos/&quot;&gt;live coding&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A short while later my slides were done. I’d injected a little humour, sprinkled in some gifs, and managed to avoid live coding. All I had left to do was practice. I recommend getting &lt;a href=&quot;http://www.telestream.net/screenflow/overview.htm&quot;&gt;screen flow&lt;/a&gt; and recording yourself running through your talk. It’s a little unnerving at first but it really helps you see how you come across to your audience. It’s also a lot easier to see if anything is confusing or falls a little flat when you watch it back. I found this to be an invaluable step in the whole process.&lt;/p&gt;
&lt;h3&gt;Game day&lt;/h3&gt;
&lt;p&gt;Let’s skip ahead to the day of the talk. As I walked in to the event, another fear of mine struck me; being in a room full of people I didn’t know. I stood nervously next to the biscuits, with a coffee in one hand and my phone in the other. I was doing that thing where you pretend to be texting. But really you’re just scrolling through your phone settings, trying to look busy. Then Peter (the event organiser) came up to introduce himself. He got me set up on stage, introduced me to the event team, and really settled my nerves. Cheers Peter, you’re a top bloke.&lt;/p&gt;
&lt;h3&gt;Here goes nothing…&lt;/h3&gt;
&lt;p&gt;It’s time. I’m set up at the side of the stage. 300 faces are staring back at me. The compare introduces me and I walk on to applause. I take a sip of water and begin, “Hello, my name is Sam Beckham and I’m here to talk about Polymer. ”&lt;/p&gt;
&lt;p&gt;All my practicing had paid off. It felt like being back behind my drum kit in my gigging days. Going through the pre-rehearsed motions, knowing exactly what was coming and what I had to do. It didn’t matter whether there were 300 people or 3, 000 people. I just gave them the same performance I gave my webcam in the practice runs. I was facing my fear and loving every minute of it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;I’d like to thank the organisers of&lt;/em&gt; &lt;a href=&quot;http://scotlandjs.com&quot;&gt;&lt;em&gt;Scotland JS&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for giving me a chance to overcome my fear. They put on a wonderful conference and made me feel welcomed in Edinburgh. You can see all the talks from the event on&lt;/em&gt; &lt;a href=&quot;https://www.youtube.com/channel/UCpW0Vh7QKPA7n0oJfrizlsw&quot;&gt;&lt;em&gt;Youtube&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you want to get into public speaking yourself. Have a look on&lt;/em&gt; &lt;a href=&quot;http://speaking.io.&quot;&gt;_speaking.io. _&lt;/a&gt; &lt;em&gt;There’s some awesome resources, tips and ideas on there to get you started. If you’re looking for somewhere to speak, have a look on Lanyard’s&lt;/em&gt; &lt;a href=&quot;http://lanyrd.com/&quot;&gt;&lt;em&gt;call for speakers&lt;/em&gt;&lt;/a&gt; &lt;em&gt;page. I also run an event in Newcastle called&lt;/em&gt; &lt;a href=&quot;https://frontendne.co.uk&quot;&gt;&lt;em&gt;Frontend NE&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. We’re always looking for people to share their experiences. Please,&lt;/em&gt; &lt;a href=&quot;https://frontendne.typeform.com/to/BgAKni&quot;&gt;&lt;em&gt;submit a proposal&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and overcome your fear. It’s not that scary once you’re up there.&lt;/em&gt;&lt;/p&gt;
</content:encoded></item><item><title>CSS Parallax Effect</title><link>https://sam.beckham.io/wrote/css-parallax-effect/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/css-parallax-effect/</guid><description>I recently discovered that one of my pens on CodePen is one of the most hearted pens of 2014. I&apos;m stunned.</description><pubDate>Tue, 17 Feb 2015 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I recently discovered that one of my pens on CodePen is one of the &lt;a href=&quot;http://codepen.io/2014/popular/10/&quot;&gt;most hearted pens of 2014&lt;/a&gt;. I&apos;m stunned.&lt;/p&gt;
&lt;p&gt;This is the pen in question: &lt;a href=&quot;http://codepen.io/samdbeckham/pen/OPXPNp&quot;&gt;Firewatch parallax in CSS&lt;/a&gt;. Scroll inside the pen to see the effect.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Full disclosure:&lt;/strong&gt; I did not design or illustrate any of this.
If you haven&apos;t seen it already, this is a remake of the beautifully illustrated &lt;a href=&quot;&quot;&gt;Firewatch&lt;/a&gt; website.
I wanted to see if I could do parallax with just CSS and this is the best designed parallax effect I’ve seen on a website.&lt;/p&gt;
&lt;h2&gt;How it works&lt;/h2&gt;
&lt;p&gt;Parallax gets mis-labelled a lot in web design.
Often, anything that moves as you scroll through a site gets called parallax.
But that&apos;s not what it means.
It&apos;s an effect that you probably see every day in the real-world and, when used correctly, can add a nice sense of depth to a website.
The definition of parallax is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The effect whereby the position or direction of an object appears to differ when viewed from different positions, e. g. through the viewfinder and the lens of a camera.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This gif by &lt;a href=&quot;http://trentwalton.com/2013/01/20/parallax-scrolling-on-the-web/&quot;&gt;Trent Walton&lt;/a&gt;, illustrates the effect quite well.&lt;/p&gt;
&lt;p&gt;&amp;lt;!-- &lt;img src=&quot;@/assets/images/articles/firewatch/parallax.gif&quot; alt=&quot;Trent Walton&apos;s real-life parallax example&quot;&gt; --&amp;gt;&lt;/p&gt;
&lt;p&gt;In my pen, I used CSS3d transforms to give the scene some depth.
When combined with some perspective you can get some really nice results.&lt;/p&gt;
&lt;h2&gt;How it&apos;s made&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;The pen has six layers, but for clarity we&apos;ll run through an example with three.&lt;/em&gt;
We start off with our wrapper, or stage. Inside that stage we have our layers, one element for each.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;div class=&amp;quot;parallax__stage&amp;quot;&amp;gt;
  &amp;lt;div class=&amp;quot;parallax__layer parallax__layer--0&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;parallax__layer parallax__layer--1&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;div class=&amp;quot;parallax__layer parallax__layer--2&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&apos;s essentially it for the HTML.
We could add images inside them divs, but we&apos;ll keep it simple.
Now, on to the CSS.&lt;/p&gt;
&lt;p&gt;We want the stage to fill the viewport and we want each layer to be the same size as the frame.
That&apos;s pretty easy.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scss&quot;&gt;.parallax__stage {
  height: 100vh;
  left: 0;
  overflow: auto;
  position: absolute;
  top: 0;
  width: 100%;
}

.parallax__layer {
  bottom: 0;
  height: 100%;
  left: 0;
  position: absolute;
  right: 0;
  top: 0;
  width: 100%;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that we&apos;ve set the stage, we need to add our (p)layers.
This is where the math comes in to play.
We could use standard CSS here, but mixins make it much easier and extendable.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scss&quot;&gt;$parallax__layers: 3;
$parallax__amount: 1;

@for $i from 0 through $parallax__layers {
  $distance: -$parallax__amount * ($parallax__layers - $i);
  .parallax__layer--#{$i} {
    background-color: rgba(0, 0, 0, (1 + $i) / 10);
    transform: translateZ($distance#{px});
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This mixin loops through each modifier and pushes it back in the z-axis.
The &lt;code&gt;$distance&lt;/code&gt; variable determines the distance each layer goes back.
I&apos;ve also modified the color on each one so we can see them clearer later.&lt;/p&gt;
&lt;p&gt;If all you can see at the moment is a screen full of gray nothing; don&apos;t adjust your set, that&apos;s what we&apos;re expecting to see.
Let&apos;s add a little perspective.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scss&quot;&gt;.parallax__stage {
  perspective: 1;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And there it is, 100% CSS parallax.
Well, not quite.
You won&apos;t be able to scroll yet because there&apos;s nowhere to scroll to.
Just add in an element below the stage and give it the following properties.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scss&quot;&gt;.content {
  background: rgba(0, 0, 0, 0.8);
  margin-top: 100vh;
  min-height: 100vh; // to make up for the lack of content
  position: relative;
  width: 100%;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can scroll away and get all that parallax loveliness.&lt;/p&gt;
&lt;p&gt;I&apos;ve made &lt;a href=&quot;http://codepen.io/samdbeckham/pen/WbaPBQ&quot;&gt;a pen of this example&lt;/a&gt; so you can play about, fork it and create your own version.
I really do like CodePen.&lt;/p&gt;
&lt;h2&gt;Differences&lt;/h2&gt;
&lt;p&gt;There are a few differences with the example and the Firewatch pen.
Mainly, the Firewatch images I used were all the same size so I had to do some maths trickery to scale them back up.
It&apos;s just an modification of the mixin we used to push them back in the z-axis.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-scss&quot;&gt;@for $i from 0 through $parallax__layers {
  $distance: ($parallax__layers - $i) / 2;
  .parallax__layer--#{$i} {
    transform: translateZ(-100 * $distance#{px}) scale($distance + 1);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also did some re-positioning of the images, and placed a cover over the top, to stop the elements peeking through each other.
It&apos;s all pretty straight forward though, and you can look at all the code on the pen, so I&apos;ll leave that as an excersise to the reader.&lt;/p&gt;
</content:encoded></item><item><title>Don&apos;t fear the command line</title><link>https://sam.beckham.io/wrote/dont-fear-the-command-line/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/dont-fear-the-command-line/</guid><description>The command line is a very powerful ally. </description><pubDate>Sun, 02 Mar 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every developer fears the command line at first. It’s bleak, un-familiar and has the power to erase your entire hard drive with a &lt;a href=&quot;http://youtu.be/8dhp_20j0Ys&quot;&gt;few mis-placed keystrokes&lt;/a&gt;. I myself felt the same way until a year or two ago, until I dove in head-first. With a little &lt;a href=&quot;https://twitter.com/jamiecurle&quot;&gt;help&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/anthonysterling&quot;&gt;guidance&lt;/a&gt;, my day-to-day now looks like a scene from the Matrix; and I’m completely comfortable with that.&lt;/p&gt;
&lt;p&gt;Over the years, I’ve integrated it more and more into my workflow. I use it for committing code with &lt;a href=&quot;http://git-scm.com/&quot;&gt;git&lt;/a&gt;; I use it to compile, minify and test my code with &lt;a href=&quot;http://gruntjs.com/&quot;&gt;grunt&lt;/a&gt;; I use it to set up my server; I even use it to &lt;a href=&quot;https://github.com/caskroom/homebrew-cask&quot;&gt;install my applications&lt;/a&gt;. I’m trying to transition into using VIM as my go-to editor, but Sublime text is just far too lovely so I’m sticking with that for now.&lt;/p&gt;
&lt;p&gt;This isn’t a how-to, there are already plenty of them around. It’s just a gentle nudge to tell you that the command line isn’t as scary as you might think. Once you get used to the power the command line gives you, you’ll wonder how you ever developed without it. Don’t fear the unknown, embrace it.&lt;/p&gt;
&lt;h2&gt;Useful links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;A great getting started guide from the folks at Treehouse &lt;a href=&quot;http://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line&quot;&gt;Introduction to the command line&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A Fun way to learn VIM - &lt;a href=&quot;http://vim-adventures.com/&quot;&gt;VIM adventures&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;A hands-on workshop from the brilliant Harry Roberts - &lt;a href=&quot;http://2014.industryconf.com/workshops/#harry&quot;&gt;The command line for beginners&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Like buzzfeed, if it were for nerds - &lt;a href=&quot;http://computers.tutsplus.com/tutorials/40-terminal-tips-and-tricks-you-never-thought-you-needed--mac-51192&quot;&gt;40 terminal tips and tricks…&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Generated Backgrounds With SVG</title><link>https://sam.beckham.io/wrote/generated-backgrounds-with-svg/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/generated-backgrounds-with-svg/</guid><description>“Playing with maths, geometry and Base64 encoded SVGs”</description><pubDate>Wed, 15 Jan 2014 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Just before Christmas I decided to have a play about with SVG on Codepen. It got quite a lot of attention and I was asked to write a post detailing the process; here is that post.&lt;/p&gt;
&lt;p&gt;This idea was born because I needed a way to generate isometric backgrounds on-the-fly with a set colour palette. I decided the best way to do it would be to use a formula that would write some SVG code and apply it to the background of an element. The problem was, I’d never used SVG before and &lt;a href=&quot;http://i.imgur.com/EiVhZ.gif&quot;&gt;I had no idea what I was doing&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Polka dots&lt;/h2&gt;
&lt;p&gt;I decided to start small and get the basics down first. If I could get something simple generated in SVG first then I could move onto writing the formula that would generate my shapes. I created a &lt;a href=&quot;http://codepen.io/sambeckham/pen/ouvGg&quot;&gt;random polka dot generator&lt;/a&gt; that was surprisingly simple.&lt;/p&gt;
&lt;p&gt;I&apos;ve outlined a - simplified - breakdown of that code below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var width = (dotSize + dotPadding) * dotsWide,
  height = (dotSize + dotPadding) * dotsHigh,
  radius = dotSize / 2,
  background =
    &amp;quot;&amp;lt;svg xmlns=&apos;http://www.w3.org/2000/svg&apos; width=&apos;&amp;quot; +
    width +
    &amp;quot;&apos; height=&apos;&amp;quot; +
    height +
    &amp;quot;&apos;&amp;gt;&amp;quot;,
  color = &amp;quot;#09c&amp;quot;,
  x,
  y;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;First I define the variables I’m going to use and generate the opening tag for the SVG (assigned to the background variable).&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;for (x = radius; x &amp;lt; width; x += dotSize + dotPadding) {
  for (y = radius; y &amp;lt; height; y += dotSize + dotPadding) {
    background +=
      &amp;quot;&amp;lt;circle fill=&apos;&amp;quot; +
      color +
      &amp;quot;&apos; cx=&apos;&amp;quot; +
      x +
      &amp;quot;&apos; cy=&apos;&amp;quot; +
      y +
      &amp;quot;&apos; r=&apos;&amp;quot; +
      radius +
      &amp;quot;&apos;/&amp;gt;&amp;quot;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then I loop through each circle/dot in the image and append the SVG code to generate it to the background variable.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;background += &amp;quot;&amp;lt;/svg&amp;gt;&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once each dot has been added, we close the SVG tag.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var b64 = &amp;quot;data:image/svg+xml;base64,&amp;quot; + window.btoa(background),
  url = &apos;url(&amp;quot;&apos; + b64 + &apos;&amp;quot;)&apos;;
$(&amp;quot;html&amp;quot;).css(&amp;quot;backgroundImage&amp;quot;, url);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally I base64 encode the image before applying it to the background as a &lt;a href=&quot;http://css-tricks.com/data-uris/&quot;&gt;Data URI&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Isometric grid&lt;/h2&gt;
&lt;p&gt;The polka dot demo proved to me that I could do this. All I had to do now was write the part that generated my isometric triangles. There’s a few ways to do this but I found this way to be the simplest.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;@/assets/images/articles/svg/concept.jpg&quot; alt=&quot;concept drawing&quot;&gt;&lt;/p&gt;
&lt;p&gt;My plan was to generate this bow-tie shape and fill it with a random colour, chosen from a pre-defined array. I would then repeat this shape so it tessellates. The problem I encountered with this approach is that they didn&apos;t stack correctly, and I had with a line of diamond-shaped gaps.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;for (i = 0; i &amp;lt;= settings.trianglesWide; i += 1) {
  for (j = 0; j &amp;lt;= settings.trianglesHigh; j += 1) {
    v = i * settings.triangleSize * settings.skew;
    w = j * settings.triangleSize;
    x = v + settings.triangleSize * settings.skew;
    y = w + settings.triangleSize;
    a = v + &amp;quot;,&amp;quot; + w;
    b = x + &amp;quot;,&amp;quot; + w;
    c = (v + x) / 2 + &amp;quot;,&amp;quot; + (w + y) / 2;
    d = v + &amp;quot;,&amp;quot; + y;
    e = x + &amp;quot;,&amp;quot; + y;

    background +=
      &amp;quot;&amp;lt;polygon fill=&apos;&amp;quot; +
      getColor() +
      &amp;quot;&apos; fill-opacity=&apos;&amp;quot; +
      settings.opacity +
      &amp;quot;&apos; points=&apos;&amp;quot; +
      a +
      &amp;quot; &amp;quot; +
      c +
      &amp;quot; &amp;quot; +
      d +
      &amp;quot; &amp;quot; +
      &amp;quot;&apos; /&amp;gt;&amp;quot;;
    background +=
      &amp;quot;&amp;lt;polygon fill=&apos;&amp;quot; +
      getColor() +
      &amp;quot;&apos; fill-opacity=&apos;&amp;quot; +
      settings.opacity +
      &amp;quot;&apos; points=&apos;&amp;quot; +
      b +
      &amp;quot; &amp;quot; +
      c +
      &amp;quot; &amp;quot; +
      e +
      &amp;quot; &amp;quot; +
      &amp;quot;&apos; /&amp;gt;&amp;quot;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Gives you…&lt;/p&gt;
&lt;p&gt;&amp;lt;div style=&amp;quot;background-image:url(&apos;/images/articles/svg/failed-attempt.png&apos;); background-position:center; height:250px; margin-bottom:0. 618033em&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p&gt;As you can see, the bow-ties don’t line up quite right but this is fixable. What we need to do is offset every second row by moving it up and along by 50%. I decided to utilise the &lt;a href=&quot;http://en.wikipedia.org/wiki/Modulo_operation&quot;&gt;modulo operation&lt;/a&gt; &lt;code&gt;(j % 1)&lt;/code&gt; to differentiate between even and odd rows. This operation will return a 0 when the number is even and a 1 when it’s odd.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;for (i = -1; i &amp;lt;= trianglesWide; i += 1) {
  for (j = -0.5; j &amp;lt;= trianglesHigh; j += 0.5) {
    v = (i + (j % 1)) * triangleSize * skew;
    w = j * triangleSize;
    x = v + triangleSize * skew;
    y = w + triangleSize;
    a = v + &amp;quot;,&amp;quot; + w;
    b = x + &amp;quot;,&amp;quot; + w;
    c = (v + x) / 2 + &amp;quot;,&amp;quot; + (w + y) / 2;
    d = v + &amp;quot;,&amp;quot; + y;
    e = x + &amp;quot;,&amp;quot; + y;

    background +=
      &amp;quot;&amp;lt;polygon fill=&apos;&amp;quot; +
      getColor() +
      &amp;quot;&apos; fill-opacity=&apos;&amp;quot; +
      opacity +
      &amp;quot;&apos; points=&apos;&amp;quot; +
      a +
      &amp;quot; &amp;quot; +
      c +
      &amp;quot; &amp;quot; +
      d +
      &amp;quot; &amp;quot; +
      &amp;quot;&apos; /&amp;gt;&amp;quot;;
    background +=
      &amp;quot;&amp;lt;polygon fill=&apos;&amp;quot; +
      getColor() +
      &amp;quot;&apos; fill-opacity=&apos;&amp;quot; +
      opacity +
      &amp;quot;&apos; points=&apos;&amp;quot; +
      b +
      &amp;quot; &amp;quot; +
      c +
      &amp;quot; &amp;quot; +
      e +
      &amp;quot; &amp;quot; +
      &amp;quot;&apos; /&amp;gt;&amp;quot;;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Adding this in allows us to offset the &lt;code&gt;v&lt;/code&gt; coordinate by 1 on every second row which pushes that row along to the correct point.&lt;/p&gt;
&lt;p&gt;You might notice that instead of starting the for loops at 0 I start them at −1 and −0. 5 respectively. This is to make sure the pattern starts outside the bounding box so we don’t get jagged edges.&lt;/p&gt;
&lt;h2&gt;Colours&lt;/h2&gt;
&lt;p&gt;Another big part of what I wanted to do here was to use random colours from a selected palette. To do this I wrote a simple &lt;code&gt;getColor()&lt;/code&gt; function.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;var colors = [&amp;quot;red&amp;quot;, &amp;quot;blue&amp;quot;, &amp;quot;green&amp;quot;],
  getColor = function() {
    var hex = colors[Math.floor(Math.random() * colors.length)];
    return hex;
  };
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This shouldn’t need too much of an explanation, it returns a random entry from the colours array when it’s called.&lt;/p&gt;
&lt;h2&gt;Plugin&lt;/h2&gt;
&lt;p&gt;Whilst this is not intended to be a jQuery plugin, I wrote it in that manner to allow me to generate several different backgrounds. Have a play about with the settings at the &lt;a href=&quot;#top&quot;&gt;top of the page&lt;/a&gt; or check out the demo on &lt;a href=&quot;http://codepen.io/sambeckham/pen/FCGrx&quot;&gt;Codepen&lt;/a&gt; to see just how versatile this can be.&lt;/p&gt;
</content:encoded></item><item><title>Public APIs</title><link>https://sam.beckham.io/wrote/public-apis/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/public-apis/</guid><description>Millions of people share their photos, thoughts and data online - and now we can access it easily with public APIs. </description><pubDate>Wed, 20 Mar 2013 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Millions of people share their photos, thoughts and data online - and now we can access it easily with public APIs.&lt;/p&gt;
&lt;h2&gt;A brief introduction&lt;/h2&gt;
&lt;p&gt;If you&apos;ve ever used a Twitter widget to display Tweets on a website - like most developers have - then you&apos;ve already used an API. An API (Application Programming Interface) is a way for programs to communicate with each other, generally using simple request and response messages.&lt;/p&gt;
&lt;p&gt;In the case of the common RESTful web API it’s as simple as sending a http response, &lt;a href=&quot;http://api.flickr.com/services/rest/?method=flickr.photos.getRecent&amp;amp;api_key=b5b0a30288a8cc21468d22e22c3255ac&amp;amp;format=rest&quot;&gt;eg&lt;/a&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://api.flickr.com/services/rest/?method=flickr.photos.getRecent&amp;amp;api_key=b5b0a30288a8cc21468d22e22c3255ac&amp;amp;format=rest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will return a JSON file that we can pull information from and use on our website or app.&lt;/p&gt;
&lt;h2&gt;4 pics 1 word&lt;/h2&gt;
&lt;p&gt;In the example at the top of this article, I have used the Instagram API to pull in four images tagged with a pre-defined keyword. That keyword then becomes the answer to the puzzle - much like the 4 pics 1 word app that&apos;s doing the rounds at the moment.&lt;/p&gt;
&lt;p&gt;This is an example of what can be achieved quite quickly with an API. You get a fully functioning app without the headache of having to source and store the data yourself. You can have a look at the code on &lt;a href=&quot;https://github.com/sambeckham/blog/blob/master/src/scripts/public-APIs.js&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;OAuth and request limits&lt;/h2&gt;
&lt;p&gt;Nothing good ever comes easy. When Twitter first launched their API in 2006 it only required basic authentication to access an unlimited amount of data. Three years later they brought in a 20, 000 requests-per-hour limit on that data and have continued to throttle it ever since. Today that limit stands at a mere 150 unauthorised requests per-hour and will very shortly need Twitter’s OAuth service to make any requests at all.&lt;/p&gt;
&lt;p&gt;OAuth is a bit of a headache at first - especially for us front end devs - but luckily there&apos;s &lt;a href=&quot;http://www.youtube.com/playlist?list=PL032A5954701D543C&quot;&gt;plenty of help&lt;/a&gt; out there to &lt;a href=&quot;http://www.webdevdoor.com/php/authenticating-twitter-feed-timeline-oauth/&quot;&gt;get you started&lt;/a&gt;. If you are writing a new app or widget that uses the Twitter API - then I suggest going straight for the OAuth approach with &lt;a href=&quot;https://dev.twitter.com/docs/api/1.1&quot;&gt;API 1. 1&lt;/a&gt; because its going to be a huge pain in the ass when the big switchover happens in June.&lt;/p&gt;
</content:encoded></item><item><title>Web Wars</title><link>https://sam.beckham.io/wrote/web-wars/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/web-wars/</guid><description>Flash is dead – long live HTML5. </description><pubDate>Fri, 04 May 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;A long time ago in a galaxy far, far away…&lt;/p&gt;
&lt;p&gt;If you wanted interactivity on a website that went beyond scrolling marquees, blinking text and hover states - you had to use Flash. However, Flash was not without its faults.&lt;/p&gt;
&lt;h2&gt;A New hope&lt;/h2&gt;
&lt;p&gt;Now there are a number of alternatives to Flash. HTML5 is the latest to step up to the plate.&lt;/p&gt;
&lt;p&gt;The HTML5 Vs Flash debate has gone on for some time now. A web search for “HTML5 vs Flash” will bring up thousands of results, some in favour of Flash and some for HTML5.&lt;/p&gt;
&lt;p&gt;A lot of people fear the arrival of HTML5, but fear is the path to the dark side. We should embrace new technologies. HTML5 has a very good community that will happily help you out. I believe sharing our knowledge is a wonderful thing and is the key to &lt;a href=&quot;http://movethewebforward.org/&quot; title=&quot;Contribute to the web&quot;&gt;moving the web forward&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course nothing is perfect - HTML5 has its faults as well. But it is still in its infancy and will continue to grow.&lt;/p&gt;
&lt;h2&gt;The Empire Strike back&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;http://www.apple.com/hotnews/thoughts-on-flash/&quot; title=&quot;Apple&apos;s thoughts on Flash&quot;&gt;April 2010&lt;/a&gt; Adobe were dealt a large blow to their battle for web supremacy, as tech giants Apple announced that their mobile operating system wouldn&apos;t support Flash and would instead favour HTML5. Since that announcement the iPhone user base has grown exponentially and the iPad - using a similar OS - has dominated the tablet market. That means a lot of people can&apos;t use Flash on-the-go.&lt;/p&gt;
&lt;p&gt;Web developers have realised this and have started to move away from Flash in favour of HTML5. Flash may still be used on around half of the world&apos;s top websites but this figure is dropping quickly.&lt;/p&gt;
&lt;h2&gt;Return of the Jedi&lt;/h2&gt;
&lt;p&gt;There are still a lot of developers that favour Flash. They know it works and it can still do a lot of things that HTML5 can&apos;t, yet.&lt;/p&gt;
&lt;p&gt;If you&apos;ve only used Flash I would suggest learning HTML5 as soon as you can, as Flash may not be around forever. As a great Jedi once said, &lt;a href=&quot;http://youtu.be/3A_uOaA3e_0#t=13m56s&quot; title=&quot;Yoda&apos;s training&quot;&gt;&amp;quot;Always in motion is the future. &amp;quot;&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>Super Mario</title><link>https://sam.beckham.io/wrote/super-mario/</link><guid isPermaLink="true">https://sam.beckham.io/wrote/super-mario/</guid><description>A brief, Nintendo-flavoured article about using the Cicada principal in CSS3. </description><pubDate>Wed, 04 Apr 2012 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I like Super Mario and I love CSS3 - so I decided to create an experiment that combined the two.&lt;/p&gt;
&lt;h2&gt;The Cicada Principle&lt;/h2&gt;
&lt;p&gt;The Cicada principle was coined by &lt;a href=&quot;http://designfestival.com/author/alex-walker/&quot; title=&quot;View Alex&apos;s Profile&quot;&gt;Alex Walker&lt;/a&gt; after being inspired by a documentary on the Cicada. I won&apos;t go into all the details as everything is covered in the &lt;a href=&quot;http://designfestival.com/the-cicada-principle-and-why-it-matters-to-web-designers/&quot; title=&quot;The Cicada Principle&quot;&gt;original article&lt;/a&gt; - which is definitely worth reading.&lt;/p&gt;
&lt;p&gt;The basis of this principle uses prime numbers - along with the new multiple backgrounds feature in CSS. By using image sizes based on prime numbers (3, 5, 7, etc) they don&apos;t repeat in sequence and create an - almost - infinitely large image.&lt;/p&gt;
&lt;p&gt;At the top of this page I have used 6 images with widths of; 16px, 208px, 272px, 304px, 368px and 496px. All of these numbers are multiples of 16 and a prime number. This creates a tiled background that&apos;s exactly 5. 023x10^13px wide.&lt;/p&gt;
&lt;p&gt;With only 33kb worth of images that&apos;s quite a feat!&lt;/p&gt;
&lt;h2&gt;Browser support&lt;/h2&gt;
&lt;p&gt;As you can tell if you&apos;re viewing this page in an older browser - the support isn&apos;t the best. This will however continue to improve.&lt;/p&gt;
&lt;p&gt;If you are having trouble viewing this page, I recommend downloading &lt;a href=&quot;http://www.google.com/chrome&quot; title=&quot;Download Google Chrome&quot;&gt;Chrome&lt;/a&gt; or &lt;a href=&quot;http://www.mozilla.org/en-US/firefox/new/&quot; title=&quot;Download Mozilla Firefox&quot;&gt;Firefox&lt;/a&gt;.&lt;/p&gt;
</content:encoded></item></channel></rss>