Mike Aparicio
Principal Design Systems Engineer at Turquoise Health. Improving collaboration between design and engineering with the power of design systems.
2024-01-01T00:00:00Z
https://mikeaparicio.com/
Mike Aparicio
peruvianidol@gmail.com
2023
2024-01-01T00:00:00Z
https://mikeaparicio.com/posts/2024-01-01-2023/
<p>I'm so ready to turn the page on 2023. While there was a lot to be grateful for this year, it was marred by loss, grief and random health struggles.</p>
<p><strong>Loss.</strong> In late 2022, our dog Geno started having swelling in his throat that became so severe he wasn't eating. The vet treated him with an injection that reduced the swelling and for a few months he was back to normal. Then in early 2023 the swelling started up again and Geno's appetite was so low that he lost a ton of weight. By March it was looking like we were going to lose him at any moment. One night I decided to go see a movie by myself, which I rarely do, and when the movie was over I checked my text messages only to learn that Geno had fallen down the stairs and died while I was gone. <a href="https://mikeaparicio.com/posts/2023-03-26-our-dear-geno/">It gutted me</a> that he died like that and, worse, that I wasn't there for him. We miss him so much.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/8caTUTLh1w-300.webp 300w, https://mikeaparicio.com/images/8caTUTLh1w-500.webp 500w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/8caTUTLh1w-300.jpeg 300w, https://mikeaparicio.com/images/8caTUTLh1w-500.jpeg 500w" sizes="100vw" /><img alt="Geno chilling on the couch." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/8caTUTLh1w-300.jpeg" width="500" height="500" /></picture>
<figcaption>
Our dear Geno.
</figcaption>
</figure>
<p>Not a month later, Allie's mom passed away after a long battle with cancer. She was so funny and gregarious. The holidays were too quiet without her. When I first met Allie, both her parents had recently been diagnosed with cancer and she was worried they wouldn't be around much longer. Some 16 years later they got to see us get married and watch their grandkids grow up. I'm grateful I got to get to know her and that she had as much time with my kids as she did. She loved them so much.</p>
<p>Later in the year Allie's uncle also passed away and my aunt was diagnosed with cancer. And just recently we had to take our dog Emily to the emergency vet because she was peeing blood. They diagnosed her with bladder stones and prescribed some medication and some special food which should hopefully help, but who knows. Allie's dad had surgery to close out the year.</p>
<p>It's been a rough year and having to explain it all to Ryan has been challenging. The biggest thing I tell him is how important it is to enjoy every moment we have with each other and let people know how much they mean to us because you never know what's going to happen. When we lose our loved ones, we keep their memory and their spirit with us always.</p>
<figure class="ma-float-left">
<video controls="">
<source src="https://mikeaparicio.com/images/ryan-sonic.mp4" type="video/mp4" />
</video>
<figcaption>
Ryan's interpretive Sonic dance.
</figcaption>
</figure>
<p><strong>Ryan.</strong> Despite everything, Ryan has been growing into a precocious little guy. It probably doesn't help that I let him watch YouTube. π³ Other parents recoil in horror when I try to explain to them what a <a href="https://knowyourmeme.com/memes/subcultures/skibidi-toilet">Skibidi Toilet</a> is.</p>
<p>Ryan's interest in gaming has broadened to include maker games like Minecraft and Super Mario Maker 2. He also got into Sonic the Hedgehog and Mario Kart. It's pretty amazing what he's able to do on his own just over a year after picking up Super Mario Bros for the first time.</p>
<p>It's been heartening to see him occasionally turn the TV off voluntarily and do some drawing or crafts. He's gotten to the point where he can write his name and all of the letters, and draws things that actually look like real world things. It's pretty wild.</p>
<p>We got to go on a lot of adventures this year and it's always such a joy to see him experience something for the first time.</p>
<p><strong>Owen.</strong> Owen is developing into his own little person. He's walking around with ease now and starting to say simple words. He's constantly babbling in his own little language. It's funny how different he is from Ryan. He's a lot more stoic than Ryan and has a voracious appetite compared to Ryan, who is much more picky unless there's sugar involved. While Ryan wants to hang out with me all the time, Owen is definitely a momma's boy, screaming any time Allie puts him down or leaves the room.</p>
<figure class="ma-float-center" style="max-width: 500px; margin-inline: auto">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/xdeAQ7JPyp-300.webp 300w, https://mikeaparicio.com/images/xdeAQ7JPyp-500.webp 500w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/xdeAQ7JPyp-300.jpeg 300w, https://mikeaparicio.com/images/xdeAQ7JPyp-500.jpeg 500w" sizes="100vw" /><img alt="Owen sitting on the floor with a soccer ball and shapes toy, smiling." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/xdeAQ7JPyp-300.jpeg" width="500" height="500" /></picture>
<figcaption>
Owen is a happy-go-lucky guy.
</figcaption>
</figure>
<p>Owen also loves to play with and torment his big brother, Ryan. It's exciting to think that a year from now he'll be talking a lot more. I can't wait to hear what he and Ryan talk about.</p>
<p><strong>Joe.</strong> My stepson, Joe, continues to grow into an adult β he'll be 20(!) in January. He's finishing up his sophomore year of junior college and looking at four-year schools where he can play baseball. I'm so proud of how far he's come in the past year.</p>
<p><strong>Mario.</strong>
In August we adopted another Boxer, who Ryan insisted we name Mario, of course. Mario is incredibly sweet, when he's not peeing and pooping in the house or <a href="https://www.instagram.com/p/C1F4uAsLQzQ/">chewing through my office door</a>. Emily has enjoyed having another dog in the house and is happy that Mario is a much more willing snuggle partner than Geno was.</p>
<p><strong>I started a new job.</strong> In early January I started a new role as Principal Design System's Engineer at <a href="https://turquoise.health/">Turquoise Health</a>. After almost a year I'm really happy that I made the move. I love the team at Turquoise. We have an eclectic bunch of talented folks that are really good at what they do but are also very down-to-earth and fun to hang out with.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/Ccz4eizE0U-300.webp 300w, https://mikeaparicio.com/images/Ccz4eizE0U-600.webp 600w, https://mikeaparicio.com/images/Ccz4eizE0U-2144.webp 2144w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/Ccz4eizE0U-300.jpeg 300w, https://mikeaparicio.com/images/Ccz4eizE0U-600.jpeg 600w, https://mikeaparicio.com/images/Ccz4eizE0U-2144.jpeg 2144w" sizes="100vw" /><img alt="An illustration of a turqouise snake." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/Ccz4eizE0U-300.jpeg" width="2144" height="1608" /></picture>
<figcaption>
Andy Carolan's Pit Viper logo.
</figcaption>
</figure>
<p>I was able to release version 1.0 of <a href="https://pitviper.turquoise.health/">Pit Viper</a>, our design system's CSS framework, relatively quickly. It's been great to see the team embrace it, build on it and quickly release new features with it. I worked with the marketing team to make a new site that <a href="https://mikeaparicio.com/posts/2023-11-07-using-wordpress-as-a-headless-CMS-for-eleventy/">uses the Wordpress API as a headless CMS with Eleventy</a>. I built my first <a href="https://codepen.io/peruvianidol/pen/mdvZjBz/195f5650fb10b1f6384fbe8d3bc2d6a9">web component</a>, which was a lot simpler than I thought it would be. I commissioned a logo for Pit Viper and <a href="https://www.andycarolan.com/">Andy Carolan</a> knocked it out of the park. I also referred my former Groupon colleague <a href="https://www.michellemartir.com/">Michelle</a> who has been absolutely crushing it on the design team.</p>
<p><strong>More Traveling!</strong>
In January I went to Los Angeles for our company summit, where I got to meet and hang with everyone at Turquoise. I also got to meet my gaming buddy, Jose, in person for the first time.</p>
<p>In July I returned to L.A. with the family and we took the boys to Universal Studios, where Ryan got to visit <a href="https://www.instagram.com/p/CuIkq0LPb9C/">Super Nintendo World</a> and <a href="https://www.instagram.com/p/CuImHC7P9XR/">see the Hogwart's Express</a> (literally the only thing he knows about Harry Potter). Next we visited one of Allie's friends in Palm Springs, where it was 116 degrees, but also found <a href="https://www.instagram.com/p/CuVxQ_NLMJ5/">one of the best Peruvian restaurants</a> I've been to in America. We finished the trip in San Diego, where we visited more friends and checked out <a href="https://www.instagram.com/p/CuaCBcEvcPK/">Legoland</a> and the San Diego Zoo. Joe was happy to catch a game at all three SoCal ballparks: The Dodgers, Angels and Padres.</p>
<p>Later that month I went to another company summit, this time in Denver. It was pretty wild to see how much the company had grown in six short months, from ~60 people to almost 100. We checked out <a href="https://meowwolf.com/visit/denver">Meow Wolf</a>, which is a really cool interactive art installation.</p>
<p>Finally, in November I went to Tampa, where my dad, stepmom and aunt traveled to from Lima to visit my other aunt. I was only there for a couple of days but I was glad to be able to reconnect with my family, even for such a short time.</p>
<p><strong>I celebrated 10 years of marriage.</strong> There's not a lot of things I've done in my life for 10 years, but <a href="https://www.instagram.com/p/C012DnLLwqj/">being married to Allie</a> is the best one. We've been through a lot but we've also shared a lot of good times and are blessed to have three wonderful boys.</p>
<p><strong>We raised $5,839 for Extra Life.</strong> This year also marked my 10th Extra Life and I was so inspired by the support we received this year. Over 10 years we've managed to raise over $44,000 for Lurie Children's Hospital in Olivia's memory. Thank you so much to everyone who generously contributed their time and money over the years.</p>
<p><strong>I weaned myself off of social media (kind of).</strong> This year saw a massive decline in my use of social media, largely thanks to the ass-clown that bought Twitter and quickly turned it into a shithole. I've tried Mastodon, Bluesky and Threads but none of them have the same vibe that made Twitter special. I met a lot of great people on Twitter and it played a huge role in growing my career. It's sad to see it wither away so quickly.</p>
<p><strong>I didn't write a book.</strong> One thing I mentioned in last year's recap that I wanted to work on this year was writing a book about CSS. Well, I didn't even start it and I'm not sure I'm going to. I've been thinking that maybe an online course would be a better way to go, but I don't know. I had a lot going on this year and was happy to just be focusing on my new job and my family.</p>
<h2>Things I loved in 2023</h2>
<h3>Movies</h3>
<p>This year I didn't do any <a href="https://letterboxd.com/peruvianidol/list/movie-a-year-challenge-2022/">movie challenges</a> but somehow managed to log more movies (150) than any other year on <a href="https://letterboxd.com/peruvianidol/">Letterboxd</a> since I started using the app in 2012. This year I revisited a lot of movies that I remember being good to see if they held up. Most of them did!</p>
<p>It was a pretty interesting year for movies. There were a lot of <em>really good</em> movies but not a ton of <strong>great</strong> ones. Here are a few that I loved.</p>
<p><strong>Past Lives</strong> It's rare that a film evokes the same feeling of melancholy as one of my favorite films of all time, <em>Eternal Sunshine of the Spotless Mind</em>. Past Lives explicitly mentions it, though I'm not sure how much it was inspired by it. It's the story of a 12-year-old girl who immigrates from South Korea to Canada and reconnects with her childhood sweetheart 12 and 24 years later. It's sublime.</p>
<p><strong>Spider-Man: Across the Spider-Verse</strong> I wasn't sure they could top the first one but <em>Across the Spider-Verse</em> expands on the concept of a multiverse in such delightful ways and further fleshes out Miles and all of the other Spider-people. This movie has so much heart and explores parenthood in a way that really resonated with me. I literally gasped out loud at least three times in the last 10 minutes when I saw this for the first time in the theater. I'm sad that this ended on a cliffhanger but it doesn't diminish everything that this film does right.</p>
<figure>
<iframe src="https://www.youtube.com/embed/Ek40XtVsO7g?si=DtYvzFCPtfLzHSOw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<figcaption>Spider-man: Across the Spider-Verse is just gorgeous.</figcaption>
</figure>
<p><strong>The Killer</strong> David Fincher returns to the stylish crime-thrillers of his early career with a slow-burn assassin movie in the vein of <em>The American</em>. Michael Fassbender is great in the title role. I'm sure some people found this boring (it basically opens with a 20-minute monologue about being an assassin) but I loved it.</p>
<p><strong>John Wick: Chapter 4</strong> I loved the first John Wick but subsequent sequels delved far too into the whole mythology of Wick's world. The hotel, the coins, the Table. I didn't find any of that particularly interesting. Even the action leaned a little to heavy on guys getting shot in the face. While there's a lot of that in <em>Chapter 4</em>, the action set pieces are so wildly inventive and ambitious, the set design so stylish, and the pacing so frenetic, that I was blown away. Solidly one of the best action movies of the 21st century.</p>
<p><strong>Mission: Impossible - Dead Reckoning Part One</strong> I watched all of the previous M:I movies leading up to this one and Dead Reckoning might be my favorite. This one felt more playful than Fallout and introduces Haley Atwell as a thief who reluctantly teams up with the IMF crew. She's faced with <strong>the choice</strong> β a throwaway line from the original series ("your mission, should you choose to accept it") β which takes on new meaning here. All of the women in this movie are just spectacularly badass. There's not really any single action set piece that tops previous entries, but it feels like there's just more of everything that makes an M:I movie great.</p>
<p><strong>Maestro</strong> I went into this one expecting a run-of-the-mill musical biopic but was pleasantly surprised to find a movie that centered on Bernstein's relationship with his wife, Felicia. Such a complicated relationship but at its heart two people who cared deeply for each other. Love the cinematography and the long, lingering takes that were subtle enough to not feel showy but brought you into moment. Cooper and Mulligan are both in top form here.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/0IHgtcLEkZ-300.webp 300w, https://mikeaparicio.com/images/0IHgtcLEkZ-600.webp 600w, https://mikeaparicio.com/images/0IHgtcLEkZ-1280.webp 1280w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/0IHgtcLEkZ-300.jpeg 300w, https://mikeaparicio.com/images/0IHgtcLEkZ-600.jpeg 600w, https://mikeaparicio.com/images/0IHgtcLEkZ-1280.jpeg 1280w" sizes="100vw" /><img alt="Bradley Cooper and Carey Mulligan in Maestro." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/0IHgtcLEkZ-300.jpeg" width="1280" height="720" /></picture>
<figcaption>
Bradley Cooper and Carey Mulligan in Maestro.
</figcaption>
</figure>
<p><strong>The Creator</strong> Doesn't do anything groundbreaking with its narrative but it filled with such ambitious ideas and imagery. It seems like this one got mixed reviews but the central relationship between John David Washington's Joshua and young Madeline Yuna Voyles' Alphie really got to me.</p>
<p><strong>Sancutary</strong> I don't want to say too much about this film other than that it's the horniest movie I saw all year. It's basically a two-hander that takes place in a hotel room with two actors I find incredibly compelling, Margaret Qualley and Christopher Abbott.</p>
<p><strong>Others worth mentioning:</strong> I didn't see it in 2022 but <strong>Babylon</strong> is such a wildly-paced, drug-induced fever dream that is uproariously funny. As the central characters fortunes begin to shift, it does lose steam, but the first two hours are quite a ride. <strong>The Holdovers</strong> is a great throwback and sure to be a new holiday favorite. Sharp writing and strong performances from Paul Giamatti and his two co-stars. <strong>Leave the World Behind</strong> features a great ensemble cast and perfectly captures all of the anxiety of the moment around technology and our polarized political climate. Also makes a strong case for physical media. I absolutely loathed the first film but <strong>Extraction 2</strong> delivers some of the best action of the year. Chris Hemsworth is great. <strong>Fair Play</strong> was not among the best films I saw this year, but it certainly was memorable and would make a great double feature with <em>Sanctuary</em> and/or <em>Anatomy of a Fall</em>.</p>
<h3>TV</h3>
<p>There was such a wealth of great television this year. A lot of great debuts and shows wrapping up successful runs. Here are some of my favorites.</p>
<p><strong>The Bear (Hulu/FX)</strong> While season 1 of The Bear felt perfectly engineered especially for me, the second season surpasses it in every way. I was a little nervous about the show (and the titular restaurant) pivoting from a beef joint to a pretentious, Michelin-rated spot, but the way it explores its characters and goes hard on the dramatic tension. The Christmas episode is filled with incredible guests and matches or surpasses the intensity of S1's best episode, while "Forks" features such a great transformation by Ebon Moss-Bachrach's cousin Richie. Two of the best episodes of television all year in a single season of a show is impressive.</p>
<p><strong>I Think You Should Leave with Tim Robinson (Netflix)</strong> Holy shit, this show is so uproariously funny. Despite the short, 15-minute episodes, every season of I Think You Should Leave is packed with meme-worthy sketches. This season's most memorable sketch involved a guy <a href="https://youtube.com/shorts/Oa8s07agHeY?si=x3Bls9ersYnrdRFh">paying it forward</a> in a fast food drive-thru.</p>
<p><strong>Succession (MAX, the one to watch for HBO)</strong> I was never compelled to get into a show about rich white people problems but I finally relented in the build-up to the final season and was not disappointed. Yes, the Roy family has rich white people problems, but the joy of the show comes from watching them fuck themselves and each other over at every turn. I watched all four seasons and the finale was masterful. If you had any reservations about this show, I'd encourage you to put them aside and check it out. Easily one of the best written and acted shows of the past decade.</p>
<p><strong>The Last of Us (MAX, the one to watch for HBO)</strong> I was a little nervous about this one as video game adaptations don't have a great track record thus far. The Last of Us is one of the best stories of all time, video game or otherwise. I was heartened that the show would be helmed by Craig Mazin, who worked on Chernobyl, and Neil Druckmann, the creative director of the original game. Pedro Pascal and Bella Ramsey are perfectly cast as Joel and Ellie and the show matches the heights of the game's narrative without getting too video gamey. It also builds on the story and its characters, delivering an amazing flashback episode with Nick Offerman's Bill and Murray Bartlett's Frank β a character that is only mentioned in passing in the game. My wife, who is not at all into video games, was completely drawn in. I can't wait to see how they handle the polarizing sequel.</p>
<figure>
<iframe src="https://www.youtube.com/embed/uLtkt8BonwM?si=LqR0zvJM4PEtxZ_G" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<figcaption>The Last of Us perfectly captures the spirit of the video game.</figcaption>
</figure>
<p><strong>Silo (Apple TV+)</strong> Based on a series of books by Hugh Howey, Silo is a dystopian drama that takes place in an underground silo built to protect its residents from an unknown catastrophe that made the world above uninhabitable. Rebecca Ferguson plays an engineer who is suddenly thrust into the role of sheriff when a series of deaths occur and she's faced with unraveling what seems to be a conspiracy. It's pretty compelling β I love a good dystopian thriller. It feels like a sci-fi noir story.</p>
<p><strong>Winning Time: The Rise of the Lakers Dynasty (MAX, the one to watch for HBO)</strong> Pretty much every NBA player featured in this series disputes its accuracy, but the drama is great and the ensemble cast is terrific. John C. Reilly plays Dr. Jerry Buss, who bought the Lakers the year they drafted Magic Johnson. Season 2 follows Pat Riley (played by Adrian Brody) and his ascension to head coach. The whole cast is great. The guys they found to play Magic, Kareem and Larry Bird are pretty convincing (and Norm Nixon is played by his actual son, DeVaughn). The show was ultimately cancelled but I had a lot of fun with it.</p>
<p><strong>Picard S3/Strange New Worlds (Paramount+)</strong> I love that Star Trek is still banging out great shows. I couldn't get into the first two seasons of Picard but season 3 serves as a Next Generation reunion and it's a ton of fun. I don't think you need to have seen the previous seasons to fully enjoy it as it pretty much stands on its own. Strange New Worlds captures the humor and spirit of the original series and features the original captain of the Enterprise, Christopher Pike, along with a young Spock, Uhura, and Nurse Chapel. Season 2 includes a great crossover with the animated series <em>Lower Decks</em> and overall is just a ton of fun.</p>
<p><strong>Reacher (Amazon Prime)</strong> The ultimate dad show. What's a dad show? Basically a show, usually featuring a cop, detective or government agent that is named after said guy (it's always a guy). Bosch, Jack Ryan, Reacher. Amazon has a monopoly on them. Reacher is based on a series of books popularized by the Tom Cruise movie, <em>Jack Reacher</em>. In the books Reacher is much more imposing than Cruise and Alan Ritchson is a beast of a man that's like at least a head taller than everyone on the show. In season two, Reacher is reunited with his former military unit (basically a bunch of mini-Reachers) to unravel a mystery involving the deaths of several of their former squadmates.</p>
<figure>
<iframe src="https://www.youtube.com/embed/rJGBVNRwl_U?si=QmtxFlWuHjQ_qX4O" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<figcaption>Reacher beats the living crap out of a guy in the first few minutes of season two.</figcaption>
</figure>
<p><strong>Others worth mentioning:</strong> Loved seeing <em>Neighbors</em> stars Seth Rogan and Rose Byrne reunited in <strong>Platonic (Apple TV+)</strong> as a brewmaster who reconnects with his married friend from college. Harrison Ford is fantastic in <strong>Shrinking (Apple TV+)</strong> as Jason Segel's boss. Segel plays a grieving therapist who gets a little too involved in his patient's lives. I loved the playful vibe of Keri Russell and Rufus Sewell in <strong>The Diplomat (Netflix)</strong>. Say what you will about Pete Davidson but <strong>Bupkis (Peacock)</strong>, loosely based on his life, is hilarious. Joe Pesci is in top form as his grandfather. Finally, I've only watched one episode of the fifth season of <strong>Fargo</strong> but it's a banger. Juno Temple is fantastic.</p>
<h3>Video Games</h3>
<p><strong>Baldur's Gate 3</strong> Easily my game of the year. I had planned to write a "<a href="https://mikeaparicio.com/tag/why-i-love/">Why I love</a>" post about it but I was too caught up in playing it, literally for hundreds of hours. Baldur's Gate 3 was made by the team at Larian Studios, whose previous games Divinity: Original Sin 1 and 2 were heavily inspired by Dungeons & Dragons but were not officially licensed. With BG3, they perfectly blend all of the rules and lore of D&D with a great narrative, fantastic voice acting, a superb score, and compelling turn-based strategy.</p>
<p>Baldur's Gate 3 is so good that <a href="https://kotaku.com/baldurs-gate-3-reviews-development-larian-studios-1850737062">other game studios complained</a> they wouldn't be able to match the high bar set by Larian. BG3 has no microtransactions β a rarity for popular games in today's industry that rely heavily on seasonal content to keep players invested. BG3 surpassed all expectations and sold incredibly well and won numerous game of the year awards. Not to mention it brought us <a href="https://youtu.be/ZjlYFWLUDBQ?si=518lEWNxmXb90Sk7">this song</a>.</p>
<p>This game is so incredibly deep and satisfying to play. There are so many things to do and people to meet and ways to accomplish your objectives. Larian seems to have thought of everything. Surprisingly, your character's story is the least interesting. The characters you meet along the way that can join your party all have their own deeply crafted storylines. They start out as seemingly basic archetypes but by the end of the game you become so deeply invested in their stories, it's incredible.</p>
<figure>
<iframe src="https://www.youtube.com/embed/QmZFxAqZKuU?si=dkscB8-DfgksN3iR" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<figcaption>BG3 is amazing solo, but you can also play four-player co-op, which allows for some pretty wild shenannigans.</figcaption>
</figure>
<p>I played through the whole game three times to get all of the trophies, which was a bit of a grind, but even after hundreds of hours I was still discovering new things, much like Elden Ring a few years ago. You also have the option of playing as any of the "origin" characters, which are the characters that you normally meet along the way that join your party. There's a bonus origin character called The Dark Urge which encourages you to be evil. I found it really difficult to constantly be evil but it's definitely entertaining!</p>
<p><strong>Wo Long: Fallen Dynasty</strong> I almost forgot about this great Souls-like from the makers of Nioh that came out early in 2023. I had a lot of fun with it. The mechanics are similar to Nioh but overall it felt a bit more accessible. Nioh is the game that finally made me able to wrap my head around the Souls genre, so I'm always stoked when Team Ninja pumps out another game.</p>
<p><strong>Chants of Sennaar</strong> I picked this one up on my boss' recommendation and instantly fell in love with it. At its heart it's a puzzle game about linguistics β you uncover the story by piecing together the languages of several different tribes. The art style is beautiful and some of the puzzles are quite challenging. It's a relatively short playthrough, too. I think it took me about 12 hours to beat and I nearly got all of the trophies as well.</p>
<p><strong>Double Dragon Gaiden</strong> I loved this throwback to one of my favorite arcade games as a kid. It looks and feels retro but incorporates some roguelike elements that make it challenging and it pushes you to unlock different characters who each have their own unique abilities.</p>
<p><strong>Call of Duty: Modern Warfare 2/3</strong> This was probably the game I spent the most time playing (regrettably). I just had a blast with the new extraction mode, DMZ, introduced in MW2. In DMZ you and two teammates drop into the large Warzone map, do missions and collect items while fending off AI soliders and other human players, who may or may not be aggressive towards you. You have about an hour to complete your objectives and extract before a toxic gas cloud begins expanding and envelops the entire map. If you die, you lose all of your gear. Because I'm a masochist, I enjoyed playing this mode solo against squads of three people.</p>
<p>Modern Warfare 3 came out in the fall and added a zombies mode which incorporated a lot of elements of DMZ on a new map. I kind of miss the uncertainty of whether other players on the map are hostile of friendly that happens in DMZ but zombies mode is a lot less stressful and, if you get downed, most players will come to revive you if you ask them in the chat. I also spent some time in Warzone and multiplayer, but a majority of my time was spent in these extraction modes.</p>
<figure>
<iframe src="https://www.youtube.com/embed/gmkqyzFsGfE?si=A_xSojR6qV7arK_c" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""></iframe>
<figcaption>Nothing in gaming is as tense and anxiety-inducing as Warzone.</figcaption>
</figure>
<p><strong>Others worth mentioning:</strong> I played a fair amount of <strong>Diablo 4</strong> but beyond the campaign (and even during the campaign, if I'm honest) it got really repetitive. I think just the mechanics of Diablo haven't evolved much over the years to keep me interested. I had a lot of fun with <strong>Star Wars: Jedi Survivor</strong> and was especially tickled that a friend who worked on the game snuck in a little easter egg with my sons names and birthdays. It probably took me a good 30 hours before I even found it! <strong>Legend of Zelda: Tears of the Kingdom</strong> felt a lot like <em>Breath of the Wild</em> but with a new crafting mechanic that allowed you to assemble different parts to make tools, enhance weapons and even build vehicles. There were some pretty inventive creations online but I always ended up just brute-forcing things with the simplest designs. I got bored with it pretty quickly and gave up after two or three bosses. Ryan and I had fun playing <strong>Teardown</strong> together. It's a voxel-based first person game where you're tasked with stealing and destroying stuff in creative ways. As the game progresses though, they quickly start adding time constraints that made the game a little too hard for Ryan. Fortunately it has a sandbox mode where you can just blow stuff up with tools like sledgehammers, blowtorches and pipe bombs.</p>
<h2>Looking forward to in 2024</h2>
<p><strong>Looking after my health.</strong> I'm going to be 49(!) this year and, while I may not look it, my insides certainly feel like it. This year I had some random nagging ailments, including a bum shoulder that just spontaneously started hurting like hell when I moved in in certain ways. After getting some x-rays and an MRI, the doctor diagnosed me with "frozen shoulder," which mostly occurs in people who have had their shoulder immobilized for long periods of time, like in a cast or sling. In my case it was from just not doing anything at all. I'm in physical therapy right now and it's feeling much better. Hoping to be back to normal in a few months.</p>
<p>I really need to start taking better care of myself. After spending my whole life never topping 140 pounds (even after working with a trainer for a year), I randomly weighed myself a few months ago and my jaw dropped when the scale read 156. Unfortunately it's not evenly distributed, except around my gut. I've got a real dad bod situation going on and I'm not sure I like it. π
</p>
<p>They recently build a new state-of-the-art <a href="https://pdop.org/crc/">rec center</a> here in Oak Park and Allie and I signed up. It's only $50 for the two of us and includes on-site childcare. There's a nice gym, a track, some basketball courts, fitness classes, and even a game room for when the boys are a little older. I need to start taking advantage of it.</p>
<p><strong>Fixing up the house.</strong> I think the next project we want to tackle is getting rid of all of our gas-powered appliances. We're looking at induction stoves right now and I'd also like to get one of those all-in-one, ventless washer/dryers to put upstairs. Eventually I'd like to get rid of our gas furnace and get a heat pump, but that's probably a bigger project than we have the budget for right now. I'm not sure if solar is feasible with our house, given that there's a three-story apartment building just south of us and we'd like to eventually finish the attic, which might require re-pitching the roof. It'd probably be cheaper to just build a new house at this point, rather than try and upgrade this 100+ year old house that's basically the <a href="https://en.wikipedia.org/wiki/Ship_of_Theseus">ship of Theseus</a>.</p>
<p><strong>Returning to Peru.</strong> It's been over 10 years now since I've been to Peru and I'm past due for a visit. We had planned to take the boys down for New Years but tickets were ridiculously overpriced and I slacked on getting the boys' passports. But also traveling with two young boys was hard enough on a 4-hour flight to California. The trip to Peru is a two-leg, 12-hour ordeal in itself, much less with two toddlers and all their gear. Hopefully it'll be a little easier this year with Owen a bit older.</p>
<p><strong>Even more traveling.</strong> I'm off to Austin for work in January. Looking forward to eating a lot of good food and hopefully catching up with some industry friends. We had a ton of fun in California, even though it was extremely taxing keeping the kids from going crazy. We haven't decided on a location but New York might be fun. I'll also have another work summit in July to look forward to.</p>
<p>Aside from all that I'm just going to keep trucking along, living with the existential dread of the upcoming U.S. election and hoping that our systems are still strong enough to keep a power-hungry, authoritarian narcissist out of the White House again.</p>
<p>Thanks for reading! I hope you and your family had a restful holiday and wish you all the best in 2024.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/L4kytMnCY--300.webp 300w, https://mikeaparicio.com/images/L4kytMnCY--600.webp 600w, https://mikeaparicio.com/images/L4kytMnCY--800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/L4kytMnCY--300.jpeg 300w, https://mikeaparicio.com/images/L4kytMnCY--600.jpeg 600w, https://mikeaparicio.com/images/L4kytMnCY--800.jpeg 800w" sizes="100vw" /><img alt="The Aparicios with Santa Claus." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/L4kytMnCY--300.jpeg" width="800" height="533" /></picture>
<figcaption>
Happy New Year from the Aparicios!
</figcaption>
</figure>
Using Wordpress as a headless CMS for Eleventy
2023-11-07T00:00:00Z
https://mikeaparicio.com/posts/2023-11-07-using-wordpress-as-a-headless-CMS-for-eleventy/
<p>Many years ago, before I started specializing in CSS and design systems, I held the job title of <strong>Webmaster</strong> β managing all aspects of a company's website. So when the Turquoise marketing team asked me to help them build a new website, I was happy to help them out.</p>
<p>The challenge was that they wanted it to be a Wordpress site, and I haven't touched Wordpress (or PHP, for that matter) in over a decade. I use Eleventy exclusively to build everything these days and I love it. But one thing about Eleventy is that it's not easy for non-technical folks to make changes without incorporating some kind of CMS.</p>
<p>I had heard of people using Wordpress as a "headless" CMS for Eleventy β meaning users manage content with Wordpress but then the content is pulled into another site using the Wordpress API. If I could get it to work, it'd be the ideal setup. Marketing could make their updates in Wordpress and I could build the site with Eleventy.</p>
<p>I had no idea where to start, so I just Googled "Wordpress Eleventy" and found <a href="https://danabyerly.com/articles/wordpress-and-eleventy-part-one-wordpress/">this great, comprehensive article</a> by <strong>Dana Byerly</strong> that set me in the right direction.</p>
<p>Along the way I ran into a bunch of issues so I thought I'd document them here. In the end, I was able to do pretty much everything I set out to and this is probably going to be my go-to setup when I need to make Eleventy sites that require a CMS.</p>
<h2>Pulling in the content</h2>
<p>The first stumbling block I ran into was that Dana's setup used self-hosted Wordpress rather than Wordpress' own managed hosting. Not a big deal, right? Except there's apparently an <a href="https://developer.wordpress.com/docs/api/">entirely different API</a> for some reason.</p>
<p>Once I figured this out, I made a file in Eleventy called <code>_src/_data/posts.js</code> that used <code>node-fetch</code> to query the API, where <code>{$URL}</code> is the Wordpress.com subdomain (e.g. yoursite.wordpress.com):</p>
<pre class="language-js"><code class="language-js"><span class="token keyword">const</span> fetch <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"node-fetch"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token keyword">const</span> postsURL <span class="token operator">=</span> https<span class="token operator">:</span><span class="token operator">/</span><span class="token operator">/</span>developer<span class="token punctuation">.</span>wordpress<span class="token punctuation">.</span>com<span class="token operator">/</span>docs<span class="token operator">/</span>api<span class="token operator">/</span><span class="token number">1.1</span><span class="token operator">/</span>get<span class="token operator">/</span>sites<span class="token operator">/</span><span class="token punctuation">{</span>$<span class="token constant">URL</span><span class="token punctuation">}</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">posts</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">;</span><br /><br />module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"Fetching posts..."</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /> <span class="token keyword">return</span> <span class="token function">fetch</span><span class="token punctuation">(</span>postsURL<span class="token punctuation">)</span><br /> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token operator">=></span> res<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><br /> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">json</span><span class="token punctuation">)</span> <span class="token operator">=></span> json<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>Unfortunately that gave me an error, which after much Googling I discovered <a href="https://stackoverflow.com/questions/69087292/requirenode-fetch-gives-err-require-esm">this Stack Overflow answer</a> that suggested using the second version of node-fetch rather than the latest third version. I don't know what any of that means, but it worked! So when installing node-fetch in Eleventy, use:</p>
<pre class="language-html"><code class="language-html">npm install node-fetch@2</code></pre>
<p>Now it was working, except the marketing team had entered the content as pages rather than posts. No problem, just update <code>/posts/</code> to <code>/pages/</code> on the endpoint, right? No, that would be too obvious. You actually need to use <code>/posts/?type=page</code>.</p>
<figure>
<img src="https://mikeaparicio.com/images/michael-bolton.gif" alt="Michael from Office Space shooting a disappointed look at the camera." />
</figure>
<p>As it turned out, we needed to be able to categorize or tag each page, which is only possible with posts, so we ended up just moving all the content to posts anyway. I used <a href="https://wordpress.org/plugins/post-type-transfer/">this handy plugin</a> to change the type without having to re-enter all the content.</p>
<h2>Working with the content in Eleventy</h2>
<p>Now that we've successfully pulled all the content into an Eleventy data file, we can use Eleventy to display that content in different ways.</p>
<h3>Listing categories</h3>
<p>We want to list the categories and descriptions of those categories on the homepage. First we need the category data, which we can get by making a new data file, <code>categories.js</code>, which is exactly the same as the posts data file above but the endpoint is <code>/categories/</code> instead of <code>/posts/</code>.</p>
<p>On our homepage we can create a list and iterate over the categories, making each their own list item.</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">for</span> category <span class="token keyword">in</span> categories<span class="token punctuation">.</span>categories <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> category<span class="token punctuation">.</span>name <span class="token operator">!==</span> <span class="token string">"Uncategorized"</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>li<span class="token operator">></span><br /> <span class="token operator"><</span>a href<span class="token operator">=</span><span class="token string">"/tqu/categories/{{ category.name | slug }}"</span><span class="token operator">></span><br /> <span class="token operator"><</span>h2<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> category<span class="token punctuation">.</span>name <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>h2<span class="token operator">></span><br /> <span class="token operator"><</span>p<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> category<span class="token punctuation">.</span>description <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>a<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>And this is the result:</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/yzZC2m8QIr-300.webp 300w, https://mikeaparicio.com/images/yzZC2m8QIr-600.webp 600w, https://mikeaparicio.com/images/yzZC2m8QIr-1578.webp 1578w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/yzZC2m8QIr-300.jpeg 300w, https://mikeaparicio.com/images/yzZC2m8QIr-600.jpeg 600w, https://mikeaparicio.com/images/yzZC2m8QIr-1578.jpeg 1578w" sizes="100vw" /><img alt="An example of the output of the above code, showing four cards with categories and descriptions." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/yzZC2m8QIr-300.jpeg" width="1578" height="840" /></picture>
</figure>
<p>Similarly, we can iterate through the categories for our navigation:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">for</span> category <span class="token keyword">in</span> categories<span class="token punctuation">.</span>categories <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> category<span class="token punctuation">.</span>name <span class="token operator">!==</span> <span class="token string">"Uncategorized"</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>li<span class="token operator">></span><span class="token operator"><</span>a href<span class="token operator">=</span><span class="token string">"/tqu/categories/{{ category.name | slug }}/"</span><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> category<span class="token punctuation">.</span>name <span class="token operator">==</span> title <span class="token operator">%</span><span class="token punctuation">}</span> aria<span class="token operator">-</span>current<span class="token operator">=</span><span class="token string">"page"</span> <span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> category<span class="token punctuation">.</span>name <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>a<span class="token operator">></span><span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<h3>Posts within a category</h3>
<p>For our category page, which lists all of the posts under a specific category, we can use Eleventy's pagination feature. The front matter looks like this:</p>
<pre class="language-js"><code class="language-js"><span class="token operator">--</span><span class="token operator">-</span><br /><span class="token literal-property property">pagination</span><span class="token operator">:</span><br /> <span class="token literal-property property">data</span><span class="token operator">:</span> categories<span class="token punctuation">.</span>categories<br /> <span class="token literal-property property">size</span><span class="token operator">:</span> <span class="token number">1</span><br /> <span class="token literal-property property">alias</span><span class="token operator">:</span> category<br /><span class="token literal-property property">permalink</span><span class="token operator">:</span> <span class="token string">"tqu/categories/{{ category.name | slug }}/"</span><br /><span class="token literal-property property">layout</span><span class="token operator">:</span> page<span class="token punctuation">.</span>njk<br /><span class="token literal-property property">classes</span><span class="token operator">:</span> tqu<span class="token operator">-</span>layout<span class="token operator">-</span>main<br /><span class="token literal-property property">eleventyComputed</span><span class="token operator">:</span> <br /> <span class="token literal-property property">title</span><span class="token operator">:</span> <span class="token string">"{{ category.name }}"</span><br /> <span class="token literal-property property">description</span><span class="token operator">:</span> <span class="token string">"{{ category.description }}"</span><br /><span class="token operator">--</span><span class="token operator">-</span></code></pre>
<p>There's some extra stuff in there specific to this project, but basically in the <code>pagination</code> we're specifying where the data is coming from, setting the <code>size</code> to 1 to get one category page for each category, and then giving the data an alias so we can reference it elsewhere as <code>category</code> instead of <code>categories.categories</code>. (The data file is called "categories" and then within that JSON the data lives inside <code>categories</code>.)</p>
<p>Next we define the URL for the category pages, and then in <code>eleventyComputed</code> we can assign the page title and description for each category page so we can access those elsewhere.</p>
<p>Fortunately, the data has a field called <code>post_count</code>, which equals the number of posts in a particular category, so we can conditionally show a list of posts in each category:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> category<span class="token punctuation">.</span>post_count <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>ul<span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> <span class="token keyword">for</span> item <span class="token keyword">in</span> posts<span class="token punctuation">.</span>posts <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">for</span> key<span class="token punctuation">,</span> value <span class="token keyword">in</span> item<span class="token punctuation">.</span>categories <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> key <span class="token operator">==</span> category<span class="token punctuation">.</span>name <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>li<span class="token operator">></span><br /> <span class="token operator"><</span>a href<span class="token operator">=</span><span class="token string">"/tqu/{{ item.slug }}"</span><span class="token operator">></span><br /> <span class="token operator"><</span>h2<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> item<span class="token punctuation">.</span>title <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>h2<span class="token operator">></span><br /> <span class="token operator"><</span>p<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> item<span class="token punctuation">.</span>excerpt <span class="token operator">|</span> safe <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>a<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">-</span><span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span><span class="token operator">/</span>ul<span class="token operator">></span><br /><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">else</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>p<span class="token operator">></span>There are no articles <span class="token keyword">in</span> <span class="token keyword">this</span> category<span class="token punctuation">.</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span><br /><span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>Here we're looking in the <code>posts</code> data file for all the posts that match the current category and displaying the title and a brief excerpt.</p>
<h3>Pages</h3>
<p>Similar to our category pages, we can use Eleventy pagination to make a page for each post. Here's the front matter:</p>
<pre class="language-js"><code class="language-js"><span class="token operator">--</span><span class="token operator">-</span><br /><span class="token literal-property property">pagination</span><span class="token operator">:</span><br /> <span class="token literal-property property">data</span><span class="token operator">:</span> posts<span class="token punctuation">.</span>posts<br /> <span class="token literal-property property">size</span><span class="token operator">:</span> <span class="token number">1</span><br /> <span class="token literal-property property">alias</span><span class="token operator">:</span> post<br /><span class="token literal-property property">permalink</span><span class="token operator">:</span> <span class="token string">"tqu/{{ post.slug }}/"</span><br /><span class="token literal-property property">layout</span><span class="token operator">:</span> page<span class="token punctuation">.</span>njk<br /><span class="token literal-property property">classes</span><span class="token operator">:</span> tqu<span class="token operator">-</span>layout<span class="token operator">-</span>main<br /><span class="token literal-property property">eleventyComputed</span><span class="token operator">:</span> <br /> <span class="token literal-property property">title</span><span class="token operator">:</span> <span class="token string">"{{ post.title }}"</span><br /> <span class="token literal-property property">description</span><span class="token operator">:</span> <span class="token string">"{{ post.excerpt | stripHTML }}"</span><br /><span class="token operator">--</span><span class="token operator">-</span></code></pre>
<p>This is almost identical to the front matter for categories, except for the description I'm taking the <code>excerpt</code> data and applying a filter to it, which strips any HTML that might be added by WordPress. This filter is adapted from Stephanie Eckles <code>excerpt</code> filter over at <a href="https://11ty.rocks/eleventyjs/content/">11ty Rocks!</a>, which is an invaluable resource for all things Eleventy.</p>
<p>In the body we can include the post title and content:</p>
<pre class="language-js"><code class="language-js"><span class="token operator"><</span>h1<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> post<span class="token punctuation">.</span>title <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span><br /><br /><span class="token punctuation">{</span><span class="token punctuation">{</span> post<span class="token punctuation">.</span>content <span class="token operator">|</span> safe <span class="token punctuation">}</span><span class="token punctuation">}</span></code></pre>
<p>And that's pretty much all you need to pull in content from WordPress!</p>
<h2>Updating the Eleventy site automatically</h2>
<p>This setup is great and everything, but the problem with it is that in its current state, I'd need to manually run a build any time someone in marketing makes an edit. Who wants to do that?</p>
<p>Fortunately, there's a plugin called <a href="https://wordpress.org/plugins/wp-jamstack-deployments/">WP Jamstack Deployments</a> that will run a build hook on Netlify any time someone makes an update. In the plugin you can specify which updates should trigger a build.</p>
<p>You can find build hooks on Netlify under <strong>Site Configuration -> Build & Deploy -> Continuous Deployment</strong> under "Build hooks".</p>
<p>Now when someone makes a change to the site, it triggers a Netlify build and the live site is updated within about 30 seconds. Sweet!</p>
<p><strong>Update:</strong> Several people brought to my attention the fact that only Wordpress' Business tier ($25/mo) and above support plugins.</p>
<h2>Adding custom CSS</h2>
<p>While our design system's CSS framework handles most of the styles for the site, it's unlikely the marketing team wants to be bothered adding CSS classes to things like headings and tables. So I added a few site-specific styles that help style all of the content that comes from Wordpress. There was a bit of redundancy, but in the end it's worth it to have the content look good without the author having to think about it.</p>
<p>(I omitted all of the classes from the examples here for the sake of brevity.)</p>
<h2>Adding search with Pagefind</h2>
<p>I wanted to add search to the site without having to sign up for some third-party service and then configure a bunch of stuff on the Eleventy side. This article, <a href="https://rknight.me/using-pagefind-with-eleventy-for-search/">Using PageFind with Eleventy for Search</a> by <strong>Robb Knight</strong>, made it super easy.</p>
<p>I ended up making a dedicated search page because as far as I could tell, I couldn't add a search bar to the global nav that would take you to a results page for that search. Pagefind kind of shows the results inline. You can see this in <a href="https://rknightuk.github.io/eleventy-pagefind-demo/">Robb's demo</a>.</p>
<h2>Four hundos</h2>
<p>You know I had to get four hundos on Lighthouse. Thanks to Zach Leatherman for gamifying performance and best practices with the <a href="https://www.11ty.dev/speedlify/">Eleventy Leaderboard</a>. This could quickly go out the window as marketing adds images and tracking scripts, but at least we started from a good place.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/K3StK0KWyu-300.webp 300w, https://mikeaparicio.com/images/K3StK0KWyu-600.webp 600w, https://mikeaparicio.com/images/K3StK0KWyu-1710.webp 1710w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/K3StK0KWyu-300.jpeg 300w, https://mikeaparicio.com/images/K3StK0KWyu-600.jpeg 600w, https://mikeaparicio.com/images/K3StK0KWyu-1710.jpeg 1710w" sizes="100vw" /><img alt="A screenshot of Lighthouse for TQU with four 100 scores" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/K3StK0KWyu-300.jpeg" width="1710" height="1554" /></picture>
</figure>
<h2>Wrapping Up</h2>
<p>I was honestly surprised how relatively easy this all was. It took a lot of trial and error to get my specific setup working, but now that I figured it out it would be pretty trivial to spin up another one of these if the need arises. Big thanks to everyone whose articles I linked to above. It made it my life so much easier.</p>
<p>One thing I love about the Eleventy community is how willing folks are to share their knowledge. β₯οΈ</p>
<p>If you have any suggestions on how to improve on this setup, <a href="https://mikeaparicio.com/contact">let me know</a>!</p>
<p>You can see the finished product at <strong><a href="https://turquoise.health/tqu">TQU</a></strong> and learn everything there is to know about price transparency in health care.</p>
10 years of Extra Life
2023-08-07T00:00:00Z
https://mikeaparicio.com/posts/2023-08-07-ten-years-of-extra-life/
<p>It's been nine years since my daughter, <a href="https://mikeaparicio.com/posts/2018-08-26-four-years/">Olivia</a>, was born prematurely and I set out on my first <a href="https://www.extra-life.org/">Extra Life</a> campaign, playing video games for 24-hours to raise money for Lurie Children's Hospital in Chicago, where she was being treated.</p>
<p>Olivia passed away less than a week later, a little over nine weeks after being born. We were devastated.</p>
<p>I can't even explain how difficult the ensuing years were, as we tried desperately to have another child. We were finally blessed with <a href="https://mikeaparicio.com/posts/2019-02-14-ryan/">Ryan</a> in 2019 and again with <a href="https://www.mikeaparicio.com/posts/2022-06-08-owen/">Owen</a> in 2022.</p>
<p>The hardest part for me about losing my daughter is thinking about what could have been. Seeing girls her age and wondering what she would have been like. How much she would have enjoyed being a big sister. Being with us on all of the adventures we've had. What kind of woman she might have grown to become.</p>
<p>I think about her every day.</p>
<p>So I've kept doing Extra Life every year to honor her memory. To give back to the hospital that kept her alive as long as they could. It's always bittersweet because on one hand Extra Life is a celebration, and on the other hand I can't help but wish she were with us, playing video games with me and her brothers to raise money to help other kids make sure they feel loved and happy while they're going through the hardest thing imaginable.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/3As8MEYoUa-300.webp 300w, https://mikeaparicio.com/images/3As8MEYoUa-600.webp 600w, https://mikeaparicio.com/images/3As8MEYoUa-2316.webp 2316w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/3As8MEYoUa-300.jpeg 300w, https://mikeaparicio.com/images/3As8MEYoUa-600.jpeg 600w, https://mikeaparicio.com/images/3As8MEYoUa-2316.jpeg 2316w" sizes="100vw" /><img alt="Mike sporting an Extra Life t-shirt and wearing nine gold medals around his neck." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/3As8MEYoUa-300.jpeg" width="2316" height="3088" /></picture>
<figcaption>Extra Life awards a gold medal for raising $1000+. Going for my 10th this year.</figcaption>
</figure>
<p>2023 marks my <strong>10th year</strong> of doing Extra Life. Over that time, thanks to the generosity of hundreds of people, we've been fortunate to raise over <strong>$38,000</strong> for Lurie Children's Hospital. Each year I'm humbled by the outpouring of love and support.</p>
<p>I'm particularly grateful to <strong>Bert Fanslow</strong>, who has done the entire 24-hour marathon with me each of the last 8 years, and <strong>Alan Spadoni</strong> who has popped in for a good strech in many of those years as well. And of course to my wife, <strong>Allie</strong>, who makes sure I stay hydrated and well-fed. Together, as <strong>Team Olivia</strong>, we have inspired people to help sick kids in need in Olivia's honor, which makes me really proud.</p>
<p>The past few years I've been doing a 12-hour stream on Olivia's birthday in addition to the full 24-hour marathon the first Saturday in November. This year, since Bert will be on his honeymoon, we've decided to do the full 24-hour marathon on Olivia's birthday, <strong>Saturday, August 26th</strong>, starting at 8am Central time.</p>
<p>I'll be streaming the entire day on <a href="https://www.twitch.tv/peruvianidol">Twitch</a> if you'd like to pop in and offer words of encouragement or just hang out and watch us play some video games.</p>
<p>It's going to be a great time and I'm going to be having a raffle for some gaming related prizes for folks who donate, as well as matching contributions for part of the day.</p>
<p>If you'd like to join us in our effort to raise funds for children's hospitals (you can pick your own local hospital to support), you can visit <a href="https://www.extra-life.org/index.cfm?fuseaction=donordrive.team&teamID=63682">our Extra Life team page</a> and click the "Join Our Team" button. What a great excuse to play video games for 24 hours!</p>
<p><strong>If you'd like to make a donation</strong>, you can do so on <a href="https://www.extra-life.org/index.cfm?fuseaction=donordrive.participant&participantID=510006">my Extra Life page</a> or by clicking this button:</p>
<p><a href="https://www.extra-life.org/index.cfm?fuseaction=donordrive.participant&participantID=510006" class="ma-button">Donate</a></p>
<p>Any amount you can give is greatly appreciated. You can really help us out by sharing our campaign with your friends and family.</p>
<p>Thank you so much to everyone who has donated to our cause over the years. It truly means a lot to me and my family.</p>
Why we're bad at CSS
2023-05-22T00:00:00Z
https://mikeaparicio.com/posts/2023-05-22-why-were-bad-at-css/
<p>When many devs think of CSS they think of Peter Griffin trying to open window blinds. But for others CSS is more like putting their hand in <a href="https://youtu.be/mbTp1vlRqYA">the pain box from Dune</a> while some product manager has a <em>gom jabbar</em> to their neck, daring them to pull their hand out.</p>
<figure>
<video poster="https://mikeaparicio.com/images/pain-box.png" src="https://mikeaparicio.com/images/pain-box.mp4" loop="" autoplay="" muted="" playsinline="">
</video></figure>
<p>There's a few reasons why tech continues to struggle with CSS.</p>
<ol>
<li>
<p><strong>We're bad at teaching CSS.</strong> While there are a ton of great CSS practitioners out there sharing their knowledge (<a href="https://thinkdobecreate.com/">Stephanie Eckles</a>, <a href="https://www.kevinpowell.co/">Kevin Powell</a>, and <a href="https://nerdy.dev/">Adam Argyle</a>, to name a few), a lot of people learn HTML and CSS in college or bootcamps from people who are perhaps not as knowledgeable, use outdated techniques or gloss over the basics in favor of frameworks like Bootstrap or Tailwind. As a result, you end up with a lot of folks who don't have a deep knowledge of HTML and CSS, which are the basic building blocks of the web.</p>
</li>
<li>
<p><strong>We're bad at hiring for CSS.</strong> Just about every job listing for a full stack or frontend engineer lists HTML, CSS and JavaScript proficiency as a prerequisite, but when they interview candidates, they're rarely testing for anything other than JavaScript skills. If companies end up hiring people with CSS skills, it's usually by accident. And if you don't have people with those skills you can't vet other people for those skills and the problem perpetuates itself.</p>
</li>
<li>
<p><strong>We're bad at writing CSS.</strong> Without deep knowledge of CSS and with an inability to hire people with that knowledge, people go to great lengths to avoid writing CSS, whether by relying on Bootstrap/Tailwind or trying to do everything in JavaScript. They end up over-complicating things to the point where their CSS is extremely hard to maintain.</p>
</li>
</ol>
<p>As I wrote in <a href="https://mikeaparicio.com/posts/2022-11-26-reframing-design-systems/">Reframing Design Systems</a>, even people who are good at CSS often approach it in the context of a product feature. If you look at just about any site's CSS, you'll find a ton of instances of the same borders, margin, padding, background colors, etc. being declared dozens of times in different contexts.</p>
<figure>
<blockquote class="ma-blockquote">
Writing CSS is applying the same set of visual styles in a bunch of <strong>different contexts</strong> over and over again until you die*
</blockquote>
<figcaption class="ma-text-small">* or, you know, quit tech and start a Peruvian food truck business, which goes great until your spouse divorces you because you took such a massive pay cut and you're working all the time, never see the kids, and come home smelling like ceviche. Hypothetically.</figcaption>
</figure>
<p>Despite the latest advancements in CSS, many are still stuck in this kind of <a href="https://en.bem.info/methodology/">BEM</a> mindset, trying to perfectly encapsulate everything so we don't end up with unexpected results when we make changes.</p>
<p>Take this example from the BEM documentation:</p>
<pre class="language-css"><code class="language-css"><span class="token selector">.page__header</span> <span class="token punctuation">{</span><br /> <span class="token property">padding</span><span class="token punctuation">:</span> 20px<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.page__footer</span> <span class="token punctuation">{</span><br /> <span class="token property">padding</span><span class="token punctuation">:</span> 50px<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>This really isn't a whole lot different from using a utility class from a framework like Tailwind, except you wouldn't use <code>page__header</code> in any other context to add 20 pixels of padding to an element.</p>
<p>With Tailwind's "utility-first" approach, you need to apply a class for every individual design decision, resulting in markup like <a href="https://tailwindcss.com/">this example</a> from their website:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>figure</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>md:flex bg-slate-100 rounded-xl p-8 md:p-0 dark:bg-slate-800<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>w-24 h-24 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto<span class="token punctuation">"</span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/sarah-dayan.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>384<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>512<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>pt-6 md:p-8 text-center md:text-left space-y-4<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>blockquote</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text-lg font-medium<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> βTailwind CSS is the only framework that I've seen scale<br /> on large teams. Itβs easy to customize, adapts to any design,<br /> and the build size is tiny.β<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>blockquote</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>figcaption</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>font-medium<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text-sky-500 dark:text-sky-400<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> Sarah Dayan<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text-slate-700 dark:text-slate-500<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> Staff Engineer, Algolia<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>figcaption</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>figure</span><span class="token punctuation">></span></span></code></pre>
<p>We're basically offloading those same contextual design decisions (in this case, what this card looks like) into class names in the markup, rather than than adding new class names to our CSS.</p>
<h2>So, what's the answer?</h2>
<p>We want our styles to be generic enough to reuse in different contexts but not so generic that we have to constantly repeat ourselves in those contexts.</p>
<p>I took a stab at trying to articulate this with <a href="https://mikeaparicio.com/posts/2021-03-25-cool-css/">COOL CSS</a>, a silly name I came up with for my own methodology that has served me well in writing CSS to support design systems at three different companies now.</p>
<p>In short, the idea is to style individual <strong>components</strong> with a single class, use <strong>utility</strong> classes to compose or modify them in different contexts, and provide <strong>layouts</strong> to keep things consistent between and within pages.</p>
<ul>
<li>Component</li>
<li>Utility (OO)</li>
<li>Layout</li>
</ul>
<p>Cool. π</p>
<h2>What Cool looks like</h2>
<p>Let's refactor the card example from the Tailwind site.</p>
<figure style="width: 75%; margin-inline: auto">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/-WaTwd2Eb--300.webp 300w, https://mikeaparicio.com/images/-WaTwd2Eb--600.webp 600w, https://mikeaparicio.com/images/-WaTwd2Eb--984.webp 984w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/-WaTwd2Eb--300.jpeg 300w, https://mikeaparicio.com/images/-WaTwd2Eb--600.jpeg 600w, https://mikeaparicio.com/images/-WaTwd2Eb--984.jpeg 984w" sizes="100vw" /><img alt="A card with a woman's photo on the left and a blockquote on the right." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/-WaTwd2Eb--300.jpeg" width="984" height="592" /></picture>
</figure>
<h3>The card</h3>
<p>This card contains a testimonial, but we might want to use this card pattern in a different context. Our card should not care what's inside of it. That is, we're not going to scope all of the content in this particular card example with <code>.card-</code>. These styles only dictate what the card container looks like.</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* /scss/components/_card.scss */</span><br /><span class="token selector">.cool-card</span> <span class="token punctuation">{</span><br /> <span class="token property">border-radius</span><span class="token punctuation">:</span> $radius-medium<span class="token punctuation">;</span><br /> <span class="token property">background-color</span><span class="token punctuation">:</span> $color-surface-brand-light<span class="token punctuation">;</span><br /> <span class="token property">overflow</span><span class="token punctuation">:</span> hidden<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br /> <span class="token selector">.cool-card</span> <span class="token punctuation">{</span><br /> <span class="token property">background-color</span><span class="token punctuation">:</span> $color-surface-brand<span class="token punctuation">;</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> $color-text-inverse<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>Yes, I'm using SCSS variables instead of CSS custom properties for tokens. I love custom props but β <strong>controversial opinion alert</strong> β not for tokens.</p>
<p>Our design system not only defines the specific values we use (colors, type, spacing) but also the contexts in which we use them. Instead of giving developers utility classes that allow them to apply <strong>any</strong> color (e.g. <code>.bg-slate-100</code>), we only want to use certain colors in specific contexts.</p>
<p>I cringe anytime I see a mixin that goes through every color in the palette and makes a background color utility class for each one. You're never going to use <em>every</em> color and if you provide that option you're going to end up with some color combinations that lack sufficient contrast.</p>
<p>That's why I use a separate layer of tokens to define contexts. <code>$color-surface-brand-light</code> might point to <code>$slate-100</code>. If we ever want to change the value where our brand color is used for backgrounds, we can change a single token to apply it across different components without having to find and replace every instance of <code>$slate-100</code> with a different color.</p>
<p>Rather than giving our developers access to all of the tokens, we can abstract them into our classes and they can use the appropriate class for each context.</p>
<p>Also, since we're using SCSS, we can be more verbose with our token names, since they will compile to smaller values anyway.</p>
<h3>Flexin'</h3>
<p>The content within this particular card includes an image and a blockquote, arranged horizontally using flexbox. Let's add a flex utility.</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* /scss/utilities/_flex.scss */</span><br /><span class="token selector">.cool-flex</span> <span class="token punctuation">{</span><br /> <span class="token property">--flex-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><br /> <span class="token property">--flex-gap</span><span class="token punctuation">:</span> $spacing-16<span class="token punctuation">;</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span><br /> <span class="token property">align-items</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--flex-align<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--flex-gap<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Here we're using CSS custom properties inside our flex utility to provide some common defaults from <em>our</em> design system. This way we don't need to provide a bunch of additional utility classes to support every possible value for each flex property.</p>
<p>If a developer runs into an instance where they need to override the defaults, they can do so by declaring them in the <code>style</code> attribute. In this case, we don't want a gap between the image and the blockquote, since that will be handled by the padding.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>figure</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cool-card cool-flex<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">--flex-gap</span><span class="token punctuation">:</span> 0</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br /> ...<br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>figure</span><span class="token punctuation">></span></span></code></pre>
<p>Sure, there are other flex properties we might want to use down the line, but I'm a firm believer in adding things as you need it rather than trying to account for every possible use case. For the purposes of this card, this is more than sufficient.</p>
<p>In this design, flex is only applied above a certain viewport width, so we could create another flex utility that only applies above a certain breakpoint.</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* /scss/utilities/_flex.scss */</span><br /><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width >= $breakpoint-medium<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br /> <span class="token selector">.cool-flex-responsive</span> <span class="token punctuation">{</span><br /> <span class="token property">--flex-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><br /> <span class="token property">--flex-gap</span><span class="token punctuation">:</span> $spacing-16<span class="token punctuation">;</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span><br /> <span class="token property">align-items</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--flex-align<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--flex-gap<span class="token punctuation">)</span><span class="token punctuation">;</span> <br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>I've never really worked on a system that required more than one breakpoint (maybe some layouts but not individual components as much), so I tend to use <code>-responsive</code> to indicate things that should only happen above a certain breakpoint. With component queries gaining wider support, viewport-based media queries might soon be unnecessary in contexts like this.</p>
<p>We can now also use the new <a href="https://caniuse.com/?search=media%20range">range syntax</a> for our media queries in evergreen browsers! Instead of <code>max-width: $breakpoint-medium</code> we can write <code>width >= $breakpoint-medium</code>.</p>
<h3>The image</h3>
<p>It kinda drives me nuts when designers have an entirely different design between large and small screens. I do my best to make it work.</p>
<p>Here, our image goes from a small circle to a full-sized image on larger screens. This might require a unique component.</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* /scss/components/_avatar.scss */</span><br /><span class="token selector">.cool-avatar</span> <span class="token punctuation">{</span><br /> <span class="token property">width</span><span class="token punctuation">:</span> $avatar-medium<span class="token punctuation">;</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> $avatar-medium<span class="token punctuation">;</span><br /> <span class="token property">border-radius</span><span class="token punctuation">:</span> $radius-round<span class="token punctuation">;</span><br /> <span class="token property">object-fit</span><span class="token punctuation">:</span> cover<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width >= $breakpoint-medium<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br /> <span class="token selector">.cool-avatar</span> <span class="token punctuation">{</span><br /> <span class="token property">--width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span><br /> <span class="token property">max-width</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--width<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">width</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span><br /> <span class="token property">border-radius</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>We're adding a token for the rounded avatar size on small screens and setting <code>object-fit</code> to account for images that don't have a square aspect ratio. On large screens, we use a custom property to allow overriding the image's width.</p>
<p>We actually have to override the <code>--flex-align</code> of <code>.cool-flex</code> back to the default <code>stretch</code> to support instances where the text of the blockquote is taller than the image. So our <code>--width</code> prop is actually setting the max width while the width and height are set to auto, dictated by the aspect ratio of the image. To compensate for this I added an <code>align-self: center</code> inline to the text container. (This is a whole lot to consider for one very specific design choice, but it happens.)</p>
<p>We also need to accommodate for the positioning of the avatar on small screens. This necessitates a couple of utility classes that only appear on small screens. Yes, these class names are a little verbose, but I find them clearer than <code>md:h-auto</code> and it also takes advantage of <a href="https://web.dev/learn/css/logical-properties/">logical properties</a>.</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* /scss/utilities/_spacing.scss */</span><br /><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width < $breakpoint-medium<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br /> <span class="token selector">.cool-margin-auto-on-small</span> <span class="token punctuation">{</span><br /> <span class="token property">margin-inline</span><span class="token punctuation">:</span> auto<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><br /> <span class="token selector">.cool-margin-block-start-on-small</span> <span class="token punctuation">{</span><br /> <span class="token property">--size</span><span class="token punctuation">:</span> $spacing-32<span class="token punctuation">;</span><br /> <span class="token property">margin-block-start</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--size<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<h3>The text container</h3>
<p>The container with our blockquote and figcaption has some padding applied as well as margin between elements and the text is centered on small screens. Time for some more utilities!</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* /scss/utilities/_spacing.scss */</span><br /><span class="token selector">:where(.cool-flow)</span> <span class="token punctuation">{</span><br /> <span class="token property">--flow-size</span><span class="token punctuation">:</span> $spacing-16<span class="token punctuation">;</span><br /> <span class="token selector">& > :not(:last-child)</span> <span class="token punctuation">{</span><br /> <span class="token property">margin-block-end</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--flow-size<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.cool-inset-square-32</span> <span class="token punctuation">{</span><br /> <span class="token property">padding</span><span class="token punctuation">:</span> $spacing-32<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">/* /scss/utilities/_text.scss */</span><br /><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span>width < $breakpoint-medium<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br /> <span class="token selector">.cool-text-center-on-small</span> <span class="token punctuation">{</span><br /> <span class="token property">text-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>The flow utility is adapted from <a href="https://andy-bell.co.uk/my-favourite-3-lines-of-css/">Andy Bell's favourite 3 lines of CSS</a>. When you place it on a container, all direct children receive a bottom margin of <code>--flow-size</code>.</p>
<p>I've included it in a <code>:where()</code> <a href="https://css-tricks.com/almanac/selectors/w/where/">pseudo-class function</a> to reduce its specificity to zero so that you could override the bottom margin of any of the children with another utility class if needed.</p>
<p>For padding utilities, I've adopted the naming conventions Nathan Curtis outlines in <a href="https://medium.com/eightshapes-llc/space-in-design-systems-188bcbae0d62">Space in Design Systems</a>.</p>
<p><strong>Inset</strong> refers to padding and <strong>square</strong> indicates the same padding value on all four sides.</p>
<p>Finally, I added another utility class that centers text on small screens only.</p>
<h3>The text</h3>
<p>In Tailwind's version of this they're applying <code>.text-medium</code> to set the font weight of both the text of the blockquote and the figcaption below it. We could use a similar class and apply it just once to the whole container, but in this case we can just let the font weight inherit from the <code>body</code>.</p>
<p>We then need a text style for large text as well as what I refer to as <strong>subdued text</strong> β text that uses a lower contrast color to indicate reduced importance rather than adjusting the font size or font weight.</p>
<p>There's also some blue text that looks like a link but isn't. I'm assuming in practice that this would actually be a link, in which case we would apply the <code>.cool-text-interactive</code> styles to links in our global styles so that we could just use an <code><a></code> without a class.</p>
<pre class="language-css"><code class="language-css"><span class="token comment">/* /scss/components/_text.scss */</span><br /><span class="token selector">.cool-text-large</span> <span class="token punctuation">{</span><br /> <span class="token property">font-size</span><span class="token punctuation">:</span> $text-large-font-size<span class="token punctuation">;</span><br /> <span class="token property">line-height</span><span class="token punctuation">:</span> $text-large-line-height<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token comment">/* /scss/utilities/_text.scss */</span><br /><span class="token selector">.cool-text-interactive</span> <span class="token punctuation">{</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> $color-text-interactive<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><span class="token selector">.cool-text-subdued</span> <span class="token punctuation">{</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> $color-text-subdued<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><span class="token atrule"><span class="token rule">@media</span> <span class="token punctuation">(</span><span class="token property">prefers-color-scheme</span><span class="token punctuation">:</span> dark<span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br /> <span class="token selector">.cool-text-interactive</span> <span class="token punctuation">{</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> $color-text-interactive-inverse<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /> <span class="token selector">.cool-text-subdued</span> <span class="token punctuation">{</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> $color-text-subdued-inverse<span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<h2>The finished markup</h2>
<p>Here's what we end up with for our refactored markup.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>figure</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cool-card cool-flex-responsive<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">--flex-gap</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span> <span class="token property">--flex-align</span><span class="token punctuation">:</span> stretch</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cool-avatar cool-margin-auto-on-small cool-margin-block-start-on-small<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">--width</span><span class="token punctuation">:</span> 12rem</span><span class="token punctuation">"</span></span></span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://assets.codepen.io/281/sarah-dayan_1.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token attr-name">width</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>384<span class="token punctuation">"</span></span> <span class="token attr-name">height</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>512<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cool-flow cool-text-center-on-small cool-inset-square-32<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">align-self</span><span class="token punctuation">:</span> center</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>blockquote</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cool-text-large<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>p</span><span class="token punctuation">></span></span><br /> βTailwind CSS is the only framework that I've seen scale<br /> on large teams. Itβs easy to customize, adapts to any design,<br /> and the build size is tiny.β<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>p</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>blockquote</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>figcaption</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cool-text-interactive<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> Sarah Dayan<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cool-text-subdued<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><br /> Staff Engineer, Algolia<br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>figcaption</span><span class="token punctuation">></span></span><br /> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span><br /><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>figure</span><span class="token punctuation">></span></span></code></pre>
<p>At a glance this doesn't look much more concise than the Tailwind example, until you actually view the source on the Tailwind example and see all of the utility classes and inline styles they actually used that they don't show in the code sample. Here's just the image element, for example:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/_next/static/media/sarah-dayan.de9b3815.jpg<span class="token punctuation">"</span></span> <span class="token attr-name">decoding</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>async<span class="token punctuation">"</span></span> <span class="token attr-name">alt</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>absolute max-w-none object-cover bg-slate-100 rounded-full<span class="token punctuation">"</span></span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span> <span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span> <span class="token property">left</span><span class="token punctuation">:</span> 0px<span class="token punctuation">;</span> <span class="token property">top</span><span class="token punctuation">:</span> 0px<span class="token punctuation">;</span> <span class="token property">transform-origin</span><span class="token punctuation">:</span> 50% 50% 0px<span class="token punctuation">;</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span></code></pre>
<p>The end code, however, results in fewer classes overall, is easier to parse what the classes are doing and allows for less repetition when reusing these styles in different contexts.</p>
<p>You can find the final example on <a href="https://codepen.io/peruvianidol/pen/VwEqERR?editors=1100">CodePen</a>.</p>
<h2>Wrapping up</h2>
<p>I actually started this post as part two of my <a href="https://mikeaparicio.com/posts/2023-02-17-design-system-diary-part-1/">Design System Diary</a> series, but it became this epic preamble before I even got to talking about building Turquoise Health's CSS framework. I ended up breaking it off into its own thing and adding a practical example so the article wasn't just me complaining about CSS frameworks that I didn't write (an integral part of my personal brand).</p>
<p>In the next Design System Diary I'll go into more detail about how our CSS framework is organized and some of the other techniques I use to keep the framework light and hopefully meet our goal of our devs never having to write CSS.</p>
<p>I should also say that if this post doesn't resonate with you and your current method of writing CSS is working out for you, congratulations! <a href="https://mikeaparicio.com/posts/2021-11-24-its-your-website/">It's your website.</a></p>
Our Dear Geno
2023-03-26T00:00:00Z
https://mikeaparicio.com/posts/2023-03-26-our-dear-geno/
<p>Our hearts are broken. On Thursday night our beloved dog, Geno, passed away. He had been sick for a few months but the last couple of weeks really took their toll on him.</p>
<style>
.scroller {
overflow-x: scroll;
overflow-behavior-x: contain;
scroll-snap-type: x proximity;
}
.scroller ul {
display: flex;
gap: 8px;
align-items: center;
}
.scroller li {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
scroll-snap-align: center;
inline-size: 100%;
max-inline-size: 20rem;
max-block-size: 300px;
border-radius: 4px;
overflow: hidden;
}
</style>
<div class="scroller">
<ul role="list">
<li><a href="https://mikeaparicio.com/images/geno-1.jpg"><img src="https://mikeaparicio.com/images/geno-1.jpg" alt="Geno laying on the couch" /></a></li>
<li><a href="https://mikeaparicio.com/images/geno-2.jpg"><img src="https://mikeaparicio.com/images/geno-2.jpg" alt="Geno wanting to play fetch" /></a></li>
<li><a href="https://mikeaparicio.com/images/geno-3.jpg"><img src="https://mikeaparicio.com/images/geno-3.jpg" alt="Geno sitting like a person on the couch next to Ryan" /></a></li>
<li><a href="https://mikeaparicio.com/images/geno-4.jpg"><img src="https://mikeaparicio.com/images/geno-4.jpg" alt="Geno snuggling with his toy" /></a></li>
</ul>
</div>
<p>Gee-Gee was the best guard dog, an eager snuggler, incredibly patient and gentle with the kids, and integral part of our family. We love him and miss him so much.</p>
Fun with Retro Handhelds
2023-02-21T00:00:00Z
https://mikeaparicio.com/posts/2023-02-21-fun-with-retro-handhelds/
<p>My son Ryan recently turned four years old and had a Super Mario-themed birthday. In the past six months or so he's gone from being obsessed with Thomas the Tank Engine to becoming obsessed with Mario. He was Mario for Halloween and has Mario-themed bedding topped with a metric ton of Mario plushes, or "stuffies."</p>
<h2>How did we get here?</h2>
<p>It all started when he spotted a Nintendo Game and Watch with the original NES Super Mario Bros. on it. He asked me what it was and I let him try it out and he was instantly hooked. After about a month, he beat level 1-1 all by himself. He was so excited!</p>
<p>Super Mario Bros. is an all-time classic. It's really a master class in game design. You learn the mechanics in a very subtle way and each level adds new enemies and traps and requires you to learn new ways to beat them. But when you think about it, it's also really challenging, particularly for a (then) three-year-old. It's like the Dark Souls of platformers.</p>
<p>In the mid-80s, we were still in the heyday of arcade games and those games were designed to get you to keep pumping quarters into the machine. Super Mario Bros. follows this same pattern, starting you with three lives. If you use up those lives, you have to start over from the beginning.</p>
<p>So for Christmas I was thinking about how to transition him to more forgiving Mario games like Super Mario World on SNES. Super Mario World had a lot more opportunites to get extra lives and also allowed to you save your progress. For my money it's still the perfect Mario game.</p>
<p>I had heard about a number of retro handheld devices that were gaining popularity and decided to check a few out to see which one might be a good fit for Ryan and, well, let's just say I got a little carried away.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/lpjUkFKsK7-300.webp 300w, https://mikeaparicio.com/images/lpjUkFKsK7-600.webp 600w, https://mikeaparicio.com/images/lpjUkFKsK7-3813.webp 3813w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/lpjUkFKsK7-300.jpeg 300w, https://mikeaparicio.com/images/lpjUkFKsK7-600.jpeg 600w, https://mikeaparicio.com/images/lpjUkFKsK7-3813.jpeg 3813w" sizes="100vw" /><img alt="A collection of gaming systems." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/lpjUkFKsK7-300.jpeg" width="3813" height="2305" /></picture>
<figcaption>
(Left to right) Top row: Anbernic RG351P, Nintendo Switch Lite, Nintendo Game and Watch (Mario)<br />
Middle row: Retriod Pocket 3+, Nintendo Switch, Miyoo Mini v2<br />
Bottom row: PlayStation Classic, Valve Steam Deck, Anbernic RG353V
</figcaption>
</figure>
<h2>An embarassingly large collection of retro handhelds π³</h2>
<p>Here are a bunch of devices I now own that can play a ton of games from past generations of gaming systems. There's a pretty wide range of pros/cons and price points, but if you're interested in reliving your childhood with some classic games, you should find something here that fits your needs/budget.</p>
<h3>Nintendo Game and Watch</h3>
<p>$45</p>
<p>These come in two different flavors β <a href="https://www.nintendo.com.au/products/game-and-watch-super-mario-bros">Mario</a> and <a href="https://www.nintendo.com/store/products/game-watch-the-legend-of-zelda/">Zelda</a>. The Mario one comes with Super Mario Bros., Super Mario Bros: The Lost Levels (a freakishly hard successor to SMB that originated in Japan as Super Mario Bros 2), and a classic Game and Watch juggling game.</p>
<p>The Zelda one comes with The Legend of Zelda, Zelda II: The Adventure of Link, and The Legend of Zelda: Link's Awakening, as well as a classic Game and Watch whack-a-mole-type game.</p>
<p>I love the retro aesthetic of these but for not much more money you can get a device that can play all of these games and hundreds more.</p>
<h3>Miyoo Mini v2</h3>
<p>$70</p>
<p>The <a href="https://miyoominiv2.com/">Miyoo Mini v2</a> was the first device I bought and ultimately the one I decided to give to Ryan for Christmas. It's incredibly small and fits easily into just about any pocket. It might even be too small for an adult's hands but for Ryan it's perfect. It looks like a super tiny Game Boy and I love it.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/1rIP-1osYi-300.webp 300w, https://mikeaparicio.com/images/1rIP-1osYi-600.webp 600w, https://mikeaparicio.com/images/1rIP-1osYi-3024.webp 3024w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/1rIP-1osYi-300.jpeg 300w, https://mikeaparicio.com/images/1rIP-1osYi-600.jpeg 600w, https://mikeaparicio.com/images/1rIP-1osYi-3024.jpeg 3024w" sizes="100vw" /><img alt="A Miyoo Mini v2 in white. It looks like a miniature Game Boy. The Super Mario World title screen is playing." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/1rIP-1osYi-300.jpeg" width="3024" height="4032" /></picture>
<figcaption>
The Miyoo Mini v2 or, as Ryan calls it, "my white game."
</figcaption>
</figure>
<p>This thing can play just about any console up to PlayStation 1, including NES, SNES, Genesis, Game Boy and Game Boy Advance, to name a few. Like many of the cheaper handhelds, it comes pre-loaded with a bunch of games, but a lot of them are junky and the games are arbitrarily numbered instead of listed alphabetically.</p>
<p>With a little bit of effort, you can find and load just about any game you can think of relatively easily. There's also a number of different custom operating systems you can load onto the Miyoo Mini. I went with <a href="https://github.com/shauninman/MiniUI">MiniUI</a>, which is a super-minimal OS created by Shaun Inman. It's a intuitive enough for a toddler to figure out.</p>
<p>The biggest drawback of the Miyoo Mini v2 is it's availability. While the original MSRP is about $70, it's been incredibly hard to come by because of its popularity combined with supply chain issues. It was recently discontinued in favor of the upcoming Miyoo Mini v3, which includes a larger screen. You can still find these, but expect to pay double or even triple the list price.</p>
<h3>Anbernic RG35XX</h3>
<p>$56</p>
<p>A better bet might be the <a href="https://anbernic.com/products/rg35xx">Anbernic RG35XX</a>. Similarly priced to the Miyoo Mini, the RG35XX is slightly larger but has a similar form factor and supports pretty much the same consoles (if not more). It also supports wireless and wired external gamepads and includes an HDMI out so you can hook it up to a TV. Best of all, you can actually find one for less than $60. I just ordered one of these recently, as if I didn't have enough handhelds already.</p>
<h3>Anbernic RG353V</h3>
<p>$120</p>
<p>The <a href="https://anbernic.com/products/rg353v-rg353vs">Anbernic RG353V</a> is almost identical to the RG35XX but can play a few newer consoles like Dreamcast and N64. It also has two analog joysticks on the bottom to support those newer consoles. You can also run Android on it and play Android games, though I haven't tested this yet. It costs twice as much as the RG35XX, but if you really want to play those other consoles, you might find it worth the extra price.</p>
<h3>Anbernic RG351P</h3>
<p>$95</p>
<p>The <a href="https://anbernic.com/products/rg351p-anbernic-retro-game-ps1-rk3326-64g-open-source-system-3-5-inch-ips-screen-portable-handheld-game-console-rg351gift-2401">Anbernic RG351P</a> is kind of in the middle, price- and feature-wise between the RG35XX and RG353V. It has its controls on the sides of the screen instead of below, giving it more of a Nintendo Switch feel. The RG351P doesn't include HDMI out but it does support the same systems as the RG353V. I kind of like the more modern form-factor of this one.</p>
<h3>Retroid Pocket 3+</h3>
<p>$150</p>
<p>I really love the form-factor of the <a href="https://www.goretroid.com/products/retroid-pocket-3-handheld-retro-gaming-system-1">Retroid Pocket 3+</a>. It's very much like a smaller Nintendo Switch Lite. It's a bit more powerful than any of the Anbernic devices I've tried, allowing it to play GameCube, PS2, Nintendo Wii and 3DS games, as well as Android games. And because it's an Android device, you can download apps to stream XBox Series X and PS5 games. This might be the best retro handheld for the money.</p>
<h3>Nintendo Switch / Switch Lite</h3>
<p>$200 (Lite) / $300 / $350 (OLED)</p>
<p>While not specifically a retro handheld, the <a href="https://www.nintendo.com/switch/">Nintendo Switch</a> does offer a bunch of retro games via Nintendo Online for NES, SNES, N64, Game Boy and Game Boy Advance, and even Sega Genesis. While you can't play your own games, Nintendo's collections feature a lot of the best games from those systems. As an added benefit, you can play a ton of modern games on the go as well.</p>
<p>For Ryan's birthday party, I set up my Switch, which I hadn't played in years and loaded up a bunch of modern Mario games on it and he loves it. He's mostly bouncing between Super Mario Maker 2, Mario Kart 8, and Super Mario Bros. U Deluxe.</p>
<h3>Valve Steam Deck</h3>
<p>$400β$650</p>
<p>If money is no object, Valve's <a href="https://store.steampowered.com/steamdeck">Steam Deck</a> might be the best portable gaming device you can buy. This thing is basically a portable PC and, as such, it can emulate just about anything as well as playing triple-A PC games like Elden Ring or Spider-Man without a hitch.</p>
<p>I picked one up when I got my Facebook settlement money (thanks Zuck!) and it's pretty great. It's the beefiest of these handhelds, almost to the point of being unweildy, but there's almost nothing it can't do.</p>
<h3>PlayStation Classic</h3>
<p>$100</p>
<p>Finally, I saw <a href="https://youtu.be/PT6viXtCBg0">a video</a> where someone turned a <a href="https://blog.playstation.com/2018/09/18/introducing-playstation-classic-with-20-pre-loaded-games/">PlayStation Classic</a> β one of those mini retro consoles that were all the rage a few years ago β into a full-fledged retro gaming console. I happened to have one unopened in my attic so I brought it down and tried it out. It was actually pretty good and because of its USB ports, I was able to hook up a PlayStation 5 controller wirelessly. And while it isn't handheld, it might be a good option if you're looking to get into retro gaming but prefer to play on a TV.</p>
<p>These are discontinued but you can find them pretty easily online, sometimes even cheaper than their original $100 retail price. This might have been the biggest dud of all the retro consoles due to its weak collection of titles.</p>
<h2>Getting Started</h2>
<p>Many of these systems come with an underwhelming selection of games pre-loaded (if any at all), and for good reason. The legality of video game emulation is iffy, to say the least. Most articles/videos won't tell you how to get all the cool games they're demoing and will issue the disclaimer that you should only use legal backups of games you've already purchased.</p>
<p>But, c'mon, anyone who spent 20 minutes in the 90s downloading a single song on Napster is probably not gonna think twice about grabbing a bunch of ROMs (game files) off the Internet.</p>
<p>That said, I'll just say that there's a subreddit called "Roms" and they have a "megathread" and if you can find that through some kind of search engine, then you're golden.</p>
<p>Aside from that, there's some great content creators that have reviews and guides on many of the systems above as well as a bunch of others that are available β and there are <strong>a lot</strong>.</p>
<p><a href="https://retrogamecorps.com/">Retro Game Corps</a> has the most in-depth reviews and guides I've found so far. I was able to get all the various custom operating systems and emulation software setup without much effort. They recently released a great video intro to retro handheld gaming.</p>
<figure>
<iframe src="https://www.youtube.com/embed/cYvT-AiGaCk" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</figure>
<p>Wulff Den also has great reviews and recently did one on the Anbernic RG35XX, calling it the best, cheap retro handheld that's actually available.</p>
<figure>
<iframe src="https://www.youtube.com/embed/jjtjWyWk90I" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</figure>
<h2>The irony of retro handheld gaming</h2>
<p>So which of these devices do I play the most? None of them, really. I'm home so often that I usually opt to play on PlayStation 5. And while Ryan loves playing all these games, they're all new to him. For me, I spent months or even years playing some of them as a kid, but games evolved to the point where playing many of them now just feels tedious.</p>
<p>I gotta say though, a lot of Nintendo games, particularly Mario games, really hold up. I've enjoyed helping Ryan when he gets stuck and playing two-player games with him on the Switch. It's so much fun reliving my childhood through him. Even if my wife would rather I didn't. π
</p>
<p>Have you dipped into retro gaming? What games are you playing? <a href="https://mikeaparicio.com/contact/">Let me know</a>!</p>
Design System Diary (Part 1)
2023-02-17T00:00:00Z
https://mikeaparicio.com/posts/2023-02-17-design-system-diary-part-1/
<p>I started my new role as Principal Design Systems Engineer at <a href="https://turquoise.health/">Turquoise Health</a> just over a month ago and thought it might be useful/interesting to document my process of building a design system from scratch.</p>
<h2>Design System Deck</h2>
<p>One of the first things I like to do when starting a new design system is make a Keynote deck about design systems and my approach to building them, as well as my plan for how we'll build this specific design system. Every company is different β products, needs, personnel, tech stack, etc. β but a lot of the foundations of building a design system are similar.</p>
<p>I try to make this deck accessible to folks of different disciplines, so that people can get a basic understanding of design systems and the value they create regardless of whether they are actually working to design/build the product. The deck also serves as a great onboarding tool when new people join the company.</p>
<p>The basic structure of the deck is:</p>
<ol>
<li>Why companies struggle with getting a design from concept to production</li>
<li>What are design systems and how to they help solve this struggle</li>
<li>What is the plan for building <em>our</em> design system</li>
<li>How will we support and iterate on the design system once it's built</li>
</ol>
<p>I've <a href="https://mikeaparicio.com/tag/design-systems/">written previously</a> about 1 & 2 so I'll mostly write about the process of building and supporting the system in this series.</p>
<h2>Design System 1:1s</h2>
<p>Identifying key stakeholders starts in the interview process, before you even get hired. Figure out who is driving product decisions and who are the folks responsible for designing/developing the product. Some people's eyes might light up at the mere mention of design systems. These are your people. They will help build and advocate for the design system.</p>
<p>One you start the job, one-on-ones are a great way to get a better sense of what the existing process of building the product is like and getting honest feedback about what's working and what's not working.</p>
<p>They're also helpful in understanding and aligning people's expectations. What will the system do? How long will it take to get there? How will we measure success? What does failure look like?</p>
<p>Brad Frost has a great set of <a href="https://bradfrost.com/blog/post/design-system-interview-questions/">design system interview questions</a> that I use as a reference.</p>
<h2>Visual Design Audit</h2>
<p>This is where I dig into the product and the designs to identify all the different visual styles in use (type, spacing, color, icons, etc.) and try to narrow them down into a discrete set of values. What are all the values we're using and in what contexts are we using them? Can we consolidate similar colors/sizes? Do the color combinations we're using have sufficient contrast?</p>
<h2>Design Tokens</h2>
<p>Once we've established our visual style values, we can store them in design tokens. The design tokens can be consumed by different design and development tools to help keep the values our designers and developers are using in sync, regardless of the technology they're using to implement them. (Figma, CSS, JSON, etc.)</p>
<p>I wrote more about tokens in this post about a hackathon called <a href="https://mikeaparicio.com/posts/2020-07-06-simple-groupon/">Simple Groupon</a>.</p>
<h2>UI Kit</h2>
<p>I often say that if your design system is primarily engineering-driven (a component library/CSS framework) and the designers aren't designing with the system, then you don't have a design system. It's crucial that the designers have an equivalent library of components in their tools (Figma/Sketch) that allows them to create new designs that align with the tools developers are building the product with. Otherwise your component library is going to be constantly growing as designers add new features that deviate from existing styles.</p>
<p>A big part of my job is meeting regularly (at least once a week) with designers to get a sense of what they're working on and determining if anything needs to be added/updated in the system.</p>
<p>I was extremely pleased to discover that Turquoise's designer (shoutout Rob!) had already developed a comprehensive UI Kit in Figma that was extremely well thought out and organized. It's going to make building out the supporting CSS framework much easier than if we needed to start a kit from scratch.</p>
<h2>What's next on the roadmap?</h2>
<p>It can be incredibly daunting to come into a company as the only design systems person and figure out where to start building a design system. You might be inclined to make a laundry list of things you want the system to include, only to struggle to get its implementation on the product roadmap.</p>
<p>Dan Donald recently asked on Twitter:</p>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">What would you consider an MVP to be for a design system π€</p>— Dan | Design Advocate @zeroheight (@hereinthehive) <a href="https://twitter.com/hereinthehive/status/1626313268028403720?ref_src=twsrc%5Etfw">February 16, 2023</a></blockquote>
<p>My response: "Whatever you need to support the next feature on the roadmap."</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/trtZ4rvezS-300.webp 300w, https://mikeaparicio.com/images/trtZ4rvezS-600.webp 600w, https://mikeaparicio.com/images/trtZ4rvezS-781.webp 781w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/trtZ4rvezS-300.jpeg 300w, https://mikeaparicio.com/images/trtZ4rvezS-600.jpeg 600w, https://mikeaparicio.com/images/trtZ4rvezS-781.jpeg 781w" sizes="100vw" /><img alt="Drake meme with Drake saying no to 'Get design system work on the roadmap' and yes to 'Let the roadmap inform the design system work'" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/trtZ4rvezS-300.jpeg" width="781" height="587" /></picture>
</figure>
<p>By letting the roadmap inform your design system, it will help you focus on just the things you need in the system <em>right now</em>. All of the visual styles, icons, components, etc. that you need to support the next feature become a tiny design system. When building the next feature, you'll already have a solid foundation and each successive feature you support will require less and less work to add to the system, allowing your team to ship things faster and faster.</p>
<p>I've found that it's much easier to get support for this approach than trying to convince people to add design system work to the roadmap.</p>
<h2>From prototype to design system</h2>
<p>Once I've identified the next feature on the roadmap, it's time to start building! I like to do this work in <a href="https://codepen.io/">CodePen</a>. I have a template that I use that's blank except for pulling in the design system's CSS framework. (Of course, for this first feature, we don't have a framework yet!)</p>
<p>I write all of the markup and styles that I need to accurately reproduce the design. This includes tokens (as CSS custom properties) and icons (as an SVG sprite).</p>
<p>It's incredibly useful to build out the entire page layout of the feature so that the prototype looks like a complete page that the user will interact with. It also has the benefit of being reused across other pages/features. It may be useful during the visual style audit to note all of the different layouts in use and try to narrow them down into a few different types.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/RY4e4mTeJr-300.webp 300w, https://mikeaparicio.com/images/RY4e4mTeJr-600.webp 600w, https://mikeaparicio.com/images/RY4e4mTeJr-1440.webp 1440w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/RY4e4mTeJr-300.jpeg 300w, https://mikeaparicio.com/images/RY4e4mTeJr-600.jpeg 600w, https://mikeaparicio.com/images/RY4e4mTeJr-1440.jpeg 1440w" sizes="100vw" /><img alt="An example of a page layout." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/RY4e4mTeJr-300.jpeg" width="1440" height="810" /></picture>
</figure>
<p>This is even more crucial as the company grows and the product team splits off into smaller teams dedicated to a single part of the product. Often there isn't a team responsible for shared parts of the site that all the teams use like layouts and icons.</p>
<p>Once the prototype is built, I share it with designers, engineers and product managers to get feedback and make adjustments as needed. They can view the prototype on different devices, see the code and make changes while seeing the prototype update live.</p>
<p>When everyone has signed off on it, whatever additional styles I added that didn't already exist in our CSS framework get added to the framework. When I release a new version the template, using the latest CSS, I can safely remove all of the CSS from CodePen and the prototype should still look the same.</p>
<p>From here, the engineering team can take the prototype and build out the functionality of the feature without having to worry about what it looks like. Instead of delivering a picture of a website, we're delivering production-ready markup and styles.</p>
<h2>Supporting the design system</h2>
<p>Even before getting started on building the system, it's important to let everyone know that you are there to support them and establishing a number of methods for people to get support. In <a href="https://mikeaparicio.com/posts/2022-12-12-design-system-advice/">Design System Advice</a> I wrote about adopting a service mentality:</p>
<blockquote>
<p>Working on design systems, your customers are not your company's customers. Your customers are designers, engineers and product managers. Your job is to help make their jobs easier.</p>
<p>Look for opportunities to connect with these customers.</p>
<ul>
<li>
<p>Establish regular office hours where people can drop in and ask questions, pair on solutions or just hang out and get to know you.</p>
</li>
<li>
<p>Make a dedicated Slack channel where people can ask questions and get support. Even if you're a solo design system team, having people ask in a channel rather than a DM allows other people who might know the answer to help out and is easier to reference than private conversations.</p>
</li>
<li>
<p>Make yourself available for questions and 1:1 sessions.</p>
</li>
<li>
<p>Get feedback via surveys and/or quarterly retrospectives. Soliciting feedback can be challenging, but it's important to give people that opportunity, even if they don't take advantage of it.</p>
</li>
<li>
<p>Evangelize the system through brown bags, lunch and learns, company all-hands β any opportunity to address large groups in the company who might not be familiar with you or the work you do.</p>
</li>
<li>
<p>Let people know that you're there to make their jobs easier. They love that!</p>
</li>
</ul>
</blockquote>
<h2>What's next?</h2>
<p>Once our first prototype is done, I'll be working on building out the CSS framework and documentation site, which I'll cover in the next part.</p>
<p>Do you have questions? Anything you'd like to see me write more about? <a href="https://mikeaparicio.com/contact/">Let me know</a>!</p>
Imagine
2023-01-15T00:00:00Z
https://mikeaparicio.com/posts/2023-01-15-imagine/
<p>Imagine youβre a fan of a professional basketball team. Youβve followed the team for more than a decade, been through ups and downs and, while the team never won a title they were fun to watch and you made a lot of friends, bonding over your shared love of the team.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/snPQWrYwMZ-300.webp 300w, https://mikeaparicio.com/images/snPQWrYwMZ-600.webp 600w, https://mikeaparicio.com/images/snPQWrYwMZ-4032.webp 4032w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/snPQWrYwMZ-300.jpeg 300w, https://mikeaparicio.com/images/snPQWrYwMZ-600.jpeg 600w, https://mikeaparicio.com/images/snPQWrYwMZ-4032.jpeg 4032w" sizes="100vw" /><img alt="A view inside the United Center. The stadium is packed and the game is about to tip off." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/snPQWrYwMZ-300.jpeg" width="4032" height="3024" /></picture>
</figure>
<p>Every now and then a rowdy fan would fan would interrupt the game, often more frequently in specific sections of the arena, but most the time theyβd get shouted down by the rest of the crowd, or sometimes be banned from attending games by team security.</p>
<p>Then, one day, a tech billionaire buys the team. This guy knows jack shit about basketball. He starts trading away your favorite players or just outright cutting them, all as a cost saving measure. The team quickly becomes no fun to watch.</p>
<p>On top of that, he starts unbanning the assholes who would ruin the game with their shitty behavior, mostly because heβs an asshole himself. And the team is so bad now that thereβs fewer fans to shout them down.</p>
<p>But you still go to the games even though your friends stopped going and tell you the team sucks and that the team is owned by a literal N*zi and that you should feel bad for still being a fan.</p>
<p>They tell you about their new favorite team, a minor league team that plays in a smaller arena, sure, but still has a passionate and growing fan base. Like they wonβt shut up about it. So you decide to get tickets to a game but you feel like youβre betraying your favorite team.</p>
<p>You go to the game and itβs quickly apparent that no one on the team is over six feet tall. Thereβs signs near the court that read NO DUNKING. When you cheer for a good play, some people turn in their seat to shush you. We donβt cheer like that here, they say.</p>
<p>So you go back to your old team and it fucking still sucks. The owner decided to revoke your season ticket so you have to buy single game tickets and your seat is considerably worse. Thereβs a pole blocking your view. You never realized how many poles this arena has.</p>
<p>Anyway thatβs what itβs like to be on Twitter now. Thank you for coming to my TED Talk.</p>
2022
2023-01-01T00:00:00Z
https://mikeaparicio.com/posts/2023-01-01-2022/
<p>2022 seemed to be the year where things finally started to look up after years of Covid threw everyone's lives through a loop. In <a href="https://mikeaparicio.com/posts/2022-01-01-2021/">last year's recap</a> I listed several things I was looking forward to in the coming year and, much to my surprise, they all happened and then some.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/ng_xdBFELJ-300.webp 300w, https://mikeaparicio.com/images/ng_xdBFELJ-600.webp 600w, https://mikeaparicio.com/images/ng_xdBFELJ-3024.webp 3024w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/ng_xdBFELJ-300.jpeg 300w, https://mikeaparicio.com/images/ng_xdBFELJ-600.jpeg 600w, https://mikeaparicio.com/images/ng_xdBFELJ-3024.jpeg 3024w" sizes="100vw" /><img alt="Baby Owen in flannel jammies" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/ng_xdBFELJ-300.jpeg" width="3024" height="4032" /></picture>
<figcaption>
Owen in his natural state of chill.
</figcaption>
</figure>
<p><strong>Owen.</strong> On May 25, our son <a href="https://mikeaparicio.com/posts/2022-06-08-owen/">Owen was born</a>! We were so blessed to add another healthy baby boy to our family. He's a happy and chill little guy. It's been a lot of fun watching him grow and start to form his personality over the last seven months. It's uncanny how much he looks like Ryan. Some people have even asked how we managed to make two of the same baby.</p>
<p><strong>Ryan.</strong> A month shy of four years old, Ryan has really turned into a little person. This year he became obsessed with Mario. I have this Nintendo Game and Watch with the original NES Super Mario Bros on it and he picked it up one day and started playing it. Within a month or so, he was able to beat the first level by himself, and shortly after that, he was using the secret warp pipe in 1-2 to go to different worlds.</p>
<figure class="ma-float-left">
<video controls="">
<source src="https://mikeaparicio.com/assets/videos/ryan-mario.mp4" type="video/mp4" />
</video>
<figcaption>
It's a me, Ryan!
</figcaption>
</figure>
<p>He started collecting all things Mario after that and was even Mario for Halloween. He wore the costume for at least an entire month. His previous obsession, Thomas the Train, is still on his radar but he'll now go weeks without even touching a train.</p>
<p>I bought him a <a href="https://www.youtube.com/watch?v=lLiT21Ddnuk">Miyoo Mini v2</a> retro handheld for Christmas and loaded a bunch of Super Nintendo games on it and he's loving it so far. (Allie, not so much.) I thought maybe Super Mario World might be a little more forgiving with more ways to get extra lives and having save states. The original Super Mario Bros is hard! It's like the Dark Souls of platformers.</p>
<p><strong>Joe.</strong> My stepson graduated from high school the same week Owen was born, which was wild, and quite emotional for my wife. The last few years were challenging for Joe, but he hung in there and now he's really turned things around. He's going to junior college and made the baseball team there. Things have been calmer around the house and he's been enjoying being a big brother to Ryan and Owen. I'm so proud of him.</p>
<figure class="ma-float-right">
<video controls="">
<source src="https://mikeaparicio.com/assets/videos/bathroom-renovation.mp4" type="video/mp4" />
</video>
</figure>
<p><strong>We finished the bathroom.</strong> This has been on the "looking forward to list" for the last two years and we <strong>FINALLY</strong> got it finished! It cost a bit more than we budgeted for, but I'm very pleased with the improved water pressure (it's the best shower I've ever had at home), heated tiles, and a Toto bidet toilet with <em>Tornado Flushβ’ Technology</em>. We also added a pocket door so we could add a large cabinet with some shelf space, which I decided would be the perfect place for a small monitor and my PS5. Allie wasn't having it though.</p>
<p><strong>I finally left Illinois β twice!</strong> OMG, it felt so good to finally go more than an hour drive away from my house for the first time in almost three years. In September we went to Florida to visit my in-laws. My dad and stepmom also happened to be vacationing in Florida, so we were able to meet up with them at my cousin's house in Tampa as well. It was the first time I'd seen them since Ryan was six months old. They were very excited to see the boys. I'm not a beach guy, but I did enjoy being away from home. We barely dodged Hurricane Ian on the way out!</p>
<figure class="ma-float-left">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/WRrBMNV40l-300.webp 300w, https://mikeaparicio.com/images/WRrBMNV40l-600.webp 600w, https://mikeaparicio.com/images/WRrBMNV40l-2720.webp 2720w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/WRrBMNV40l-300.jpeg 300w, https://mikeaparicio.com/images/WRrBMNV40l-600.jpeg 600w, https://mikeaparicio.com/images/WRrBMNV40l-2720.jpeg 2720w" sizes="100vw" /><img alt="My dad and stepmom in matching his and hers Miami hoodies." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/WRrBMNV40l-300.jpeg" width="2720" height="2041" /></picture>
<figcaption>
Maybe the most adorable picture of my dad and stepmom ever.
</figcaption>
</figure>
<p>In November I attended <a href="https://www.clarityconf.com/">Clarity Conference</a> in New Orleans. Clarity is a design systems conference I've attended a few times before. The last two years were entirely online but this year was both online and in person, and I couldn't miss an opportunity to visit New Orleans for the first time. It was great connecting with a bunch of folks that work on design systems and I enjoyed all the food and drinks the city had to offer.</p>
<p><strong>We raised $5,650 for Extra Life.</strong> For the second year in a row I did a 12-hour stream to celebrate Olivia's birthday in August and it was another success. However, I think splitting the fundraising between her birthday and the official Extra Life game day (first Saturday of November) isn't as effective. This year I raised a little less than last year but I'm proud that over the past nine(!) years we've been able to raise <strong>$38,475</strong> for Lurie Children's Hospital in Olivia's name. I'm extremely grateful to Bert for coming over every year and playing the whole 24 hours, and to Jose for helping me power through those late hours with some Call of Duty Spec Ops. Thank you so much to all of you who donated to the cause. We really appreciate your kindness.</p>
<p><strong>We finally got Covid.</strong> It was bound to happen eventually, but the timing really sucked. I tested positive the Tuesday before Thanksgiving, and my wife tested positive the next day. A week later Owen tested positive, shortly after getting over RSV, and it was compounded by an ear infection. Ryan was seemingly spared, but he had pink eye around the same time, and my wife got it too. And then she got strep! So we were pretty much sick constantly for a month. It was brutal. I still can't shake this upper chest congestion that causes me to cough constantly. Hoping we don't get it again any time soon.</p>
<p><strong>I started mentoring.</strong> I joined <a href="https://app.adplist.org/">ADPList</a> as a mentor a few months ago and have been having some great conversations with people trying to grow their careers in both design and engineering. A lot of common themes come up around design systems, so I wrote an article with some <a href="https://mikeaparicio.com/posts/2022-12-12-design-system-advice/">design system advice</a> that I've shared with them.</p>
<p><strong>I got a new job.</strong> I've been feeling pretty stagnant in my career for awhile now. I've been stuck at Senior Engineer for the past five years or so, despite my work impacting just about every feature that gets shipped. Donnie D'Amato recently wrote a great piece about <a href="https://blog.damato.design/posts/terminal-career/">the challenges of working between design and engineering</a> that really resonated with me.</p>
<p>I had been open to new opportunities, if not actively seeking them, for awhile. In November, Provi announced layoffs and, while I was spared, it only further motivated me to find a new role. Coincidentally, that same day, a former Groupon colleague reached out to ask if I knew anyone who does what I do, to which I replied, "yeah, me!"</p>
<p>My conversations with the team went great, and I'm happy to announce that starting this month, I will be the <strong>Principal Design Systems Engineer</strong> at <a href="https://turquoise.health/">Turquoise Health</a>! Turquoise is fully remote but each quarter they get together in a different city. I'm looking forward to meeting the team in Los Angeles in a few weeks!</p>
<h2>Things I loved in 2022</h2>
<h3>Movies</h3>
<p>I had a really hard time staying awake to watch movies in 2022. This year's <a href="https://letterboxd.com/peruvianidol/list/movie-a-year-challenge-2022/">Movie a Year Challenge</a> fell by the wayside around the time Owen was born. It was taking me multiple nights to watch a single movie. I ended up taking comfort in old favorites and a lot of the new releases I enjoyed this year were fun, action romps, with a few notable exceptions.</p>
<p><strong>RRR</strong> This movie slaps so fucking hard. Wildly entertaining and over-the-top but made with such an endearing earnestness it's impossible not to love. The ultimate action bromance to end all action bromances. When a movie opens with a disclaimer that at least a dozen species of wild animals were not harmed during the making of the film, you know you're in for some shit.</p>
<figure>
<iframe src="https://www.youtube.com/embed/OsU0CGZoV8E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<figcaption>Do you even Naatu, bro?</figcaption>
</figure>
<p><strong>The Batman</strong> I can't help but love <em>almost</em> any iteration of Batman. I <strong>loved</strong> Matt Reeves' grounded take. Great cast, particularly Robert Pattinson as Emo Batman. Some argue The Batman is too self-serious, but I found it to be a refreshing change of pace from all the cynical quipping of Marvel movies and their copycats. If nothing else, this is certainly the horniest Batman movie.</p>
<p><strong>Top Gun: Maverick</strong> Who would have guessed a sequel to a 35-year-old movie would be the biggest thrill ride of the summer? Incredible aerial photography sequences made you feel like you were in the jets with the characters. Absolutely exhilarating. And some surprising emotional moments really hit home.</p>
<p><strong>Everything Everywhere All at Once</strong> This relatively low-budget film from the creators of Swiss Army Man absolutely blew me away. A fantastic showcase for Michelle Yeoh and, holy cow, Ke Huy Quan β best known for his roles as Short Round in Indiana Jones and the Temple of Doom and Data in The Goonies. He's perfect here, effortlessly shifting between milquetoast husband, martial arts expert, and a suave, Tony Leung in a tux vibe.</p>
<p><strong>The Unbearable Weight of Massive Talent</strong> Another great action bromance. This is maybe the funniest Nicholas Cage has been since Raising Arizona. Pokes fun at the various stages of Cage's prolific career in such a delightful way. Pedro Pascal is perfect in this.</p>
<figure>
<iframe src="https://www.youtube.com/embed/zCiieqzqCHo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</figure>
<p><strong>Decision to Leave</strong> A fantastically horny noir from director Park Chan-wook (The Handmaiden, Oldboy) that's like a cross between Vertigo and In the Mood for Love. This movie continues to haunt me weeks after watching it. So many incredible shots.</p>
<p><strong>Others worth mentioning</strong>: I loved seeing Martin McDonagh reunite with his In Bruges stars Colin Farrell and Brendan Gleeson in <strong>Banshees of Inisherin</strong>, a film gorgeously shot on a remote Irish island about two life-long friends who find themselves at odds. <strong>The Northman</strong>, Robert Eggers follow-up to The Lighthouse, is a wild revenge tale. An incredible vibe with great performances throughout. <strong>Prey</strong> was an unexpected prequel to The Predator that went straight to Hulu. Dan Trachtenberg (10 Cloverfield Lane) clearly has love for this franchise and managed to make the best entry in the series since the original. Some truly inventive combat, mixing period weapons with the Predator's futuristic arsenal. Amber Midthunder is phenomenal in the lead role. <strong>Nightmare Alley</strong> technically came out in 2021, but I saw it early this year and it blew me away. More of a juicy noir than a horror film. The ending is perfect.</p>
<p>You can find the rest of my <a href="https://letterboxd.com/peruvianidol/list/favorite-films-of-2022/">favorite films of 2022</a> on Letterboxd.</p>
<h3>TV</h3>
<p>What a great year for TV. In researching this section, I kept being reminded of more shows I loved. Lots of great new shows as well as some returning shows doing their best work.</p>
<p><strong>Station Eleven (HBO)</strong> I was mid-way through Station Eleven when I wrote about it in last year's recap, but it just continued to get better and I found it to be just sublime. Great emotional payoff at the end and a beautiful score by Dan Romer that stayed with me for months.</p>
<p><strong>Severance (Apple TV)</strong> Ben Stiller's directorial follow-up to Escape at Dannemora is a high-concept sci-fi show about a group of people whose minds are "severed", living two separate but distinct lives working in a mysterious office and living outside of work. The final episode was an all-time cliffhanger. I can't wait for another season.</p>
<p><strong>The Rehearsal (HBO)</strong> Nathan Fielder's (Nathan for You) new show begins with a ridiculous premise β helping people rehearse difficult but mundane conversations by intricately recreating an environment and simulating every possible outcome β and quickly turns into something more surreal. This show had me in tears of laughter just about every episode.</p>
<p><strong>The Bear (FX/Hulu)</strong> I loved this show about a world-class chef returning home to Chicago to take over his deceased brother's Italian beef joint. It was at times both incredibly accurate in its portrayal of Chicago and also hit all of the Chicago clichΓ©s. A great ensemble cast. The show culminates in a tense, one-shot episode that feels like Uncut Gems in a restaurant. One of the best episodes of television all year.</p>
<p><strong>Peacemaker (HBO)</strong> This spinoff of The Suicide Squad (the good one, not the Jared Leto Joker one) stars John Cena as an over-the-top, patriotic assassin working with the government to uncover the mystery of parasitic butterfly-like creatures who are taking over human bodies. Peacemaker really leans into its mature rating and John Cena really commits to the character. This show is hysterical from its incredible opening dance number to the end credits.</p>
<figure>
<iframe src="https://www.youtube.com/embed/_mrr3UNALww" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</figure>
<p><strong>Andor (Disney+)</strong> I wasn't too thrilled about yet another Star Wars show about some side character from the movies, but Andor kind of blew me away from the start. Created by Tony Gilroy (The Bourne Identity, Michael Clayton), this show isn't precious about the Star Wars universe. There's no force powers, no lightsabers, no Skywalkers. It's gritty! There's a few episodes that are just absolutely thrilling. The Star Wars universe is huge. I want to see more stories like this.</p>
<p><strong>Pachinko (Apple TV)</strong> I loved the whole vibe of this series about a Korean family, told across multiple generations. Director Kogonada (Columbus, After Yang) establishes a gorgeous visual style. Another show with a great ensemble cast and a joyous opening credits with the cast dancing.</p>
<figure>
<iframe src="https://www.youtube.com/embed/1GgKXR_J-ww" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</figure>
<p><strong>Better Call Saul (AMC)</strong> Breaking Bad is one of my all-time favorite shows but, for whatever reason, I never got into Better Call Saul. I decided this year to finally catch up as everyone was raving about the final season. I enjoyed how the show fleshed out characters like Mike and Saul and introduced new characters, but it never reached the heights of Breaking Bad. An incredible showcase for Second City alum Bob Odenkirk. I absolutely loved Tony Dalton as Lalo, who is at once incredibly menacing and charismatic.</p>
<p><strong>Others worth mentioning</strong>: I was reluctant to jump back into the world of Game of Thrones after its disappointing final season, but <strong>House of the Dragon (HBO)</strong> roped me back in with its smaller scope and family intrigue. Paddy Considine is fantastic. I couldn't tell you a single thing about the first two seasons, but season 3 of <strong>Jack Ryan (Amazon)</strong> starts off with some great action and gave me some strong 24 vibes. <strong>Star Trek: Strange New Worlds</strong> is like a throwback to the original series. I love its humor and earnestness. Donald Glover continued to do whatever the hell he wanted with the last two seasons of <strong>Atlanta</strong>, which both aired this year after a long hiatus. Alternating between one-off episodes and episodes with the main cast, Atlanta was one of the most surreal shows ever. Season 3 of <strong>Barry</strong> was a bit uneven, but at its best it's still one of the best shows on TV. I'm not sure how much longer they can sustain its wild premise.</p>
<h3>Video Games</h3>
<p>This year, a couple of new games cemented themselves among my all-time favorites, and some yearly staples added new modes that pulled me back in. I also picked up a Steam Deck and several portable retro handhelds, but since I rarely leave my house these days, I haven't used them that much.</p>
<p><strong>Elden Ring</strong> I finally embraced Souls-like games after falling in love with Nioh a few years ago, and this game from the creator of Dark Souls further refines the formula into one of the most accessible entries yet while still remaining incredibly deep and challenging. Elden Ring's open-world nature allows you to explore different areas when you get stuck on a boss and come back to it after you've leveled up your character a bit more. Even around 300 hours into this game, I was still finding entirely new areas I hadn't yet seen. This game is fantastic and its the first Souls game I would wholeheartedly recommend to people who don't like or haven't played them before.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/Iggjz8bwpY-300.webp 300w, https://mikeaparicio.com/images/Iggjz8bwpY-600.webp 600w, https://mikeaparicio.com/images/Iggjz8bwpY-2400.webp 2400w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/Iggjz8bwpY-300.jpeg 300w, https://mikeaparicio.com/images/Iggjz8bwpY-600.jpeg 600w, https://mikeaparicio.com/images/Iggjz8bwpY-2400.jpeg 2400w" sizes="100vw" /><img alt="The main character of Sifu" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/Iggjz8bwpY-300.jpeg" width="2400" height="1350" /></picture>
<figcaption>
Sifu
</figcaption>
</figure>
<p><strong>Sifu</strong> This game hooked me right away with its gorgeous visual style and kinetic hand-to-hand combat. Sifu takes the 1-vs-many combat of games like the Arkham series and Ghost of Tsushima to a new level. I loved the fluidity of animations and the wide variety of moves at my disposal. This is a brutally hard game but at a certain point it starts to click and you feel like a complete badass, taking on multiple enemies with ease. I wrote <a href="https://mikeaparicio.com/posts/2022-02-21-tips-for-beating-sifu/">a guide for Sifu</a> that many of my friends referred to when they started playing.</p>
<p><strong>Inscryption</strong> Much like Hades last year, Inscryption is a game I tried on PC when it came out the previous year and couldn't get into. But when it released this year on PS5 I decided to give it another shot. Once you get past the odd art style and unlock new mechanics, this game reveals itself to be much more than it starts off as. To say any more would spoil it. If you enjoy turn-based strategy and deck building games, this game will blow your mind if you give it a chance.</p>
<p><strong>Call of Duty: Modern Warfare II</strong> The Modern Warfare entries are my favorite of the Call of Duty series and this one is no exception. One of the greatest single-player campaigns culminates with a nighttime helicopter flight over the Chicago River onto a skyscraper where you can enjoy a faithfully rendered view of downtown Chicago.</p>
<p>Modern Warfare II also added a new mode called DMZ which absolutely hooked me. DMZ takes place on the Warzone map but pits you against both human and AI opponents while offering much more to do than just survive. There's a risk/reward element that's extremely satisfying. DMZ is still in beta and it's not without its problems, but when it's not crashing or bombarding you with crackshot AI bots, it's a ton of fun.</p>
<p>I've barely touched Warzone 2.0. After getting an early win in "Unhinged Trios", which allows you to add up to three other players to your squad, I've been reluctant to ruin my win percentage!</p>
<figure>
<iframe src="https://www.youtube.com/embed/jXY3Lo_tYGQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</figure>
<p><strong>NBA 2k23</strong> Every time I think I've gotten this series out of my system, they add a new feature that hooks me. This year it's NBA Eras, a new mode that allows you to start a franchise in the 80s, 90s, 2000s, or today, with mostly period-accurate rosters and draft classes. You can try to relive or re-write NBA history with the benefit of hindsight.</p>
<p>I tried to extend the Bulls dynasty of the 90s, since Michael Jordan never retired to play baseball, and ended up with a god squad that included Steve Nash and Lamar Odom playing along side MJ and Scottie Pippen.</p>
<p>NBA Eras is sorely lacking over half of each draft class, including such greats as Charles Barkley and Reggie Miller, so even a few years in you end up with some pretty unrealistic rosters. Still, I loved playing with the rules and broadcast aesthetic of the different eras.</p>
<p><strong>Marvel's Midnight Suns</strong> The latest game from Firaxis, makers of XCOM (my all-time favorite game), had a lot going against it. First, I was disappointed that it wasn't XCOM 3. I'm also suffering from Marvel fatigue with all the shows and movies that have been coming out almost monthly now. But Midnight Suns quickly won me over with its inventive card-based combat and a Road House reference in the first five minutes. Once I let go of my selfish desire for more XCOM, I realized this game is like XCOM and Persona 5 had a baby and I fell in love with it. Sorry I doubted you, Firaxis friends!</p>
<p><strong>Others worth mentioning</strong>: I had a blast playing <strong>Cult of the Lamb</strong> during Olivia's birthday stream in August. Incredible art style and compelling gameplay loop. <strong>Stray</strong> is a sci-fi cat simulator/puzzle-platformer. It's a relatively short experience but I had a great time with it.</p>
<h2>Looking forward to in 2023</h2>
<p><strong>Owning my own content.</strong> Twitter has experienced a notable downturn since being acquired by Elon Musk. People are leaving in droves and those who stuck around are using the platform a lot less. I have mixed feelings about the whole thing.</p>
<p>On one hand, Elon is a narcissistic baby man who is running Twitter into the ground while his alt-right sycophants cheer him on. On the other hand, Twitter has been my most used social media app over the last 14 years. It effectively replaced RSS for me when Google killed Reader. It helped me grow my career and I've made a ton of friends through it. I'm reluctant to just walk away from it. Alternatives like <a href="https://mastodon.social/">Mastodon</a> have their own issues and lack the critical mass of Twitter.</p>
<p>What this whole debacle has illuminated for me is the need for me to own my own content. In 2023 I'm going to try and write more here on my site. I'm looking at preserving at least some of my Twitter archive with something like <a href="https://github.com/tweetback/tweetback">Tweetback</a> and maybe adding <a href="https://webmention.io/">webmentions</a> to the site to add a layer of social connectivity. Maybe getting off Facebook and Instagram while I'm at it.</p>
<p>Or maybe Elon will get bored and go back to digging holes and sending cars into space. But I'm not counting on it.</p>
<p><strong>Digging deeper into web components.</strong> This year, out of necessity, I started getting into the technical side of making components for our design system. Specifically, I started learning Svelte and was surprised to find I really enjoyed it!</p>
<p>Long ago, before I doubled down on CSS, I was a "webmaster" and built lots of stuff with PHP and MySQL. It's been so long since I had to use them that I don't even know how to build similar stuff on a modern stack.</p>
<p>Besides Svelte, I tinkered around with Supabase, Astro, and Storybook. In 2023, I'd like to keep learning and see how I might apply them to my day-to-day work. I'm also super interested in the work that Zach Leatherman is doing with <a href="https://github.com/11ty/webc">WebC</a> and <a href="https://github.com/11ty/is-land">is-land</a>, which have the potential to really expand how I use Eleventy.</p>
<p><strong>Writing a book?</strong> After a talk I proposed called <em>How to Never Write CSS Again</em> was rejected, I had a thought that maybe a talk isn't the right medium for everything I have to say on the topic. I've been kicking around the idea of turning it into a book.</p>
<p>There's a ton of great writing on CSS out there already but most of it is about <em>how to CSS</em> β that is, it shows you techniques for achieving specific results. What there's not a ton of about out there is <em>how to CSS <strong>together</strong></em>. How do you CSS when you have a bunch of people committing CSS to your codebase that don't like and/or aren't good at it? How do you write CSS in the context of a design system? And yes, how do you write CSS so that you never have to write it again? That's what I hope to answer with this book.</p>
<p><strong>Traveling more.</strong> It felt so good to travel again. Especially to two places I'd never been. I'm looking forward to Turquoise Health's quarterly all-hands meetings in different cities, starting with L.A. in January. I'm also hoping to head to Europe or Asia for the first time and visiting my family in Peru after a 10-year absence.</p>
<p><strong>Being present with my kids.</strong> I try really hard to be in the moment with Ryan but sometimes it can be a lot. Now with Owen around, it's made me realize how much I miss Ryan being that age. I want to enjoy this time with them as much as I can before they both grow up to resent me and want nothing to do with me. π</p>
<p><strong>Going with the flow.</strong> Not trying to have babies, not having house projects looming and no longer worried about what's next in my career, I'm looking forward most of all to just letting things happen and seeing where life takes me. Things tend to happen whether you plan for them or not. Sometimes making big plans only results in disappointment.</p>
<p>One thing I learned at Second City that's applicable outside of improv is the concept of "yes, and..." If you keep yourself open to what is happening instead of trying to control it, you'll be surprised where it can lead. I'm going to keep this in mind in 2023 and encourage you to try to do so as well.</p>
<p>Thanks for reading! I hope your 2023 is happy, healthy and drama-free.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/fZ0E7tTbBr-300.webp 300w, https://mikeaparicio.com/images/fZ0E7tTbBr-600.webp 600w, https://mikeaparicio.com/images/fZ0E7tTbBr-2188.webp 2188w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/fZ0E7tTbBr-300.jpeg 300w, https://mikeaparicio.com/images/fZ0E7tTbBr-600.jpeg 600w, https://mikeaparicio.com/images/fZ0E7tTbBr-2188.jpeg 2188w" sizes="100vw" /><img alt="Mike with Ryan, Owen and Emily in festive Christmas attire." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/fZ0E7tTbBr-300.jpeg" width="2188" height="1641" /></picture>
<figcaption>
Happy New Year from the Aparicios!
</figcaption>
</figure>
Design System Advice
2022-12-12T00:00:00Z
https://mikeaparicio.com/posts/2022-12-12-design-system-advice/
<p>I've been talking with a lot of people about design systems recently. First at <a href="https://www.clarityconf.com/event/2022">Clarity Conference</a>, in New Orleans, where I met a bunch of folks working on design systems big and small. In all of those conversations the one thing that struck me is that none of us have this design systems thing figured out. We're all just kind of stumbling around in the dark, learning from each other's mistakes and successes.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/ZS1UxAs0DE-300.webp 300w, https://mikeaparicio.com/images/ZS1UxAs0DE-600.webp 600w, https://mikeaparicio.com/images/ZS1UxAs0DE-2048.webp 2048w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/ZS1UxAs0DE-300.jpeg 300w, https://mikeaparicio.com/images/ZS1UxAs0DE-600.jpeg 600w, https://mikeaparicio.com/images/ZS1UxAs0DE-2048.jpeg 2048w" sizes="100vw" /><img alt="A bunch of awesome design systems folks standing in front of a flaming fountain in New Orleans." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/ZS1UxAs0DE-300.jpeg" width="2048" height="1152" /></picture>
<figcaption>
Hanging out with some lovely design systems people at Clarity Conf 2022 in New Orleans.
</figcaption>
</figure>
<p>Recently I started <a href="https://adplist.org/mentors/mike-aparicio">mentoring on ADPList</a> and so far my mentees fall into two categories: people trying to get into design systems and people working on design systems that are facing various challenges. A lot of common themes have come up and talking about them has helped me better articulate my approach to design systems, so I thought I'd share some of that advice here!</p>
<h2>Get in where you fit in</h2>
<p>It's tough out there right now in tech. So many companies are laying people off, freezing their hiring, and/or rescinding offers. Beyond that, they're reprioritizing the efforts of their remaining employees. Unfortunately, this sometimes means that design systems work, which to management doesn't directly drive revenue, often gets the short shrift.</p>
<p>If you're a recent grad or trying to pivot your career into a design systems role, now is honestly not a great time. Your best bet is to look for any role you can get hired for, but once you're in, look for opportunities to work on design systems or whatever else you might be interested in.</p>
<p>Find the people in the company who are doing that work and offer to help, even if they're not on your team. Not only is it a great opportunity to expand your skills and influence, but as other people doing the work move on, you'll become the de facto go-to person for whatever you're interested in.</p>
<p>In short, <strong>don't let your employer define your role</strong>. Find opportunities to work on what you're interested in and make yourself indispensable for that thing.</p>
<h2>Adopt a service mentality</h2>
<p>Working on design systems, your customers are not your company's customers. Your customers are designers, engineers and product managers. Your job is to help make their jobs easier.</p>
<p>Look for opportunities to connect with these customers.</p>
<ul>
<li>
<p>Establish regular office hours where people can drop in and ask questions, pair on solutions or just hang out and get to know you.</p>
</li>
<li>
<p>Make a dedicated Slack channel where people can ask questions and get support. Even if you're a solo design system team, having people ask in a channel rather than a DM allows other people who might know the answer to help out and is easier to reference than private conversations.</p>
</li>
<li>
<p>Make yourself available for questions and 1:1 sessions.</p>
</li>
<li>
<p>Get feedback via surveys and/or quarterly retrospectives. Soliciting feedback can be challenging, but it's important to give people that opportunity, even if they don't take advantage of it.</p>
</li>
<li>
<p>Evangelize the system through brown bags, lunch and learns, company all-hands β any opportunity to address large groups in the company who might not be familiar with you or the work you do.</p>
</li>
<li>
<p>Let people know that you're there to make their jobs easier. They love that!</p>
</li>
</ul>
<figure>
<img src="https://mikeaparicio.com/images/deal-with-designers.gif" alt="Tom from Office Space animatedly telling the Bobs: I deal with the goddamn designers so the engineers don't have to!" />
<figcaption>
My job, in a nutshell.
</figcaption>
</figure>
<h2>Let the roadmap inform the system</h2>
<p>I've talked to a lot of folks who have taken a "if you build it, they will come" approach to design systems and then struggle with adoption. They have this whole list of things they want the system to have and then they spend months working on those things. Meanwhile the product and its needs are constantly evolving and you end up with a lot of one-offs. Trying to get design system work on the product roadmap becomes extremely difficult.</p>
<p>Instead, look at the roadmap and let that inform what goes in your system. Whatever the next feature is, provide everything that feature needs β and <em>just</em> what that feature needs β to ship.</p>
<p>Each successive feature you work on will build on the work of the previous features, making it possible to ship things faster and faster. As a result, your system won't be cluttered with a bunch of components you <em>might</em> need someday. It will include the minimum you need to support the features built with it.</p>
<h2>Learn where the system ends and the product begins</h2>
<p>I recently wrote about <a href="https://mikeaparicio.com/posts/2022-11-26-reframing-design-systems/">reframing your thinking</a> around supporting product features with your design system. It's crucial, particularly if your design system team is small, to keep product decisions out of the system as much as possible. Things become extremely hard to maintain when the system becomes responsible for keeping track of product decisions.</p>
<p>Think about how you might create a feature while removing all product context from it. Create the atoms and some utilites to compose them into larger molecules and organisms. The smaller you can keep your system, the easier it will be to maintain and the more flexible it will be for your users.</p>
<h2>Sell the results, not the system</h2>
<p>Many people still struggle with "selling" the importance of design systems to stakeholders. It can be an uphill battle, particularly in times like this where companies are tightening their belts.</p>
<p>Ten years ago, we were selling the idea of responsive design. As ridiculous as that sounds now, we had to convince people that making our websites responsive was worth the investment. Today it's just become the way we make websites.</p>
<p>Design systems are on a similar path. Dan Mall noted in his Clarity talk that his early clients were asking him to build a system, while more recently they are asking him to help with their existing systems. At some point in the near future, we won't have to "sell" design systems. It will just be how we make websites.</p>
<p>In the meantime, make design systems part of your process. Let the roadmap inform the system instead of trying to get design system work on the roadmap. The results will do the selling for you.</p>
Reframing Design Systems
2022-11-26T00:00:00Z
https://mikeaparicio.com/posts/2022-11-26-reframing-design-systems/
<p>Dan Mall tweeted some great advice for struggling design systems teams:</p>
<blockquote class="twitter-tweet" data-conversation="none" data-theme="dark"><p lang="en" dir="ltr">Do less.<br /><br />Almost every team I work with tries to make their design system do everything. They stress themselves out, trying to tackle too much and end up accomplishing nothing.<br /><br />Pick a handful of things, and do them really well.</p>— Dan Mall (@danmall) <a href="https://twitter.com/danmall/status/1596540918810939393?ref_src=twsrc%5Etfw">November 26, 2022</a></blockquote>
<p>While attending Clarity Conference a few weeks ago, a common theme that came up in talking to folks struggling with their design systems was scope. The root of the problem is similar to why people struggle with CSS: we tend to look at a pattern in the context of a product feature.</p>
<p>Take the following set of patterns.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/Ir6prOCI7b-300.webp 300w, https://mikeaparicio.com/images/Ir6prOCI7b-600.webp 600w, https://mikeaparicio.com/images/Ir6prOCI7b-1290.webp 1290w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/Ir6prOCI7b-300.jpeg 300w, https://mikeaparicio.com/images/Ir6prOCI7b-600.jpeg 600w, https://mikeaparicio.com/images/Ir6prOCI7b-1290.jpeg 1290w" sizes="100vw" /><img alt="A set of common design patterns" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/Ir6prOCI7b-300.jpeg" width="1290" height="1240" /></picture>
</figure>
<p>You might look at these and see:</p>
<ol>
<li>A subscription form</li>
<li>A navigation menu</li>
<li>A button group</li>
<li>A card grid</li>
</ol>
<p>If you were to write the CSS for these, you'd see that all of these are groups of atomic components (text, buttons, inputs, images) composed with flexbox. Rather than adding new classes to support each of these feature contexts, we can use a utility class.</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.flex </span><span class="token punctuation">{</span><br /> <span class="token property">--flex-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span><br /> <span class="token property">--flex-gap</span><span class="token punctuation">:</span> .5rem<span class="token punctuation">;</span><br /><br /> <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span><br /> <span class="token property">align-items</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--flex-align<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">gap</span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--flex-gap<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>In this basic example, we can use CSS custom properties to provide defaults which can be overridden to support different contexts without having to make utility classes for every possible combination of flexbox properties.</p>
<p>In order to keep things managagable, particularly when your design system team is maybe fortunate enough to have a single person working on it full-time, it's critical to keep the system separate from "product decisions."</p>
<p>It's simply not possible to build and mantain a design system while also being included in every product meeting and keeping the system in sync with decisions made in those meetings.</p>
<p>Therefore, your best bet is to keep things small and provide designers and engineers with the building blocks to compose whatever they can imagine using the system.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/M2vS8aU2oI-300.webp 300w, https://mikeaparicio.com/images/M2vS8aU2oI-600.webp 600w, https://mikeaparicio.com/images/M2vS8aU2oI-1024.webp 1024w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/M2vS8aU2oI-300.jpeg 300w, https://mikeaparicio.com/images/M2vS8aU2oI-600.jpeg 600w, https://mikeaparicio.com/images/M2vS8aU2oI-1024.jpeg 1024w" sizes="100vw" /><img alt="A diagram from Brad Frost's Atomic Design showing Atoms (components) and Molecules (composition) as part of your design system, while Organisms, Templates and Pages are Product Decisions." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/M2vS8aU2oI-300.jpeg" width="1024" height="341" /></picture>
<figcaption>
from Brad Frost's <a href="https://bradfrost.com/blog/post/atomic-web-design/">Atomic Design</a>
</figcaption>
</figure>
<p>In Atomic Design terms, your system's components should largely consist of Atoms, while you can apply utility classes (like a flexbox utility) to compose those atoms into larger Molecules. When you start getting into Organisms you're in full on Product Decision Land.</p>
<p>LEGO analogies in design systems are clichΓ©, but think of yourself as designing the individual bricks and making sure designers and engineers have the pieces they need and let them decide if they're building Star Wars or Avengers or Harry Potter.</p>
Nested navigation in Eleventy
2022-08-19T00:00:00Z
https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/
<p>I'm currently working on a design systems documentation project that has some pretty extensive navigation requirements. The site is built with Eleventy and I wanted to be able to handle the nav menu without needing to update it manually each time I add a new page.</p>
<p>It turns out Eleventy has a helpful <a href="https://www.11ty.dev/docs/plugins/navigation/">navigation plugin</a> that's capable of generating a nested list based on the front matter of your pages. By default it creates a simple nested list, like so:</p>
<ul>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Home</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Changelog</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Visual Style</a>
<ul>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Color</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Typography</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Spacing</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Icons</a></li>
</ul>
</li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Components</a>
<ul>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Accordion</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Alert</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Avatar</a></li>
</ul>
</li>
</ul>
<p>As the number of pages increases, this could get noisy pretty quickly. So I decided to use the <code>details</code> element to toggle all of the sub-sections (<strong>without JavaScript!</strong>) and then add a little style to it.</p>
<style>
.nav-list-demo :where([role="list"]) {
list-style: none;
padding-inline-start: 0;
}
.nav-list {
background-color: #1F1E25;
color: #8F94A6;
padding: 2rem;
user-select: none;
}
.nav-list-demo .nav-list a {
color: inherit;
text-decoration: none;
display: block;
}
.nav-list-demo .nav-list summary {
cursor: pointer;
display: block;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 512'%3E%3Cpath d='M118.6 105.4l128 127.1C252.9 239.6 256 247.8 256 255.1s-3.125 16.38-9.375 22.63l-128 127.1c-9.156 9.156-22.91 11.9-34.88 6.943S64 396.9 64 383.1V128c0-12.94 7.781-24.62 19.75-29.58S109.5 96.23 118.6 105.4z' fill='%236A89FE'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right center;
background-size: 1.125em 1.125em;
}
.nav-list-demo .nav-list details[open] > summary {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M310.6 246.6l-127.1 128C176.4 380.9 168.2 384 160 384s-16.38-3.125-22.63-9.375l-127.1-128C.2244 237.5-2.516 223.7 2.438 211.8S19.07 192 32 192h255.1c12.94 0 24.62 7.781 29.58 19.75S319.8 237.5 310.6 246.6z' fill='%236A89FE'/%3E%3C/svg%3E");
}
.nav-list-demo .nav-list summary::-webkit-details-marker {
display: none;
}
.nav-list-demo .nav-list details > [role="list"] {
padding-inline-start: .75rem;
}
.nav-list-demo .nav-list a,
.nav-list-demo .nav-list summary {
padding-block: .375rem;
transition: color .1s ease-in-out;
}
.nav-list-demo .nav-list a:hover,
.nav-list-demo .nav-list a[aria-current="page"],
.nav-list-demo .nav-list summary:hover,
.nav-list-demo .nav-list .is-active summary {
color: #FDFDFE;
}
.nav-list-demo .nav-list > li,
.nav-list-demo .nav-list .is-active summary {
position: relative;
}
.nav-list-demo .nav-list > li > a[aria-current="page"]:before,
.nav-list-demo .nav-list .is-active summary:before {
content: "";
display: block;
width: 4px;
height: 100%;
background-color: #6A89FE;
position: absolute;
inset-inline-start: -2rem;
inset-block-start: 0;
inset-block-end: 0;
}
/* override site styles */
.nav-list-demo .nav-list a:hover {
border-bottom: none;
}
.demo-layout {
display: grid;
grid-template-columns: minmax(0, 240px) 1fr;
outline: 2px solid #212836;
outline-offset: 1px;
}
.demo-layout > [data-grid-area="nav"] {
background-color: #1F1E25;
}
.demo-layout > [data-grid-area="main"] {
background-color: #16151A;
min-height: 526px;
padding: 2rem;
}
.demo-layout > [data-grid-area="main"] > :not(:last-child) {
margin-bottom: 1.5rem;
}
@media (max-width: 599px) {
.demo-layout > [data-grid-area="main"] {
display: none;
}
.demo-layout {
display: grid;
grid-template-columns: 1fr;
max-width: 240px;
}
}
</style>
<section class="demo-layout">
<nav class="nav-list-demo" id="example" data-grid-area="nav">
<ul role="list" class="nav-list">
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Home</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Changelog</a></li>
<li>
<details class="is-active" open="">
<summary>Visual Style</summary>
<ul role="list">
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#" aria-current="page">Color</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Typography</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Spacing</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Icons</a></li>
</ul>
</details>
</li>
<li>
<details>
<summary>Components</summary>
<ul role="list">
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Accordion</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Alert</a></li>
<li><a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#">Avatar</a></li>
</ul>
</details>
</li>
</ul>
</nav>
<div data-grid-area="main">
<p class="ma-heading-1">Color</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Possimus ab temporibus sapiente commodi? Accusamus qui quidem praesentium nesciunt quasi beatae, deserunt deleniti, aut veniam blanditiis provident fugiat incidunt consequatur natus.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Qui consequatur necessitatibus possimus, ut magnam magni enim distinctio iste explicabo debitis eum reprehenderit ea facilis numquam unde ipsam minus. Iusto, magni.</p>
</div>
</section>
<h2>Setting up the plugin</h2>
<p>In your Eleventy project, install the plugin:</p>
<pre class="language-js"><code class="language-js">npm install @11ty<span class="token operator">/</span>eleventy<span class="token operator">-</span>navigation <span class="token operator">--</span>save<span class="token operator">-</span>dev</code></pre>
<p>Next, add the plugin to your Eleventy config file:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// .eleventy.js</span><br /><span class="token keyword">const</span> eleventyNavigationPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"@11ty/eleventy-navigation"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br />module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">eleventyConfig</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> eleventyConfig<span class="token punctuation">.</span><span class="token function">addPlugin</span><span class="token punctuation">(</span>eleventyNavigationPlugin<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span><span class="token punctuation">;</span></code></pre>
<p>Assuming you already have <code>module.exports</code>, you can just add the <code>const</code> and <code>addPlugin()</code>.</p>
<h2>Front Matter</h2>
<p>In each page's front matter, add the <code>eleventyNavigation</code> object and assign a unique <code>key</code>:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// _src/index.md</span><br /><span class="token operator">--</span><span class="token operator">-</span><br /><span class="token literal-property property">eleventyNavigation</span><span class="token operator">:</span><br /> <span class="token literal-property property">key</span><span class="token operator">:</span> Home<br /><span class="token operator">--</span><span class="token operator">-</span></code></pre>
<p>You can nest a page within the navigation by setting another page as its parent:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// _src/visual-style/color.md</span><br /><span class="token operator">--</span><span class="token operator">-</span><br /><span class="token literal-property property">eleventyNavigation</span><span class="token operator">:</span><br /> <span class="token literal-property property">key</span><span class="token operator">:</span> Color<br /> <span class="token literal-property property">parent</span><span class="token operator">:</span> Visual Style<br /><span class="token operator">--</span><span class="token operator">-</span></code></pre>
<p>In my example, I don't actually have a page for Visual Style, so I created an empty index page and set <code>permalink</code> to <code>false</code> so that it wouldn't be generated. I also wanted it to appear before Components, so I also added an <code>order</code>:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// _src/visual-style/index.md</span><br /><span class="token operator">--</span><span class="token operator">-</span><br /><span class="token literal-property property">title</span><span class="token operator">:</span> Visual Style<br /><span class="token literal-property property">permalink</span><span class="token operator">:</span> <span class="token boolean">false</span><br /><span class="token literal-property property">eleventyNavigation</span><span class="token operator">:</span><br /> <span class="token literal-property property">key</span><span class="token operator">:</span> Visual Style<br /> <span class="token literal-property property">order</span><span class="token operator">:</span> <span class="token number">1</span><br /><span class="token operator">--</span><span class="token operator">-</span></code></pre>
<h2>Rendering the navigation</h2>
<p>The plugin documentation has <a href="https://www.11ty.dev/docs/plugins/navigation/#bring-your-own-html-render-the-menu-items-manually">a snippet for a Nunjucks macro</a> that will recursively render the menu with unlimited child levels. In this case, I only needed it to go down one level, but I wanted it to use the <code>details</code> element instead of a link for sections with children:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// _includes/partials/nav-list.njk</span><br /><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">set</span> navPages <span class="token operator">=</span> collections<span class="token punctuation">.</span>all <span class="token operator">|</span> eleventyNavigation <span class="token operator">%</span><span class="token punctuation">}</span><br /><br /><span class="token punctuation">{</span><span class="token operator">%</span> macro <span class="token function">renderNavListItem</span><span class="token punctuation">(</span>entry<span class="token punctuation">)</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> entry<span class="token punctuation">.</span>children<span class="token punctuation">.</span>length <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>li<span class="token operator">></span><br /> <span class="token operator"><</span>details<br /> <span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> <span class="token keyword">for</span> child <span class="token keyword">in</span> entry<span class="token punctuation">.</span>children <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> child<span class="token punctuation">.</span>parent <span class="token operator">==</span> entry<span class="token punctuation">.</span>title and child<span class="token punctuation">.</span>url <span class="token operator">==</span> page<span class="token punctuation">.</span>url <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"is-active"</span><br /> open<br /> <span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator">></span><br /> <span class="token operator"><</span>summary<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> entry<span class="token punctuation">.</span>title <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>summary<span class="token operator">></span><br /> <span class="token operator"><</span>ul role<span class="token operator">=</span><span class="token string">"list"</span><span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> <span class="token keyword">for</span> child <span class="token keyword">in</span> entry<span class="token punctuation">.</span>children <span class="token operator">%</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token function">renderNavListItem</span><span class="token punctuation">(</span>child<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">-</span><span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span><span class="token operator">/</span>ul<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>details<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">else</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>li<span class="token operator">></span><br /> <span class="token operator"><</span>a href<span class="token operator">=</span><span class="token string">"{{ entry.url }}"</span><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> entry<span class="token punctuation">.</span>url <span class="token operator">==</span> page<span class="token punctuation">.</span>url <span class="token operator">%</span><span class="token punctuation">}</span> aria<span class="token operator">-</span>current<span class="token operator">=</span><span class="token string">"page"</span> <span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> entry<span class="token punctuation">.</span>title <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>a<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> endif <span class="token operator">-</span><span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> endmacro <span class="token operator">%</span><span class="token punctuation">}</span><br /><br /><span class="token operator"><</span>ul <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"nav-list"</span> role<span class="token operator">=</span><span class="token string">"list"</span><span class="token operator">></span><br /><span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> <span class="token keyword">for</span> entry <span class="token keyword">in</span> navPages <span class="token operator">%</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token function">renderNavListItem</span><span class="token punctuation">(</span>entry<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> endfor <span class="token operator">-</span><span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token operator"><</span><span class="token operator">/</span>ul<span class="token operator">></span></code></pre>
<p>Okay, there's a lot going on here, so let's break it down.</p>
<p>First, we're adding our collections to <code>navPages</code> and applying the <code>eleventyNavigation</code> filter, which <a href="https://www.11ty.dev/docs/plugins/navigation/#fetch-the-menu-items-using-the-eleventynavigation-filter">returns a sorted array of page objects</a>:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">set</span> navPages <span class="token operator">=</span> collections<span class="token punctuation">.</span>all <span class="token operator">|</span> eleventyNavigation <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>Next, we're creating a Nunjucks macro called <code>renderNavListItem</code> that takes <code>entry</code>, an individual item in <code>navPages</code>, as an argument.</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><span class="token operator">%</span> macro <span class="token function">renderNavListItem</span><span class="token punctuation">(</span>entry<span class="token punctuation">)</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator">...</span><br /><span class="token punctuation">{</span><span class="token operator">%</span> endmacro <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>Inside the macro, if an item has children, we'll show it as a <code>details</code> element inside a list item. If one of its children is the current page, we'll add a class of <code>.is-active</code> and also add an attribute of <code>open</code> to expand the <code>details</code> element by default. (If you want all of them to be expanded by default, you can move <code>open</code> outside of the <code>for</code> loop and before the closing bracket of <code>details</code>.) Below the <code>summary</code>, we're using the <code>renderNavListItem</code> macro recursively to show children of the item in a list.</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> entry<span class="token punctuation">.</span>children<span class="token punctuation">.</span>length <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>li<span class="token operator">></span><br /> <span class="token operator"><</span>details<br /> <span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> <span class="token keyword">for</span> child <span class="token keyword">in</span> entry<span class="token punctuation">.</span>children <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> child<span class="token punctuation">.</span>parent <span class="token operator">==</span> entry<span class="token punctuation">.</span>title and child<span class="token punctuation">.</span>url <span class="token operator">==</span> page<span class="token punctuation">.</span>url <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"is-active"</span><br /> open<br /> <span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator">></span><br /> <span class="token operator"><</span>summary<span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> entry<span class="token punctuation">.</span>title <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>summary<span class="token operator">></span><br /> <span class="token operator"><</span>ul role<span class="token operator">=</span><span class="token string">"list"</span><span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> <span class="token keyword">for</span> child <span class="token keyword">in</span> entry<span class="token punctuation">.</span>children <span class="token operator">%</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token function">renderNavListItem</span><span class="token punctuation">(</span>child<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">-</span><span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span><span class="token operator">/</span>ul<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>details<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span></code></pre>
<p>If the item doesn't have children, we're displaying it as a list item linking to the page and setting <code>aria-current="page"</code> if the item matches the current page.</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">else</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>li<span class="token operator">></span><br /> <span class="token operator"><</span>a href<span class="token operator">=</span><span class="token string">"{{ entry.url }}"</span><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> entry<span class="token punctuation">.</span>url <span class="token operator">==</span> page<span class="token punctuation">.</span>url <span class="token operator">%</span><span class="token punctuation">}</span> aria<span class="token operator">-</span>current<span class="token operator">=</span><span class="token string">"page"</span> <span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span><span class="token operator">></span><span class="token punctuation">{</span><span class="token punctuation">{</span> entry<span class="token punctuation">.</span>title <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>a<span class="token operator">></span><br /> <span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span><br /><span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> endif <span class="token operator">-</span><span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>Finally, we call our macro inside of our <code>.nav-list</code>:</p>
<pre class="language-js"><code class="language-js"><span class="token operator"><</span>ul <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"nav-list"</span> role<span class="token operator">=</span><span class="token string">"list"</span><span class="token operator">></span><br /><span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> <span class="token keyword">for</span> entry <span class="token keyword">in</span> navPages <span class="token operator">%</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token punctuation">{</span> <span class="token function">renderNavListItem</span><span class="token punctuation">(</span>entry<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">{</span><span class="token operator">%</span><span class="token operator">-</span> endfor <span class="token operator">-</span><span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token operator"><</span><span class="token operator">/</span>ul<span class="token operator">></span></code></pre>
<p>In our layout, we can insert the include that displays the nav list:</p>
<pre class="language-js"><code class="language-js"><span class="token comment">// _src/_includes/base.njk</span><br /><span class="token punctuation">{</span><span class="token operator">%</span> include <span class="token string">"partials/nav-list.njk"</span> <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<h2>Styling the navigation</h2>
<p>I styled this a little differently within the context of the design system, but I'll break it down here so that it works on its own.</p>
<p>First, a quick reset on lists where we set the <code>role</code> attribute to <code>list</code>. We're basically saying this should act like a list, even if we're stripping it of the default list styles. I picked this up from <a href="https://piccalil.li/blog/a-modern-css-reset/">Andy Bell's Modern CSS Reset</a>.</p>
<pre class="language-scss"><code class="language-scss"><span class="token punctuation">:</span><span class="token function">where</span><span class="token punctuation">(</span>[role=<span class="token string">"list"</span>]<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token property">list-style</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /> <span class="token property">padding-inline-start</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Note that I've enclosed the rule inside of a <code>:where()</code> selector, which is <a href="https://caniuse.com/?search=%3Awhere">supported in modern browsers</a> and reduces its specificity to zero.</p>
<p>Next, we set some basic styles on the <code>.nav-list</code> itself:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.nav-list </span><span class="token punctuation">{</span><br /> <span class="token property">background-color</span><span class="token punctuation">:</span> #1F1E25<span class="token punctuation">;</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> #8F94A6<span class="token punctuation">;</span><br /> <span class="token property">user-select</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>In the <a href="https://mikeaparicio.com/posts/2022-08-19-nested-navigation-in-eleventy/#example">above example</a>, I also set a max-width and a left margin, but in the context of a full page, those would probably be dictated by your layout.</p>
<p>Also note that I'm setting <code>user-select</code> to <code>none</code> here to prevent the user (read: me) from accidentally selecting text while clicking around the navigation.</p>
<p>Next, some link styles:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.nav-list a </span><span class="token punctuation">{</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> inherit<span class="token punctuation">;</span><br /> <span class="token property">text-decoration</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>We're setting the color of our links to inherit the text color we previously set on <code>.nav-list</code>, instead of our default link color, and removing the underline. We also set <code>display: block</code> so that the link takes up the full width of the list, giving it a larger clickable surface.</p>
<p>Next, we want the <code>summary</code> of our <code>details</code> element to be largely indistinguishable from a link, except for the arrow indicator. For the arrow, we'll replace the default native indicator with a custom SVG, which we'll URL encode as a background image so that we don't need any external assets.</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.nav-list summary </span><span class="token punctuation">{</span><br /> <span class="token property">cursor</span><span class="token punctuation">:</span> pointer<span class="token punctuation">;</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span><br /> <span class="token property">background-image</span><span class="token punctuation">:</span> <span class="token url">url</span><span class="token punctuation">(</span><span class="token string">"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 512'%3E%3Cpath d='M118.6 105.4l128 127.1C252.9 239.6 256 247.8 256 255.1s-3.125 16.38-9.375 22.63l-128 127.1c-9.156 9.156-22.91 11.9-34.88 6.943S64 396.9 64 383.1V128c0-12.94 7.781-24.62 19.75-29.58S109.5 96.23 118.6 105.4z' fill='%236A89FE'/%3E%3C/svg%3E"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token property">background-repeat</span><span class="token punctuation">:</span> no-repeat<span class="token punctuation">;</span><br /> <span class="token property">background-position</span><span class="token punctuation">:</span> right center<span class="token punctuation">;</span><br /> <span class="token property">background-size</span><span class="token punctuation">:</span> 1.125em 1.125em<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>We're setting the background size using <code>em</code> so that the arrow is always proportionate to the size of the text. You could also use <code>rem</code> or <code>px</code> here, if you prefer.</p>
<p>When the list is open, we want to change the direction of the indicator arrow, so we'll use a different SVG:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.nav-list details[open] > summary </span><span class="token punctuation">{</span><br /> <span class="token property">background-image</span><span class="token punctuation">:</span> <span class="token url">url</span><span class="token punctuation">(</span><span class="token string">"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 320 512'%3E%3Cpath d='M310.6 246.6l-127.1 128C176.4 380.9 168.2 384 160 384s-16.38-3.125-22.63-9.375l-127.1-128C.2244 237.5-2.516 223.7 2.438 211.8S19.07 192 32 192h255.1c12.94 0 24.62 7.781 29.58 19.75S319.8 237.5 310.6 246.6z' fill='%236A89FE'/%3E%3C/svg%3E"</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Whoopsie! Safari still shows the native arrow on the left. (Applying <code>display: block</code> on the <code>summary</code> removes it in other browsers. The default value is <code>list-item</code>.) We can remove it like so:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.nav-list summary::-webkit-details-marker </span><span class="token punctuation">{</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Let's give our link and summary elements some vertical padding using the <a href="https://web.dev/learn/css/logical-properties/">logical property</a> <code>padding-block</code>. We'll also add a subtle transition on the color when it changes on hover.</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.nav-list a,<br />.nav-list summary </span><span class="token punctuation">{</span><br /> <span class="token property">padding-block</span><span class="token punctuation">:</span> .375rem<span class="token punctuation">;</span><br /> <span class="token property">transition</span><span class="token punctuation">:</span> color .1s ease-in-out<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Speaking of which, let's increase the contrast on a link or summary if it's hovered over or if it's the current page.</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.nav-list a:hover,<br />.nav-list a[aria-current="page"],<br />.nav-list summary:hover,<br />.nav-list .is-active summary </span><span class="token punctuation">{</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> #FDFDFE<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Note the use of <code>[aria-current="page"]</code> here. This is a great way to ensure that you're exposing the fact that the page is current to assistive devices and not just visually by using a class.</p>
<p>Ben Myers has an excellent article about <a href="https://benmyers.dev/blog/semantic-selectors/">using stateful, semantic selectors</a> like this.</p>
<p>Next, for lists inside of a <code>details</code> element, we'll add some padding to indent the text.</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.nav-list details > [role="list"] </span><span class="token punctuation">{</span><br /> <span class="token property">padding-inline-start</span><span class="token punctuation">:</span> .75rem<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Finally, we'll add some styles to highlight the active top-level page or section:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.nav-list > li,<br />.nav-list .is-active summary </span><span class="token punctuation">{</span><br /> <span class="token property">position</span><span class="token punctuation">:</span> relative<span class="token punctuation">;</span><br /><span class="token punctuation">}</span><br /><br /><span class="token selector">.nav-list > li > a[aria-current="page"]:before,<br />.nav-list .is-active summary:before </span><span class="token punctuation">{</span><br /> <span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">""</span><span class="token punctuation">;</span><br /> <span class="token property">display</span><span class="token punctuation">:</span> block<span class="token punctuation">;</span><br /> <span class="token property">width</span><span class="token punctuation">:</span> 4px<span class="token punctuation">;</span><br /> <span class="token property">height</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span><br /> <span class="token property">background-color</span><span class="token punctuation">:</span> #6A89FE<span class="token punctuation">;</span><br /> <span class="token property">position</span><span class="token punctuation">:</span> absolute<span class="token punctuation">;</span><br /> <span class="token property">inset-inline-start</span><span class="token punctuation">:</span> -2rem<span class="token punctuation">;</span><br /> <span class="token property">inset-block-start</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span><br /> <span class="token property">inset-block-end</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Here we're positioning a thin pseudo-element with a background color on the left edge of the list. Again we're using logical properties to position the pseudo-element.</p>
<h2>Wrapping up</h2>
<p>So there you have it! A complex nav menu made slightly less complex, thanks to the <code>details</code> element, Eleventy's navigation plugin, and a little CSS. And we didn't need JavaScript or any additional assets.</p>
<p>Feel free to <a href="https://twitter.com/peruvianidol">reach out to me on Twitter</a> if you have any questions or feedback!</p>
Owen
2022-06-08T00:00:00Z
https://mikeaparicio.com/posts/2022-06-08-owen/
<p>Three and a half years ago, <a href="https://mikeaparicio.com/posts/2019-02-14-ryan/">our son Ryan was born</a>. We decided we wanted another one but weren't really actively trying. If it happened, it happened. And, well, it happened!</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/dHGDk1YdH1-300.webp 300w, https://mikeaparicio.com/images/dHGDk1YdH1-600.webp 600w, https://mikeaparicio.com/images/dHGDk1YdH1-4584.webp 4584w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/dHGDk1YdH1-300.jpeg 300w, https://mikeaparicio.com/images/dHGDk1YdH1-600.jpeg 600w, https://mikeaparicio.com/images/dHGDk1YdH1-4584.jpeg 4584w" sizes="100vw" /><img alt="My newborn son, Owen" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/dHGDk1YdH1-300.jpeg" width="4584" height="3056" /></picture>
<figcaption>
Owen James Aparicio Β· born 5/25/22 @ 9:12am, 6lbs 11oz, 20in
</figcaption>
</figure>
<p>After the trauma of <a href="https://mikeaparicio.com/posts/2018-08-26-four-years/">losing Olivia</a> and trying for four years to have Ryan, and then spending the entire pregnancy anxious about the outcome, this was quite a bit easier. We still had anxiety about Owen being affected with the same rare condition (CAMT) that Olivia had, but it seems so far that he is perfectly fine. Somehow even healthier than Ryan was.</p>
<p>Friends who are new parents often ask me if it gets easier. I always tell them it doesn't get easier, there are just new challenges. Having a three-year-old and a newborn (and an 18-year-old stepson who graduated high school just days after Owen was born), I can confirm that the three-year-old is in fact harder. Ryan demands more attention and is at an age where he's trying to assert his independence. Meanwhile, Owen is usually sleeping when he's not eating or pooping, and he hasn't yet learned the word "no".</p>
<p>Ryan is excited to be a big brother, though maybe a bit disappointed that Owen didn't come out of the womb ready to chat and play. I explained to him that not too long ago he was just as small and had to learn how to talk and walk and do all of the things he can do now. And now he'll be able to help Owen learn all of those things.</p>
<p>It's a good reminder as an adult that nothing comes easy and that we have to keep learning and practicing to get better at everything.</p>
<p>The other thing I tell new parents is to enjoy every moment because they don't get any smaller. Ryan is already getting to the point where it's hard to carry him everywhere, as much as he'd like me to. I'm trying to constantly remind myself of this with both Ryan and Owen and enjoy this time while I can. It won't be long before they're graduating high school and want to have nothing to do with me. π</p>
Refactoring MikeAparicio.com
2022-05-26T00:00:00Z
https://mikeaparicio.com/posts/2022-05-26-refactoring-mikeaparicio-com/
<p>It's been about two years since I last rebuilt my blog. Since that time I've learned a lot more about Eleventy and my thinking around design systems and CSS has evolved a bit.</p>
<p>My existing codebase had accumulated numerous failed attempts at implementing search, adding a CMS, not to mention all of the abandoned drafts. The features I was able to cobble together were hastily and shamelessly borrowed from various Eleventy starters. It got to the point where the code was causing me anxiety any time I'd sit down to try and write a post. Something had to give!</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/JuA_Ep3TYh-300.webp 300w, https://mikeaparicio.com/images/JuA_Ep3TYh-600.webp 600w, https://mikeaparicio.com/images/JuA_Ep3TYh-963.webp 963w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/JuA_Ep3TYh-300.jpeg 300w, https://mikeaparicio.com/images/JuA_Ep3TYh-600.jpeg 600w, https://mikeaparicio.com/images/JuA_Ep3TYh-963.jpeg 963w" sizes="100vw" /><img alt="An older couple sitting among piles of stuff in a hoarder house" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/JuA_Ep3TYh-300.jpeg" width="963" height="542" /></picture>
<figcaption>
I know it looks bad but I know exactly where everything is.
</figcaption>
</figure>
<p>I decided to start completely from scratch with a fresh build of the most bleeding edge version of Eleventy (currently 2.0.0-canary.11). Here's a few things I learned along the way.</p>
<h2>Setting a color scheme</h2>
<p>For this design refresh I wanted to default to a dark design. (Light mode to come!) You may be aware of the CSS media query <code>prefers-color-scheme</code>, but there is also a CSS property called <code>color-scheme</code> that provides some default styles based on its setting.</p>
<figure>
<div class="ma-grid">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/Sklt2W7rlG-300.webp 300w, https://mikeaparicio.com/images/Sklt2W7rlG-600.webp 600w, https://mikeaparicio.com/images/Sklt2W7rlG-744.webp 744w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/Sklt2W7rlG-300.jpeg 300w, https://mikeaparicio.com/images/Sklt2W7rlG-600.jpeg 600w, https://mikeaparicio.com/images/Sklt2W7rlG-744.jpeg 744w" sizes="100vw" /><img alt="A sample HTML with text, form elements and a button defaulting to a light color scheme" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/Sklt2W7rlG-300.jpeg" width="744" height="1016" /></picture>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/ATEwabt4tu-300.webp 300w, https://mikeaparicio.com/images/ATEwabt4tu-600.webp 600w, https://mikeaparicio.com/images/ATEwabt4tu-744.webp 744w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/ATEwabt4tu-300.jpeg 300w, https://mikeaparicio.com/images/ATEwabt4tu-600.jpeg 600w, https://mikeaparicio.com/images/ATEwabt4tu-744.jpeg 744w" sizes="100vw" /><img alt="The same sample HTML defaulting to a dark color scheme" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/ATEwabt4tu-300.jpeg" width="744" height="1016" /></picture>
</div>
<figcaption>
<code>color-scheme</code> provides default styles appropriate to the author's preferred color scheme, or can be overridden by the user's.
</figcaption>
</figure>
<p>You can set this in your CSS to indicate that the site supports both dark and light schemes and whichever is first is the author's preferred default.</p>
<pre class="language-css"><code class="language-css"><span class="token selector">:root</span> <span class="token punctuation">{</span><br /> <span class="token property">color-scheme</span><span class="token punctuation">:</span> dark light<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>You can also set this in a <code>meta</code> tag in the <code>head</code> to help the browser choose the correct color scheme before the CSS is loaded.</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>color-scheme<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dark light<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></code></pre>
<h2>Adding a non-fluid responsive type scale</h2>
<p>While CSS's <code>clamp</code> function is useful for creating fluid type/spacing scales (e.g. <a href="https://utopia.fyi/">Utopia</a>), I haven't quite embraced it yet. Still, I did want to have a larger type scale and gutter size on large screens than on smaller ones, so I decided to try combining Sass variables, which I use for my design tokens, and CSS custom properties.</p>
<p>First, in my global tokens I set my type scale as follows:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$font-size-100</span></span><span class="token punctuation">:</span> .75rem<span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$font-size-200</span></span><span class="token punctuation">:</span> .875rem<span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$font-size-300</span></span><span class="token punctuation">:</span> 1rem<span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$font-size-400</span></span><span class="token punctuation">:</span> 1.25rem<span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$font-size-500</span></span><span class="token punctuation">:</span> 1.5rem<span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$font-size-600</span></span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$font-size-700</span></span><span class="token punctuation">:</span> 2.5rem<span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$font-size-800</span></span><span class="token punctuation">:</span> 3rem<span class="token punctuation">;</span></code></pre>
<p>Then I set some CSS custom properties for font size and shift the entire scale and double the gutter size on large screens with a media query:</p>
<pre class="language-scss"><code class="language-scss"><span class="token punctuation">:</span><span class="token function">where</span><span class="token punctuation">(</span>html<span class="token punctuation">)</span> <span class="token punctuation">{</span><br /> <span class="token property">--font-size-200</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-100}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-300</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-200}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-400</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-300}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-500</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-400}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-600</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-500}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-700</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-600}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-800</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-700}</span><span class="token punctuation">;</span><br /> <span class="token property">--gutter</span><span class="token punctuation">:</span> <span class="token variable">#{$size-gutter}</span><span class="token punctuation">;</span><br /><br /> <span class="token atrule"><span class="token rule">@media</span><span class="token punctuation">(</span><span class="token property">min-width</span><span class="token punctuation">:</span> <span class="token variable">$breakpoint-medium</span><span class="token punctuation">)</span></span> <span class="token punctuation">{</span><br /> <span class="token property">--font-size-200</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-200}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-300</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-300}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-400</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-400}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-500</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-500}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-600</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-600}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-700</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-700}</span><span class="token punctuation">;</span><br /> <span class="token property">--font-size-800</span><span class="token punctuation">:</span> <span class="token variable">#{$font-size-800}</span><span class="token punctuation">;</span><br /> <span class="token property">--gutter</span><span class="token punctuation">:</span> <span class="token function">calc</span><span class="token punctuation">(</span><span class="token variable">#{$size-gutter}</span> <span class="token operator">*</span> 2<span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><br /><span class="token punctuation">}</span></code></pre>
<p>Then in my component tokens, instead of referencing a Sass variable, I reference the CSS custom property:</p>
<pre class="language-scss"><code class="language-scss"><span class="token property"><span class="token variable">$heading-1-font-size</span></span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-800<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$heading-2-font-size</span></span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-700<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$heading-3-font-size</span></span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-600<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$heading-4-font-size</span></span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-500<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><br /><span class="token property"><span class="token variable">$text-large-font-size</span></span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-400<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$text-medium-font-size</span></span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-300<span class="token punctuation">)</span><span class="token punctuation">;</span><br /><span class="token property"><span class="token variable">$text-small-font-size</span></span><span class="token punctuation">:</span> <span class="token function">var</span><span class="token punctuation">(</span>--font-size-200<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Is this overkill? Should I just give in and use <code>clamp</code>? Maybe! But for now this does the job.</p>
<h2>Dealing with drafts</h2>
<p>Previously, my drafts just consisted of some Markdown files and I didn't really have a way to preview them without moving them to the <code>posts</code> folder. I came across a few different solutions for handling drafts, but most of them involved using environment variables and/or adding a bunch of code to my <code>.eleventy.js</code> file.</p>
<p>Instead, I ended up creating a <code>drafts</code> folder and including a data file (<code>drafts.json</code>) that set the bare minimum of front matter for all drafts:</p>
<pre class="language-json"><code class="language-json"><span class="token punctuation">{</span><br /> <span class="token property">"layout"</span> <span class="token operator">:</span> <span class="token string">"post"</span><span class="token punctuation">,</span><br /> <span class="token property">"thumbnail"</span><span class="token operator">:</span> <span class="token string">"wtf-tailwind.jpg"</span><span class="token punctuation">,</span><br /> <span class="token property">"thumbnailAlt"</span><span class="token operator">:</span> <span class="token string">"..."</span><br /><span class="token punctuation">}</span></code></pre>
<p>In <code>.eleventy.js</code> I created a collection based on all Markdown files in the drafts folder:</p>
<pre class="language-js"><code class="language-js"> eleventyConfig<span class="token punctuation">.</span><span class="token function">addCollection</span><span class="token punctuation">(</span><span class="token string">'drafts'</span><span class="token punctuation">,</span> <span class="token parameter">collection</span> <span class="token operator">=></span> <span class="token punctuation">{</span><br /> <span class="token keyword">return</span> <span class="token punctuation">[</span><br /> <span class="token operator">...</span>collection<span class="token punctuation">.</span><span class="token function">getFilteredByGlob</span><span class="token punctuation">(</span><span class="token string">'./_src/drafts/*.md'</span><span class="token punctuation">)</span><br /> <span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">reverse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><br /> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>Then I made an index page that lists all of my drafts as well as a list of ideas that pulls from a data file (<code>_data/ideas.json</code>):</p>
<pre class="language-js"><code class="language-js"><span class="token operator">--</span><span class="token operator">-</span><br /><span class="token literal-property property">title</span><span class="token operator">:</span> Drafts<br /><span class="token literal-property property">layout</span><span class="token operator">:</span> page<br /><span class="token literal-property property">eleventyExcludeFromCollections</span><span class="token operator">:</span> <span class="token boolean">true</span><br /><span class="token operator">--</span><span class="token operator">-</span><br /><br /><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">for</span> post <span class="token keyword">in</span> collections<span class="token punctuation">.</span>drafts <span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token operator">*</span> <span class="token punctuation">[</span><span class="token punctuation">{</span><span class="token punctuation">{</span> post<span class="token punctuation">.</span>data<span class="token punctuation">.</span>title <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span><span class="token punctuation">{</span> post<span class="token punctuation">.</span>url <span class="token punctuation">}</span><span class="token punctuation">}</span></span><span class="token punctuation">)</span><br /><span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span><br /><br />## Ideas<br /><br /><span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">for</span> idea <span class="token keyword">in</span> ideas <span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token operator">*</span> <span class="token punctuation">{</span><span class="token punctuation">{</span> idea <span class="token punctuation">}</span><span class="token punctuation">}</span><br /><span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>Finally, I made sure to add the <code>drafts</code> folder (and ideas list!) to my <code>.gitignore</code> to avoid committing drafts to my repo, which would also deploy them to the live site.</p>
<h2>Displaying a list of tags</h2>
<p>On the previous site, you could click on tags within a post to see all posts with that tag, but there wasn't a way to see all of the tags. Some research turned up a few different ways to achieve this, but they all felt overly complicated.</p>
<p>The solution I landed on was pretty succinct and did exactly what I needed it to do:</p>
<pre class="language-js"><code class="language-js"><span class="token operator"><</span>ul <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"ma-tag-list"</span> role<span class="token operator">=</span><span class="token string">"list"</span><span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">for</span> tag<span class="token punctuation">,</span> posts <span class="token keyword">in</span> collections <span class="token operator">|</span> dictsort <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> <span class="token keyword">if</span> tag <span class="token operator">!=</span> <span class="token string">"all"</span> and tag <span class="token operator">!=</span> <span class="token string">"posts"</span> and tag <span class="token operator">!=</span> <span class="token string">"drafts"</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token operator"><</span>li<span class="token operator">></span><span class="token operator"><</span>a href<span class="token operator">=</span><span class="token string">"/tag/{{ tag | slugify }}"</span> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"ma-tag"</span><span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token punctuation">{</span> tag <span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">{</span> posts<span class="token punctuation">.</span>length <span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token punctuation">)</span><br /> <span class="token operator"><</span><span class="token operator">/</span>a<span class="token operator">></span><span class="token operator"><</span><span class="token operator">/</span>li<span class="token operator">></span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> endif <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> endfor <span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token operator"><</span><span class="token operator">/</span>ul<span class="token operator">></span></code></pre>
<p>The Nunjucks <code>dictsort</code> filter sorts the tags alphabetically. I exclude specific collections in the <code>if</code> block. Finally, I display a link to the tag page that shows all posts with that tag, as well as a count of how many posts include that tag.</p>
<p>Having a list of all the tags helped surface how many tags were only used once, and I ended up stripping most of those out of the individual posts. (Things like specific video game or movie titles, which I'm unlikely to write another post on.)</p>
<p>You can see this tag list on top of the <a href="https://mikeaparicio.com/blog/">Blog</a> page.</p>
<h2>Including a partial with an async shortcode</h2>
<p>For posts I have a card pattern that I use on both the homepage as well as the blog page. In order to not repeat the pattern, I put it in an include. But when I did that, the entire card didn't render and Eleventy didn't throw an error.</p>
<p>I came to found out that if you use a custom shortcode that has an asynchronous function in it, Eleventy tries to build the page before the function can finish and nothing appears.</p>
<p>The solution is rather than using a <code>for</code> loop, you can use Nunjucks' <code>asyncEach</code> instead:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><span class="token operator">%</span> asyncEach post <span class="token keyword">in</span> collections<span class="token punctuation">[</span>tag<span class="token punctuation">]</span> <span class="token operator">|</span> reverse <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> include <span class="token string">"partials/card.njk"</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token punctuation">{</span><span class="token operator">%</span> endeach <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>However, if you try and nest a loop inside of that (<code>if loop.index0 <= 2</code>), it still won't render the include. To show the last three posts on the homepage, I ended up using <code>slice()</code>:</p>
<pre class="language-js"><code class="language-js"><span class="token punctuation">{</span><span class="token operator">%</span> asyncEach post <span class="token keyword">in</span> collections<span class="token punctuation">.</span>posts<span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /> <span class="token punctuation">{</span><span class="token operator">%</span> include <span class="token string">"partials/card.njk"</span> <span class="token operator">%</span><span class="token punctuation">}</span><br /><span class="token punctuation">{</span><span class="token operator">%</span> endeach <span class="token operator">%</span><span class="token punctuation">}</span></code></pre>
<p>Problem solved!</p>
<h2>Use as little HTML as possible</h2>
<p>One of my biggest regrets was that I used entirely too much HTML in my posts because I wanted to have more control over styling without having to style elements like <code>h2</code> directly. This made it really challenging to redesign based on these classes and it was a lot of extra friction in writing new posts.</p>
<p>Instead I decided to lean heavily on Markdown and apply styles to elements within the <code>article</code> element on post pages. The only HTML I ended up keeping were <code>figure</code> elements (as there wasn't a great way to deal with these without a Markdown extension) and third-party embeds like Twitter tweets.</p>
<p>Stripping out all of the HTML from each post and restyling everything proved to be one of the most time-consuming parts of this refactor. But it did give me an opportunity to proofread all of my previous posts and check for typos.</p>
<p>I had seen an article on <a href="https://www.aleksandrhovhannisyan.com/blog/design-mode-in-11ty/">using Design Mode in Eleventy</a>, which was a feature I didn't even know was a thing. It basically makes a whole page behave as if <code>contenteditable</code> were enabled.</p>
<p>Rather than following the article and building design mode into Eleventy, I decided to make a good old-fashioned bookmarklet. To try this yourself, make a new bookmark in your browser of choice and set the following as the link:</p>
<pre class="language-js"><code class="language-js"><span class="token literal-property property">javascript</span><span class="token operator">:</span> document<span class="token punctuation">.</span>designMode<span class="token operator">=</span><span class="token string">"on"</span><span class="token punctuation">;</span><span class="token keyword">void</span> <span class="token number">0</span><span class="token punctuation">;</span></code></pre>
<p>This lets you turn on design mode on <strong>any</strong> webpage by clicking on the bookmark. Design mode will highlight any typos with a little red squiggle.</p>
<p>I could have probably used a spellcheck extension in VSCode, but this was a fun alternative.</p>
<h2>Adding more meaningful copy</h2>
<p>I wanted to tighten up the copy on my homepage and try and give a better sense of what I do. I'm tired of getting recruiters reaching out with opportunities to do feature work, building React components, or other stuff I'm not interested in. Not that recruiters usually bother to read too deeply into someone's background. (If you're a recruiter and you've read this far, here's a cookie: πͺ)</p>
<p>My previous site intro read:</p>
<blockquote>
<p>Hi! I'm Mike Aparicio, a Chicago-based web developer interested in helping companies large and small improve collaboration between design and engineering through the use of design systems.</p>
</blockquote>
<p>Which I trimmed down to:</p>
<blockquote>
<p>Improving collaboration between design and engineering with the power of design systems</p>
</blockquote>
<p>Which is still pretty vague but more concise. There's no longer a need to introduce myself since I changed from a logo to my name in the header, and my location is mostly irrelevant now, thanks to Covid.</p>
<p>I also fleshed out my brief work experience section that highlights my superpower: <strong>creating custom CSS frameworks that empower engineering teams to get from concept to production quickly, while writing little to no CSS.</strong></p>
<p>I also added a section about my weekly stream and added a contact form so that people can more easily get in touch.</p>
<h2>Stretch goals</h2>
<p>Aside from cleaning up the codebase and refreshing the design a bit, my goal for launch was to reach parity feature- and content-wise with the existing site.</p>
<p>Anything beyond that I listed as stretch goals. Some of those goals include:</p>
<p><strong>Adding a design system page.</strong> I want to better outline my approach to design systems and also demonstrate some concepts by documenting the system in use on this site. It's kind of tricky to show design system work in a portfolio because typically you're not designing the visual style of the system (if you're an engineer) and you're not responsible for building the end features. Being able to show a design system in full without having to worry about exposing proprietary company code should be useful!</p>
<p><strong>Adding search.</strong> I don't know if there's much demand for this but I was able to <a href="https://mikeaparicio.com/posts/2021-08-29-adding-algolia-search-with-netlify/">do it pretty easily</a> on the documentation site for Provi's design system so I might as well add it here, too.</p>
<p><strong>Automate Open Graph images.</strong> I've seen a few articles on this and I think I might dig into them a little deeper. Right now I usually just include an image from the post for the social image but it isn't always cropped to the right aspect ratio. I'd love to be able to automate it so that I can continue using any size image and have my build generate the appropriate social images for me.</p>
<p><strong>Add light mode.</strong> It was so weird toggling between the existing site and this redesign. I have gone full dark mode wherever I can, and looking back at the old site burns my retinas now. I realize some people prefer light mode, so I want to give folks that option. I just want to make sure I take the time to do it well and not just invert some colors.</p>
<p><strong>Add more about my previous work.</strong> When I last redid the site I was transitioning from working at Groupon for almost nine years to a new startup at Provi. I didn't have much work to demonstrate at my new gig. But almost two years have passed, so I think I have a lot more to say. I was at Groupon for so long that I don't think the work I did previously was worth highlighting, but at the same time I kind of feel nostalgic about my days of building lots of custom web apps with PHP and MySQL. I also want to showcase more of the old side projects I've been digging up recently.</p>
<h2>Wrapping up</h2>
<p>So that's the new site. I'd love to hear <a href="https://mikeaparicio.com/contact/">your feedback</a>. I'll continue to iterate on it but the most important thing to me is that the codebase is a little leaner and causes me less anxiety when thinking about writing a new post.</p>
<h3>Further reading</h3>
<ul>
<li><a href="https://web.dev/color-scheme/">Improved dark mode default styling with the color-scheme CSS property and the corresponding meta tag</a></li>
<li><a href="https://codepen.io/peruvianidol/pen/JjpOPyM">color-scheme demo on CodePen</a></li>
</ul>
Tips for beating Sifu
2022-02-21T00:00:00Z
https://mikeaparicio.com/posts/2022-02-21-tips-for-beating-sifu/
<p>Sifu (PS4/PS5/PC) has already cemented itself as one of my top games of 2022. It's an action-packed, gorgeously-styled love letter to martial arts movies. It's also an extremely challenging game, taking elements of Souls-likes (shortcuts, beefy bosses) and Rogue-likes (permanent upgrades across runs), which can give players who aren't used to these types of games fits when they're expecting more of a button-mashing brawler.</p>
<p>I was completely absorbed in Sifu and went from barely making it past the first level to earning all the trophies on PS5 in just over two weeks. I know a lot of people are still struggling to get past the second boss, so here's some tips I learned from my time mastering Sifu.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/A6HKoLHhQt-300.webp 300w, https://mikeaparicio.com/images/A6HKoLHhQt-600.webp 600w, https://mikeaparicio.com/images/A6HKoLHhQt-1920.webp 1920w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/A6HKoLHhQt-300.jpeg 300w, https://mikeaparicio.com/images/A6HKoLHhQt-600.jpeg 600w, https://mikeaparicio.com/images/A6HKoLHhQt-1920.jpeg 1920w" sizes="100vw" /><img alt="Your character, dressed in a tank top with his hair in a top knot, faces the interior of a nightclub, where several gangsters are gathered, unaware of their impending doom, near the dance floor." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/A6HKoLHhQt-300.jpeg" width="1920" height="1080" /></picture>
<figcaption>
A Sifu walks into a bar...
</figcaption>
</figure>
<h2>Dealing with incoming attacks</h2>
<p>It's tempting to go into Sifu and just start mashing buttons. It manages to look pretty badass as you pummel enemy after enemy, but it won't get you too far in the game.</p>
<p>The key to Sifu is understanding its four different ways of dealing with incoming attacks and then countering with your own attacks when the opportunity arises.</p>
<h3>Guard</h3>
<p>This is Sifu's term for blocking. Holding the left button without moving the stick will block all incoming attacks, but add to your "structure" meter. When your structure meter is full, your guard will break and you'll be vulnerable to attacks for a brief period of time.</p>
<p>You don't want to guard <strong>every</strong> attack, but you can selectively block high/low attacks while using other means to prevent incoming damage to prevent your structure meter from filling too fast.</p>
<p>A good example is the second boss, Sean, who adds a low, sweeping attack in his second phase. Sean typically opens each string of attacks with either a thrust attack or a sweep attack. Rather than trying to guess which he'll open with, you can <strong>always</strong> block the first attack and then either deflect or avoid his remaining attacks until you have an opening to counter. Once you recognize this pattern and can react to it accordingly, it makes this fight much easier.</p>
<h3>Deflect</h3>
<p>Once you have guarding down, instead of holding the button, you can try and time it with your enemies attacks to deflect them. Deflecting attacks adds to your <strong>enemy's</strong> structure, and potentially breaks their attack, giving you an opening for a quick counter.</p>
<p>Building your enemy's structure is key to beating tough enemies and bosses. If you can break their structure, you can execute a finisher without needing to wear down their entire health bar. (This is especially crucial with bosses if you want to be able to spare them to get the "true" ending.)</p>
<p>The timing of deflects have a relatively long window, so you can sometimes just mash the guard button as your enemy attacks to deflect each one. Once you learn the cadence of enemy attacks, it gets a lot easier to deflect accurately.</p>
<p>However, deflecting also adds to your own structure meter, so be sure to back off and let your structure recover before enduring more attacks.</p>
<h3>Avoid</h3>
<p>Avoiding is a great way to keep your structure meter from filling up while still preventing damage. To avoid an attack, hold the left button as you would to guard, but move the left stick up, down or to either side. This requires similar timing to deflecting, but you also have to be able to anticipate whether the incoming attack is high, medium or low.</p>
<p>Most low-level enemies, especially the kind that can swarm you, will only attack you with mid attacks. So you can often just spam a single direction (left/right) to avoid most attacks.</p>
<p>A successful avoid will briefly slow time, allowing you to counter or get a hit on another nearby enemy. Avoiding also helps build your focus faster, allowing you to unleash unblockable attacks like the eye strike.</p>
<h3>Dodge</h3>
<p>Dodging can be used to quickly get out of the way of an attack, which is especially useful when a group of enemies is closing in around you. To dodge, hold the left button and press the right trigger while holding a direction on the left stick.</p>
<p>Some enemies can unleash a long string of attacks that are too strong or quick to react to. Typically their momentum will carry them straight ahead, allowing you to dodge to the side to avoid their attacks.</p>
<p>The opportunity window to counter after dodging is a lot smaller than other guard methods, but for some enemies, like the third boss, dodging can be vital to escaping the battle without taking a ton of damage.</p>
<h2>Weapons are your best friend</h2>
<p>Weapons are plentiful in Sifu. Bricks, bottles, bats, pipes, sticks, staffs, brooms, knives and machetes can be found throughout the game, giving you a huge advantage in most battles.</p>
<p>You can disarm most enemies with weapons using sweep attacks.</p>
<figure class="ma-float-right">
<video preload="auto" aria-label="Embedded video" src="https://mikeaparicio.com/images/sifu-one-shot.mp4" poster="https://mikeaparicio.com/images/sifu-one-hit.png" type="video/mp4" playsinline="" autoplay="" disablePictureInPicture="" loop="" muted=""></video>
<figcaption>Using the Charged Backfist skill with a knife can bring down the toughest enemies in one hit.</figcaption>
</figure>
<p>Weapons have a limited durability, which can be enhanced through skills and rewards. You can also throw weapons at enemies using the right (R1) button.</p>
<p>The <strong>Environmental Mastery</strong> skill allows you to throw objects like weapons and furniture directly from the ground at enemies to stun, trip or even sometimes kill them.</p>
<p>Even better, the <strong>Charged Backfist</strong> skill, when used with a knife in hand, can <strong>one-shot-kill</strong> any non-boss enemy, immediately destroying the knife in the process. Knives can be found starting on the third level.</p>
<h2>Use i-frames to your advantage</h2>
<p>I-frames, or invincibility frames, is a term that describes a temporary window of invincibility resulting from certain animations. In Sifu, you can use this to deal effectively with multiple enemies who might be surrounding you.</p>
<p>The following attacks give you i-frames:</p>
<ul>
<li>Ground attacks (hold circle/B on a downed enemy)</li>
<li>Finishers (triangle + circle / Y + B, when an enemy's structure is broken)</li>
<li>Focus attacks (left trigger unblockable attacks)</li>
</ul>
<p>You can use these i-frame attacks to temporarily prevent incoming damage. Use this to your advantage if you find yourself getting overwhelmed with groups of enemies.</p>
<h2>Spend XP wisely</h2>
<p>As you progress through the game, you'll earn XP that you can use to unlock skills and rewards. While it's tempting to unlock as many things as possible during a run, it's really to your advantage to focus on putting XP into a single skill at a time.</p>
<p>Spending points on a skill the first time will unlock it for that run, while spending additional points on an unlocked skill five times (across multiple runs) will unlock it permanently. This means you'll start a run with that skill already unlocked and won't have to spend XP to unlock it.</p>
<p>In addition to quickly unlocking skills permanently, this method also lets you learn the new skills more deliberately and work them into your routine.</p>
<p>Keep in mind certain skills can only be unlocked up to a certain age. So you'll want to make sure you focus on unlocking the skills lower in the list before you're too old.</p>
<p>Here are some key skills you'll want to unlock:</p>
<ul>
<li>
<p><strong>Strong Sweep Focus</strong> is an unblockable focus attack that will knock down your enemy, allowing you to follow up with ground strikes or deal with other enemies. It can come in handy against tough enemies and bosses, giving you crucial time for your structure meter to reset.</p>
</li>
<li>
<p><strong>Charged Backfist</strong>, as mentioned above, can one-shot-kill any non-boss enemy when you have a knife equipped, making it incredibly useful on later levels for getting past tough enemies without taking damage. Bare-handed, it can also be quite effective against charging enemies.</p>
</li>
<li>
<p><strong>Environmental Mastery</strong>, also mentioned above, opens up a lot of options for dealing with enemies. You can throw weapons from the ground to stun enemies or kick objects to trip enemies, opening them up to ground attacks. There's even one exhibit in the museum level that is loaded with objects you can throw at the two tough enemies inside.</p>
</li>
<li>
<p><strong>Slide Kick</strong> is a great running attack you can use to drop an enemy to the ground, opening them up for further attacks. Great for closing the distance on certain enemies or getting the jump on unsuspecting foes.</p>
</li>
<li>
<p><strong>Weapon Mastery</strong> lets you use a weapon until it breaks completely. Any additional use you can get out of weapons is worth having.</p>
</li>
</ul>
<p>There's also three rewards you can purchase at shrines using XP:</p>
<ul>
<li>
<p><strong>Focus Reserve</strong> adds 1/2 focus bar, and you can have up to three focus bars total. It can certainly be handy to have some additional focus but, aside from unlocking the trophy for using each focus attack once (<strong>Thigh Cut Focus</strong> requires three focus bars), you'll probably be fine with two bars. You can't use focus attacks at all on the final boss, so your shrine visits might be better spent elsewhere.</p>
</li>
<li>
<p><strong>Weapon Proficiency</strong> improves weapon damage and impact on your opponent's structure. Combined with other weapon bonuses, this can be quite powerful, but it's also 500 XP you could spend on unlocking a skill.</p>
</li>
<li>
<p><strong>Death Counter</strong> resets your death counter to <strong>zero</strong>. This can be useful if you've racked up a lot of deaths, particularly going into a boss fight. It costs 1,000 XP though, so it's best to only buy this when you're trying to make it through a level for the first time and you want to get as many reps in against the boss as possible.</p>
</li>
</ul>
<p>The other shrine rewards can be unlocked with level score or based on your age. They are all moderately useful but you won't be able to unlock all the rewards in a run since there's a limited amount of shrines.</p>
<p>I'd recommend <strong>Focus Regain</strong> to help you build up focus for unblockable attacks more frequently (keeping in mind you can't use focus on the last boss) and <strong>Health Gained on Takedowns</strong> if you find yourself struggling to even get to a boss without racking up a high death counter.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/jyJnGoDXhv-300.webp 300w, https://mikeaparicio.com/images/jyJnGoDXhv-600.webp 600w, https://mikeaparicio.com/images/jyJnGoDXhv-1920.webp 1920w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/jyJnGoDXhv-300.jpeg 300w, https://mikeaparicio.com/images/jyJnGoDXhv-600.jpeg 600w, https://mikeaparicio.com/images/jyJnGoDXhv-1920.jpeg 1920w" sizes="100vw" /><img alt="Sifu's bosses" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/jyJnGoDXhv-300.jpeg" width="1920" height="1034" /></picture>
</figure>
<h2>How to beat the bosses</h2>
<p>Sifu's five bosses can be extremely frustrating until you learn their moves and how to counter them. Be patient, watch their attacks and wait for an opening. After you're able to beat a boss, you'll find it easier and easier to do it again on future runs.</p>
<p>Getting the "true" ending requires you to spare the lives of all five bosses. To do this, you'll need to break their structure in the second phase of the fight, but do not execute the finisher. They will recover some structure, which you'll need to break again, and when you're close enough, you'll be prompted to spare them by pressing left on the D-pad instead of doing the finisher.</p>
<p>Here are some tips for each boss encounter:</p>
<p><strong>Fajar β The Botanist</strong></p>
<p>Fajar is quick, but he mostly attacks mid, allowing you to guard, deflect or avoid his attacks until an opening appears and you can counter. Try spamming avoid in one direction (left/right) to build up your focus and then counter with regular and focus attacks as you're able to.</p>
<p>The second phase his moves are a bit more advanced but the same technique applies. Look around the outskirts of the area for bamboo sticks you can use to gain an edge, and watch out for the trees he grows out of the ground that he can knock you against and stun you with.</p>
<p><strong>Sean β The Fighter</strong></p>
<p>I imagine a lot of people will get stuck on Sean and give up on Sifu, which is a shame because the game gets so much better. Sean is arguably the second toughest boss in the game, but once you learn his moves, he's a piece of cake.</p>
<p>In the first phase, he'll usually lunge with his staff or shoulder and then follow up with a series of three attacks. Block or deflect the first attack and then avoid the next three pushing the one direction (right or left). Counter with a few attacks and then step back and repeat. There are staffs you can pick up along the walls, but Sean is pretty aggressive so be careful not to turn your back on him.</p>
<p>In the second phase, Sean throws in a sweep attack, but the same strategy holds. Block or deflect the first attack and avoid the following attacks. One combo has more than three attacks but can still be avoided just the same. Avoid until you have an opening, and then counter.</p>
<p><strong>Kuroki β The Artist</strong></p>
<p>Keep just out of range of her three-section staff by dodging to the side. Try to time your dodges with her attacks. Look for an opening and attack a few times before backing off. Keep an eye out for pauses between her last few attacks. You'll want to stand clear and observe her combos a few times to get familiar with them. Whittling her down this way takes awhile but it's relatively safe.</p>
<p>In phase two, Kuroki will attack with kunai at close range. Avoid these attacks to the left or right and counter. After about five attacks, she'll leap back a bit and immediately jump back at you with both feet. Dodge again and counter. She'll then jump way back, throwing a spread of kunai one or more times. Avoid again. She may throw individual kunai, avoid again. She will then lower her stance and zig zag or come straight at you. When you see a glint on her kunai, she's about to attack. Avoid immediately and then counter. She'll keep doing this pattern. Once you have it down, you should be able to beat her.</p>
<p><strong>Jinfeng β The CEO</strong></p>
<p>At first this fight feels pretty daunting, but it might be the easiest in the game because of Jinfeng's low health. You should have a weapon from the mini-boss room right before this, when the fight starts it should be right behind you. Jinfeng will throw her chain weapon three times. Avoid left/right twice, and then once up to avoid her sweep, then rush in and attack. Reset your position before she recovers and repeat.</p>
<p>The second phase is similar but she has an attack that can pull you in close before she unleashes a series of attacks. She has a few more close-range combos in this phase, but if you keep your distance, you should be able to repeat the same process above.</p>
<p><strong>Yang β The Leader</strong></p>
<p>This fight feels impossible at first. Yang, a disciple of your father and Sifu, has a similar move set as you with a few unique ones. As I mentioned earlier, you can't use focus attacks on Yang, which adds another layer of difficulty. His structure heals really fast if you struggle to keep pressure on him.</p>
<p>In the first phase, spam deflects as he rushes in and then counter. Keep an eye out when he jumps back, he may immediately rush back in with a sweep, which you can avoid by pushing up on the left stick while guarding and then counterattack. The deflects will quickly raise his structure to a point where he doesn't recover as quickly. Keep it up and you should get to the second phase relatively quickly.</p>
<p>The second phase is much tougher, as Yang has a lot of attacks that Sifu didn't teach you. Here you want to deflect the first two attacks and then keep avoiding the rest until you have an opening. Deflecting the first two attacks will build his structure and also protect you whether Yang opens with a high, mid or low attack. Watch out when he jumps back and leans back with both arms up. He's about to rush in with a series of punishing punches. Spam avoid to the side and then counterattack.</p>
<h2>Winning the game by age 25</h2>
<p>This is by far the toughest trophy to unlock. Replay each level until you have it down cold. Take advantage of shortcuts. The third, fourth and fifth levels have pretty generous shortcuts that can save your from having to fight a ton of enemies.</p>
<p>You'll be able to start each level at the lowest age you reached that level at. You want to try and eventually beat the first two levels without dying. You can maybe die once on the third or fourth level. You want to leave as many opportunities as possible for the ultimate fight with Yang.</p>
<p>If this all sounds impossible, keep at it! The boss fights get much easier once you learn the patterns. You just have to string together a good run of the various fights leading up to the bosses.</p>
<p>Remember, your health refills at each shrine and between each boss phase. Use that mentally to your advantage. Just make it to the next shrine or boss phase without dying.</p>
<h2>Parting Tips</h2>
<p>I'll leave you with a few miscellaneous tips:</p>
<ul>
<li>
<p><strong>Pushing enemies</strong> When an enemy is stunned or in a finisher state, you can press square + X/X + A to throw them against a wall or other enemies. If they are near a ledge/railing you can throw them over. Enemies tend to die from fall damage from even the shortest drops. There's also a trophy for throwing someone into the museum fountain from an upper floor, which is extremely satisfying!</p>
</li>
<li>
<p><strong>Ignoring enemies</strong> There are certain sections where enemies will not attack you unless you attack them first. Use this to your advantage to make it through levels while taking as little damage as possible. This is especially true in the Club and Tower levels.</p>
</li>
<li>
<p><strong>Sneak Attacks</strong> If an enemy is not aware of your presence, you can finish them after a single hit. There are several areas where you can capitalize on this, including the hangar in the first level (there's a trophy for completing it within 90 seconds after alerting an enemy). Work around the perimeter and you can take out at least three enemies before anyone knows your there, making this trophy a lot easier.</p>
</li>
<li>
<p><strong>Mantling obstacles</strong> You can press X/A to vault over tables, low walls and other obstacles. Use this technique to keep some distance between yourself and large groups of enemies, allowing you to pick off stragglers and even the odds.</p>
</li>
<li>
<p><strong>Don't always take shortcuts</strong> If you're trying to unlock as many skills and rewards as possible, you might want to avoid taking shortcuts in some situations. There's a path you can take in the third level after unlocking the shortcuts that allows you to access three shrines without having to fight your way through all the exhibits.</p>
</li>
</ul>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/0TXRKJGDu--300.webp 300w, https://mikeaparicio.com/images/0TXRKJGDu--600.webp 600w, https://mikeaparicio.com/images/0TXRKJGDu--3584.webp 3584w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/0TXRKJGDu--300.jpeg 300w, https://mikeaparicio.com/images/0TXRKJGDu--600.jpeg 600w, https://mikeaparicio.com/images/0TXRKJGDu--3584.jpeg 3584w" sizes="100vw" /><img alt="Sifu's homage to Old Boy" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/0TXRKJGDu--300.jpeg" width="3584" height="1199" /></picture>
<figcaption>
Sifu pays homage to a number of iconic fight scenes, like the hallway fight from Oldboy.
</figcaption>
</figure>
<h2>Good luck on your path to vengeance!</h2>
<p>Hopefully you found this guide helpful! Sifu can be extremely challenging but also incredibly satisfying when you elegantly plow your way through waves of enemies.</p>
2021
2022-01-01T00:00:00Z
https://mikeaparicio.com/posts/2022-01-01-2021/
<p>I'm still reeling from 2020 and here we are in 2022. It seems as I get older that each year feels simultaneously like the longest and shortest year of my life. 2021 was no exception. I had a particularly hard time thinking of highlights because I feel like I barely left the house. I did manage to come up with a few.</p>
<p><strong>Ryan.</strong> My son turned two in January and it's been amazing to see him develop his vocabulary and his personality. I can't believe it's been almost three years since he was born. It went by so fast. It was especially fun seeing him learn and get excited about holidays like Halloween and Christmas this year. Last year it just kind of washed over him and he took it all in, but in 2021 he really got into all of the little rituals and traditions. Seeing the most ordinary things through his eyes, like popping popcorn, was so amazing.</p>
<figure>
<blockquote class="instagram-media" data-instgrm-permalink="https://www.instagram.com/tv/CXuYgYXl5Er/?utm_source=ig_embed&utm_campaign=loading" data-instgrm-version="14" style=" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:540px; min-width:326px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);"><div style="padding:16px;"> <a href="https://www.instagram.com/tv/CXuYgYXl5Er/?utm_source=ig_embed&utm_campaign=loading" style=" background:#FFFFFF; line-height:0; padding:0 0; text-align:center; text-decoration:none; width:100%;" target="_blank"> <div style=" display: flex; flex-direction: row; align-items: center;"> <div style="background-color: #F4F4F4; border-radius: 50%; flex-grow: 0; height: 40px; margin-right: 14px; width: 40px;"></div> <div style="display: flex; flex-direction: column; flex-grow: 1; justify-content: center;"> <div style=" background-color: #F4F4F4; border-radius: 4px; flex-grow: 0; height: 14px; margin-bottom: 6px; width: 100px;"></div> <div style=" background-color: #F4F4F4; border-radius: 4px; flex-grow: 0; height: 14px; width: 60px;"></div></div></div><div style="padding: 19% 0;"></div> <div style="display:block; height:50px; margin:0 auto 12px; width:50px;"><svg width="50px" height="50px" viewBox="0 0 60 60" version="1.1" xmlns="https://www.w3.org/2000/svg" xmlns:xlink="https://www.w3.org/1999/xlink"><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g transform="translate(-511.000000, -20.000000)" fill="#000000"><g><path d="M556.869,30.41 C554.814,30.41 553.148,32.076 553.148,34.131 C553.148,36.186 554.814,37.852 556.869,37.852 C558.924,37.852 560.59,36.186 560.59,34.131 C560.59,32.076 558.924,30.41 556.869,30.41 M541,60.657 C535.114,60.657 530.342,55.887 530.342,50 C530.342,44.114 535.114,39.342 541,39.342 C546.887,39.342 551.658,44.114 551.658,50 C551.658,55.887 546.887,60.657 541,60.657 M541,33.886 C532.1,33.886 524.886,41.1 524.886,50 C524.886,58.899 532.1,66.113 541,66.113 C549.9,66.113 557.115,58.899 557.115,50 C557.115,41.1 549.9,33.886 541,33.886 M565.378,62.101 C565.244,65.022 564.756,66.606 564.346,67.663 C563.803,69.06 563.154,70.057 562.106,71.106 C561.058,72.155 560.06,72.803 558.662,73.347 C557.607,73.757 556.021,74.244 553.102,74.378 C549.944,74.521 548.997,74.552 541,74.552 C533.003,74.552 532.056,74.521 528.898,74.378 C525.979,74.244 524.393,73.757 523.338,73.347 C521.94,72.803 520.942,72.155 519.894,71.106 C518.846,70.057 518.197,69.06 517.654,67.663 C517.244,66.606 516.755,65.022 516.623,62.101 C516.479,58.943 516.448,57.996 516.448,50 C516.448,42.003 516.479,41.056 516.623,37.899 C516.755,34.978 517.244,33.391 517.654,32.338 C518.197,30.938 518.846,29.942 519.894,28.894 C520.942,27.846 521.94,27.196 523.338,26.654 C524.393,26.244 525.979,25.756 528.898,25.623 C532.057,25.479 533.004,25.448 541,25.448 C548.997,25.448 549.943,25.479 553.102,25.623 C556.021,25.756 557.607,26.244 558.662,26.654 C560.06,27.196 561.058,27.846 562.106,28.894 C563.154,29.942 563.803,30.938 564.346,32.338 C564.756,33.391 565.244,34.978 565.378,37.899 C565.522,41.056 565.552,42.003 565.552,50 C565.552,57.996 565.522,58.943 565.378,62.101 M570.82,37.631 C570.674,34.438 570.167,32.258 569.425,30.349 C568.659,28.377 567.633,26.702 565.965,25.035 C564.297,23.368 562.623,22.342 560.652,21.575 C558.743,20.834 556.562,20.326 553.369,20.18 C550.169,20.033 549.148,20 541,20 C532.853,20 531.831,20.033 528.631,20.18 C525.438,20.326 523.257,20.834 521.349,21.575 C519.376,22.342 517.703,23.368 516.035,25.035 C514.368,26.702 513.342,28.377 512.574,30.349 C511.834,32.258 511.326,34.438 511.181,37.631 C511.035,40.831 511,41.851 511,50 C511,58.147 511.035,59.17 511.181,62.369 C511.326,65.562 511.834,67.743 512.574,69.651 C513.342,71.625 514.368,73.296 516.035,74.965 C517.703,76.634 519.376,77.658 521.349,78.425 C523.257,79.167 525.438,79.673 528.631,79.82 C531.831,79.965 532.853,80.001 541,80.001 C549.148,80.001 550.169,79.965 553.369,79.82 C556.562,79.673 558.743,79.167 560.652,78.425 C562.623,77.658 564.297,76.634 565.965,74.965 C567.633,73.296 568.659,71.625 569.425,69.651 C570.167,67.743 570.674,65.562 570.82,62.369 C570.966,59.17 571,58.147 571,50 C571,41.851 570.966,40.831 570.82,37.631"></path></g></g></g></svg></div><div style="padding-top: 8px;"> <div style=" color:#3897f0; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:550; line-height:18px;">View this post on Instagram</div></div><div style="padding: 12.5% 0;"></div> <div style="display: flex; flex-direction: row; margin-bottom: 14px; align-items: center;"><div> <div style="background-color: #F4F4F4; border-radius: 50%; height: 12.5px; width: 12.5px; transform: translateX(0px) translateY(7px);"></div> <div style="background-color: #F4F4F4; height: 12.5px; transform: rotate(-45deg) translateX(3px) translateY(1px); width: 12.5px; flex-grow: 0; margin-right: 14px; margin-left: 2px;"></div> <div style="background-color: #F4F4F4; border-radius: 50%; height: 12.5px; width: 12.5px; transform: translateX(9px) translateY(-18px);"></div></div><div style="margin-left: 8px;"> <div style=" background-color: #F4F4F4; border-radius: 50%; flex-grow: 0; height: 20px; width: 20px;"></div> <div style=" width: 0; height: 0; border-top: 2px solid transparent; border-left: 6px solid #f4f4f4; border-bottom: 2px solid transparent; transform: translateX(16px) translateY(-4px) rotate(30deg)"></div></div><div style="margin-left: auto;"> <div style=" width: 0px; border-top: 8px solid #F4F4F4; border-right: 8px solid transparent; transform: translateY(16px);"></div> <div style=" background-color: #F4F4F4; flex-grow: 0; height: 12px; width: 16px; transform: translateY(-4px);"></div> <div style=" width: 0; height: 0; border-top: 8px solid #F4F4F4; border-left: 8px solid transparent; transform: translateY(-4px) translateX(8px);"></div></div></div> <div style="display: flex; flex-direction: column; flex-grow: 1; justify-content: center; margin-bottom: 24px;"> <div style=" background-color: #F4F4F4; border-radius: 4px; flex-grow: 0; height: 14px; margin-bottom: 6px; width: 224px;"></div> <div style=" background-color: #F4F4F4; border-radius: 4px; flex-grow: 0; height: 14px; width: 144px;"></div></div></a><p style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;"><a href="https://www.instagram.com/tv/CXuYgYXl5Er/?utm_source=ig_embed&utm_campaign=loading" style=" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none;" target="_blank">A post shared by Mike A (@peruvianidol)</a></p></div></blockquote> <script async="" src="https://www.instagram.com/embed.js"></script>
</figure>
<p><strong>Leaning into online communities.</strong> Early in the year I started watching a lot of web dev streams on Twitch. One of them, <a href="https://frontend.horse/">Frontend Horse</a>, has a community Discord filled with a bunch of lovely creative developers. I really felt like I found my people. I ended up <a href="https://youtu.be/69rQrjMt2go">being a guest</a> on Frontend Horse, as well as <a href="https://youtu.be/wX3z42LbfbI">Some Antics</a>, talking about design systems. I also did a <a href="https://mikeaparicio.com/template-talk/">short talk on templating</a> at the first Eleventy Meetup.</p>
<p>I was inspired to start my own regular <a href="https://twitch.tv/peruvianidol">Twitch stream</a>, Fridays at 1pm Central, where I talk about and answer questions about design systems, CSS, Eleventy and other topics. It's been a lot of fun working in the open and connecting with folks in the industry.</p>
<p><strong>New side projects.</strong> Twitter was especially exhausting last January and I thought about how nice it would be to have a social media site free from hot takes, faux outrage and memes. Thus <a href="https://dogsof.dev/">Dogs of Dev</a> was born. A site that's just a bunch of pictures of dogs of people who make websites. There's currently close to 100 dogs! If you're a designer, developer or even tangentially involved with making websites, I'd love to add your pup(s)!</p>
<p>I also resurrected an old project from 2007, <a href="https://myfakeseason.netlify.app/">My Fake Season</a>, which was originally built with PHP and MySQL. I rebuilt the whole thing in Eleventy, which was an interesting challenge. Especially since I didn't have access to the original database and had to pull a lot of the rendered content from the Internet Archive.</p>
<p>That project got me thinking about how I could replicate some of the old features I built for various basketball projects with a static site generator. I ended up making a <a href="https://nba-schedule.netlify.app/">Chicago Bulls schedule</a> that pulls data from the NBA API. I've been meaning to update it so that you can view any team's schedule, but in the meantime it's been useful for me to be able to check out who the Bulls are playing and the results of past games. I have a GitHub action that rebuilds the site at 1am each day to get the latest results.</p>
<p>I also made an <a href="https://github.com/peruvianidol/11ty-starter">Eleventy starter</a> that's been useful for quickly spinning up new sites, as well as an attempt to abstract my CSS methodology, <a href="https://mikeaparicio.com/posts/2021-03-25-cool-css/">Cool CSS</a>, into a <a href="https://github.com/peruvianidol/coolcss">small framework</a> I can use across projects and customize via design tokens. I still have a lot to do on that one, but I think it will be pretty useful in the long run.</p>
<p><strong>Health issues.</strong> This seems to be a recurring theme as I get older. For awhile I was experiencing some weird abdominal pain that several doctors dismissed as acid reflux, but I was convinced it was not that. I ended up getting an endoscopy which didn't show anything out of the ordinary.</p>
<p>That same week I started having really bad tachycardia, where my resting heart rate was around 130 bpm, and the slightest exertion would raise it to ~160. I ended up going to the ER and, after a bunch of tests, they weren't able to figure it out.</p>
<p>Within a few weeks it all resolved itself, but it's not much comfort having gone through all that testing and not finding the cause. Ever since having that AFib episode a few years ago, any time something feels off, I get really anxious and that just makes things worse. It's like a vicious feedback loop that's really hard to get back to normal.</p>
<p><strong>We raised $7,815 for Extra Life.</strong> Bert, Al and I had another record-breaking year, playing video games for 24 hours <a href="https://www.extra-life.org/">to support Lurie Children's Hospital in Chicago</a>. To celebrate Olivia's birthday, I did a 12-hour stream where I raised almost half of my personal goal of $5000 and matched the first $1000 of donations. I think I'm going to start doing this every year, in addition to the regular marathon the first Saturday in November. To date, we've raised over $32,000 in Olivia's memory to help other sick children in Chicago.</p>
<p>I'm so grateful to Bert and Al for doing this with me year after year, and to everyone who generously donated this year and in years past. I'm really humbled each year by the support and encouragement.</p>
<h2>Things I loved in 2021</h2>
<h3>Movies</h3>
<p>The pandemic made for yet another rough year for the movie business. After completely failing my goal of watching a movie a day in 2020, I did manage to watch a single movie I'd never seen from each year since the year I was born. I wrote <a href="https://mikeaparicio.com/posts/2021-11-29-my-movie-a-year-challenge/">a recap of the highs and lows</a> and already have <a href="https://letterboxd.com/peruvianidol/list/movie-a-year-challenge-2022/">a list ready for 2022</a>.</p>
<p>There were a number of 2021 releases I enjoyed:</p>
<p><strong>Dune</strong> I went into this with high expectations, despite not having read the book or seen the Lynch version. All I knew was this was a passion project for Villeneuve, whose other films rank among my all-time favorites. Again I was blown away by his world-building and attention to detail. Dune handles exposition in clever and subtle ways, without just having characters recite everything you need to know. Loved all the performances from the ensemble cast. The biggest complaint people seem to have about this is it's abrupt ending, but it felt like a natural stopping point and had me excited for what's to come, much like the first Lord of the Rings film.</p>
<p><strong>Inside</strong> An incredible work of genius. It captures what we've all been feeling over the course of the pandemic in a weird, meta fever dream. So many inventive uses of lighting, editing and sound. I was constantly in awe. I alternated between laughing and wondering if Bo is ok. The songs are on Spotify and I listened to them quite a bit this year.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/4jyLtqrX2Q-300.webp 300w, https://mikeaparicio.com/images/4jyLtqrX2Q-600.webp 600w, https://mikeaparicio.com/images/4jyLtqrX2Q-1024.webp 1024w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/4jyLtqrX2Q-300.jpeg 300w, https://mikeaparicio.com/images/4jyLtqrX2Q-600.jpeg 600w, https://mikeaparicio.com/images/4jyLtqrX2Q-1024.jpeg 1024w" sizes="100vw" /><img alt="A still from Bo Burnham's Inside" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/4jyLtqrX2Q-300.jpeg" width="1024" height="576" /></picture>
<figcaption>
Filmed in a single room, Bo Burnham's special Inside features lots of inventive lighting and projection work.
</figcaption>
</figure>
<p><strong>The Harder They Fall</strong> Dripping with style with a fantastic cast and a banging soundtrack. Easily one of the best Westerns in years. I had a lot of fun with it.</p>
<p><strong>Pig</strong> A restrained performance from Cage, maybe one of his best. He doesn't even really speak that much but when he does it's remarkable. This isn't John Wick in the Portland restaurant scene, as the trailer would have you believe. It's more of a character study where everyone is grieving something lost.</p>
<p><strong>C'mon C'mon</strong> This movie really got me thinking about the fallibility of our memory and how some of the most influential periods of our lives are reduced to flashes over time, if we even remember them at all. And how our recollections of the same event can be so different. Joaquin Phoenix was excellent as always and Woody Norman is wonderful as his young nephew. I got emotional several times thinking about my relationship with my son and how cool it is to see his personality forming already at the age of two. What will the future look like for him and what will he think about it?</p>
<p><strong>Others worth mentioning:</strong> <strong>Bad Trip</strong> was the hardest I laughed all year. A very loose narrative around what's basically a hidden camera show, Eric Andre, Lil Rel Howery and Tiffany Haddish do some outrageous stuff in front of unsuspecting bystanders. And <strong>Spider-Man: No Way Home</strong> was incredibly ambitious and wildly entertaining, paying off 20+ years of Spider-Man films in unexpected ways. A fitting conclusion to Marvel's Spidey trilogy, and hopefully not the last we'll see of him in the MCU.</p>
<p>You can find the rest of my <a href="https://letterboxd.com/peruvianidol/list/favorite-films-of-2021/">favorite films of 2021</a> over on Letterboxd.</p>
<h3>TV</h3>
<p><strong>Squid Game</strong> If you haven't seen this Korean show that had everyone talking, I don't want to spoil anything for you. I'll just say it was probably the best thing I watched on TV this year and I burned through it in a day. The end of the first episode is bananas and will leave you wanting more. I had a few nitpicks but overall this show is a thrill ride.</p>
<p><strong>I Think You Should Leave with Tim Robinson</strong> Season two was somehow even more hilarious than the first. My only complaint is that the episodes are so short and there's only six of them. But at the same time it makes it easy to re-watch again and again. This season brought us sloppy steaks, Dan Flashes, and a guy who doesn't want to be around anymore.</p>
<figure>
<iframe src="https://www.youtube.com/embed/J4Fv3LFGCgo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</figure>
<p><strong>Sex Education</strong> I unapologetically love this British teen sex comedy about a high school student who makes money as a sex therapist to his classmates. The cast is great and diverse and the show tackles all different aspects of sex and sexuality with earnestness that's very endearing.</p>
<p><strong>What We Do in the Shadows</strong> This TV spinoff of the 2014 film really hit its stride in its third season. It's a mockumentary about a group of vampires and their familiar (who happens to be a descendant of Van Helsing), living in New Jersey. The performances and writing are fantastic. One of the funniest shows on television.</p>
<p><strong>How To with John Wilson</strong> I mentioned the first season of this documentary series last year. The latest season is so good. It's such a unique format, with a narrative built around seemingly random clips of life in New York City. Every episode begins with a premise that goes on outrageously unexpected tangents.</p>
<p><strong>Others worth mentioning:</strong> <strong>Invincible</strong> is an adaptation of a graphic novel that poses the question: what if Superman was evil? Incredibly dark with a great cast. I ended up buying all of the graphic novels. <strong>Curb Your Enthusiasm</strong> is having quite a run in its 11th(!) season. Outrageous scenarios played out by the usual Curb crew and some amazing guests. <strong>In and of Itself</strong> is ostensibly a live magic show, but so much more. Derek DelGaudio is captivating as he explores the idea of identity. One of the best specials I watched this year. <strong>Station Eleven</strong> is a late contender but one I'm enjoying, about a post-apocalyptic troupe of traveling performers keeping culture alive. Has some Lost vibes with flashbacks to the past of various characters.</p>
<h3>Video Games</h3>
<p><strong>Returnal</strong> I absolutely loved this game about an astronaut who is stranded on a remote planet and wakes up on her crashed ship each time she dies. It's a third-person action game with elements of "bullet hell" shooters and it's absolutely gorgeous to look at. The movement and shooting feels so good, largely due to its innovative use of Sony's DualSense controller.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/g2cQCmik4_-300.webp 300w, https://mikeaparicio.com/images/g2cQCmik4_-600.webp 600w, https://mikeaparicio.com/images/g2cQCmik4_-3584.webp 3584w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/g2cQCmik4_-300.jpeg 300w, https://mikeaparicio.com/images/g2cQCmik4_-600.jpeg 600w, https://mikeaparicio.com/images/g2cQCmik4_-3584.jpeg 3584w" sizes="100vw" /><img alt="Astronaut Selene stands outside a portal to another biome in Returnal" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/g2cQCmik4_-300.jpeg" width="3584" height="2018" /></picture>
<figcaption>
Selene uses extraterrestrial portals to traverse between biomes in Returnal.
</figcaption>
</figure>
<p>It's definitely an unforgiving game, much like Dark Souls, but if you can power through, the story and the action are great. I've been dying to talk about the end of the first act but only one person I know has made it that far. Hands down my game of the year.</p>
<p><strong>Hades</strong> I briefly checked out Hades when it came out in 2020 on PC and couldn't get into it. Based on recommendations from several people and comparisons to Returnal, I decided to try it again when it was released on PS5 in 2021 and I fell in love with it. It's a beautifully-styled rougelike with fantastic gameplay and lots of interesting weapons, abilities and mechanics. A typical run takes 20-30 minutes and it's very easy to lose several hours to "just one more run."</p>
<p><strong>Halo Infinite</strong> I've never been a big Halo guy, but with Halo Infinite releasing on Xbox Game Pass, all of my friends had access to it. I had so much fun jumping into matches with a full fireteam, sometimes with as many as seven or eight other people in Big Team Battle. Its longer time-to-kill compared to other shooters like Call of Duty or Destiny makes it feel much more tactical and a bit less sweaty (intense).</p>
<p>The campaign was a bit monotonous, but I still had a lot of fun with its open world and the new grappling hook makes traversing the world easier and adds some interesting tactics to the combat. I'm looking forward to seeing how this game evolves over time and whether it can keep people's interest among the glut of battle royales like Warzone and Fortnite.</p>
<p><strong>Fights in Tight Spaces</strong> I started playing this turn-based strategy game when it released in early access and was surprised at how solid it was in such an early state. It combines the deck building of Slay the Spire with the tactical action of XCOM, and has an art style reminiscent of Superhot. So basically it was made just for me.</p>
<p>You play as a John Wick-type character, navigating your way through tiny maps and using a variety of cards representing different martial arts moves to take on a group of bad guys. It can be wickedly unforgiving, but extremely rewarding when you make it past a level. I don't even think I ever beat the game, but its one that I've been meaning to revisit since it recently had its official launch.</p>
<p><strong>Hitman 3</strong> I can't believe this game came out last January. It seems like ages ago that I played this. The third installment in the latest iteration of the Hitman series adds six new levels, each a gorgeous sandbox where you have to assassinate your targets in various ways while avoiding suspicion from the hundreds of characters that populate each level. The levels are incredible too, taking you from a skyscraper in Dubai to a nightclub in Berlin to a palatial estate where you play out a scenario right out of Knives Out.</p>
<p>There's so much replayability in Hitman, since you can complete your objective in any number of ways, and are in fact encouraged to do so through dozens of challenges. The Escalation Contracts mode has you assassinating different characters on the map with increasingly challenging modifiers, such as not being seen, killing them with a certain weapon, or without swapping outfits. There is no better murder simulator on the market.</p>
<p><strong>Warzone</strong> When I wasn't playing one of the games above, I was probably playing Call of Duty's Warzone with the boys: Dave, Jose and Riz. We mostly played the smaller Rebirth Island map, where we'd usually get at least one win a night. We did have an incredible quads win in Battle Royale where we kept doing recon contracts on the train until we pinpointed where the final circle would end up. That was a thrill.</p>
<figure class="ma-embed">
<iframe src="https://www.youtube.com/embed/gr70d8a0E0M" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
</figure>
<p>I haven't spent much time with it since the new Caldera map was released. I played exactly one match on the new map and wasn't feeling it. Maybe when the novelty of Halo wears off I'll give it another go.</p>
<h2>Looking forward to in 2022</h2>
<p><strong>Updating the bathroom (finally?)</strong> I mentioned last year that we were planning on updating our upstairs bathroom in 2021 and literally nothing got done. We worked with a designer to figure out a look and got an estimate from a contractor only to be blown off month after month. I don't know why it's so hard to give people money. It seems like unless you're doing a gut rehab and spending hundreds of thousands of dollars, contractors don't even want to give you the time of day. Meanwhile I've already dropped over $10k on designs and materials and have nothing to show for it. Hopefully it'll finally get done in 2022.</p>
<p><strong>Traveling (finally?)</strong> I mentioned this last year too and the furthest I made it was about an hour drive from my house. I really miss traveling. Hoping I can get in at least one trip outside of Illinois.</p>
<p><strong>The next phase in my career</strong> I still have no idea what this looks like. It feels like I made some strides this year in getting some more exposure as someone who knows a fair bit about design systems and CSS. I've talked to my boss about possibly going down the management route but feel like I'd miss the work. I've also thought about doing consulting, but the thought of having to constantly find new clients stresses me out. In the meantime, I'm just going with the flow and trying to enjoy the ride.</p>
<p><strong>We're having another baby</strong> Oh yeah, I buried the lede again. Allie and I are expecting a baby boy in May. Normally that would be great news and cause for celebration but I've been reluctant to share it. After we lost <a href="https://mikeaparicio.com/posts/2018-08-26-four-years/">Olivia</a>, we went through a lot trying to have another baby. When Allie was pregnant with Ryan we were both incredibly anxious about whether the baby would be affected by the same condition Olivia had or if Allie would give birth prematurely again. It was extremely stressful.</p>
<p>This time it feels a little less scary but there's still a lot of uncertainty. I won't be able to breathe easily until the baby is born. We'll be so lucky if we end up with another one as healthy and perfect as Ryan.</p>
<h2>Happy New Year!</h2>
<p>If you've made it this far, thanks for reading! I hope you find peace this year in spite of how messed up everything can feel these days. Take it easy on yourself and each other. We only tend to see everyone's highlights online but we're all struggling to get through this in one way or another. Always feel free to reach out if you need a friendly ear. Take care!</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/rTZWU8VoZ--300.webp 300w, https://mikeaparicio.com/images/rTZWU8VoZ--600.webp 600w, https://mikeaparicio.com/images/rTZWU8VoZ--4032.webp 4032w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/rTZWU8VoZ--300.jpeg 300w, https://mikeaparicio.com/images/rTZWU8VoZ--600.jpeg 600w, https://mikeaparicio.com/images/rTZWU8VoZ--4032.jpeg 4032w" sizes="100vw" /><img alt="Ryan holding hands with Santa" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/rTZWU8VoZ--300.jpeg" width="4032" height="3024" /></picture>
<figcaption>
Happy New Year from Ryan and the Aparicios!
</figcaption>
</figure>
Games as a Service are Ruining Gaming
2021-12-21T00:00:00Z
https://mikeaparicio.com/posts/2021-12-21-games-as-a-service-are-ruining-gaming/
<p>There was once a time when I could check out a different video game every few weeks, burn through it, and move onto the next one. These days I find myself playing one or two different games for months on end, grinding out XP and completing daily challenges so I can get a fancy coat of paint for a gun I'll never use or a double XP token I can redeem to get it twice as fast.</p>
<p>The whole "games as a service" or "live-service" model of games became a popular way of extending the shelf life of games and, more importantly, monetizing those games beyond their initial purchase price.</p>
<p>It's been a thing since MMOs started charging subscription fees back in the day, and has evolved into a constant stream of content doled out slowly over the course of "seasons" β arbitrary chunks of time where you have a limited opportunity to acquire mostly cosmetic items (i.e. not affecting gameplay) by playing the game or via micro-transactions.</p>
<p>Damn near every triple-A multiplayer game does this now. Destiny, Fortnite, Apex Legends, Call of Duty, Halo Infinite and NBA 2k, to name a few. Some are more rewarding than others, but they all follow the same pattern. You buy a "Battle Pass", usually for $10-20 per season (each spanning 6-8 weeks), and unlock items by progressing through the pass. You can also pay <strong>more</strong> money to unlock levels of the pass (often ~100 levels per season). There's also a store where you can buy other stuff exclusively for real-world money.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/adB1dzHyxy-300.webp 300w, https://mikeaparicio.com/images/adB1dzHyxy-600.webp 600w, https://mikeaparicio.com/images/adB1dzHyxy-3840.webp 3840w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/adB1dzHyxy-300.jpeg 300w, https://mikeaparicio.com/images/adB1dzHyxy-600.jpeg 600w, https://mikeaparicio.com/images/adB1dzHyxy-3840.jpeg 3840w" sizes="100vw" /><img alt="Grinding the Halo Battle Pass could net you a sweet shoulder pad." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/adB1dzHyxy-300.jpeg" width="3840" height="2160" /></picture>
<figcaption>
Halo Infinite's Battle Pass has a shoulder pad as one of its rewards. Not an entire skin, just a single shoulder pad. (The right one.)
</figcaption>
</figure>
<h2>Destiny</h2>
<p>Destiny was the first game I played that followed this model. I had a ton of fun with it, logging on and playing with friends each night as we grinded for new guns, emotes, vehicles and other virtual tchotchkes. Most of it you could get as random drops from playing the game or participating in limited-time seasonal activities. Some of it you could only get by dropping cold, hard cash in the "Eververse Store".</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/PkXj7YUWVF-300.webp 300w, https://mikeaparicio.com/images/PkXj7YUWVF-600.webp 600w, https://mikeaparicio.com/images/PkXj7YUWVF-2354.webp 2354w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/PkXj7YUWVF-300.jpeg 300w, https://mikeaparicio.com/images/PkXj7YUWVF-600.jpeg 600w, https://mikeaparicio.com/images/PkXj7YUWVF-2354.jpeg 2354w" sizes="100vw" /><img alt="My Destiny Space Barbie, a decked out Hunter." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/PkXj7YUWVF-300.jpeg" width="2354" height="1549" /></picture>
<figcaption>
My Destiny Space Barbie.
</figcaption>
</figure>
<p>For many years(!) I was content doing this, sinking thousands of hours(!!) and who knows how much money into dressing up my virtual space Barbie. Eventually I got tired of having to do the same monotonous activities for a bunch of gear that quickly became obsolete as soon as the next thing dropped.</p>
<p>I eventually quit Destiny cold-turkey, but I couldn't escape the allure of live-service games like it.</p>
<h2>NBA 2k</h2>
<p>The NBA 2k series is probably the most egregious offender of charging you money for a bunch of useless virtual stuff. On top of the $60 price tag for the game itself (of which annual versions β slightly modified versions of the previous year's game β require shelling out another $60), the game is relentless in its use of virtual currency (cleverly named "VC") in all of its many modes.</p>
<p>Like creating your own player and working your way through the ups and downs of an NBA career while playing pickup games? NBA 2k has a mode for that, complete with story lines directed by the likes of Spike Lee or starring A-list celebs like Idris Elba. You usually play a top prospect... and the game starts you as one of the lowest rated players in the league.</p>
<p>Oh, you're the #1 draft pick? Congrats, you're now the third-string point guard for the Cleveland Cavaliers. But for the low price of US$100, you can bump your rating instantly from a 65 to an 85 and deck yourself out in Nike gear from head to toe, while all those poor kids have to grind it out for months while wearing grey sweats, a brown tee shirt and a pair of Kirkland shoes. (CostCo makes shoes, right?)</p>
<p>You'd rather open a bunch of packs of cards and build a team of NBA stars past and present? NBA 2k has you covered with MyTeam, where you start off with a bunch of the worst players to ever lace up a pair of Jordans and get thrown into games with people who have shelled out hundreds, if not thousands of dollars for a chance to pick up rare and powerful cards.</p>
<p>Want to buy some of those cards? That'll be US$100, please. But you won't get <strong>those</strong> cards. Instead here's the 12th man on the worst team in the league and a pair of Reebok Pumps that will boost that player's free throw rating by one point for a single game. Oh, whoops, that player has a real-life contract with Nike, so they can't even wear those Reeboks.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/a1NihzDRHR-300.webp 300w, https://mikeaparicio.com/images/a1NihzDRHR-600.webp 600w, https://mikeaparicio.com/images/a1NihzDRHR-2175.webp 2175w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/a1NihzDRHR-300.jpeg 300w, https://mikeaparicio.com/images/a1NihzDRHR-600.jpeg 600w, https://mikeaparicio.com/images/a1NihzDRHR-2175.jpeg 2175w" sizes="100vw" /><img alt="2K advertises possible pack contents as highly-rated cards of Kobe, Magic or Steve Nash" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/a1NihzDRHR-300.jpeg" width="2175" height="1086" /></picture>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/cFCGZfwqR0-300.webp 300w, https://mikeaparicio.com/images/cFCGZfwqR0-600.webp 600w, https://mikeaparicio.com/images/cFCGZfwqR0-1920.webp 1920w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/cFCGZfwqR0-300.jpeg 300w, https://mikeaparicio.com/images/cFCGZfwqR0-600.jpeg 600w, https://mikeaparicio.com/images/cFCGZfwqR0-1920.jpeg 1920w" sizes="100vw" /><img alt="A typical pack of virtual cards in NBA 2k's MyTeam mode." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/cFCGZfwqR0-300.jpeg" width="1920" height="1080" /></picture>
<figcaption>
What they advertise as possible pack contents vs. what you actually end up getting.
</figcaption>
</figure>
<p>If this sounds absolutely insane, it's because it is. And NBA 2k's publisher, Take Two, is <a href="https://venturebeat.com/2020/05/20/take-two-hits-record-financials-with-in-game-revenues-up-34/">raking in BILLIONS a year</a> cranking out useless digital crap in games like GTA Online and NBA 2k and selling it to your kids. (And dumb-ass grownups like me.)</p>
<p>On top of that the game is plastered with advertisements for everything from Gatorade, to various shoe brands, to a guest appearance from Jake from fucking State Farm. (I wish I were joking.)</p>
<h2>And others...</h2>
<p>Call of Duty's massively popular Warzone, a free-to-play battle royale game, is also all-in on the live-service model, pumping out fresh cosmetic items in their store almost daily. And most recently, Halo Infinite launched with a free-to-play multiplayer mode with a seasonal "Battle Pass" that <a href="https://www.ign.com/articles/halo-infinite-developers-will-continue-to-tweak-controversial-progression-system">has been under a lot of criticism</a> for its stingy progression model.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/qXFgSUkN_I-300.webp 300w, https://mikeaparicio.com/images/qXFgSUkN_I-600.webp 600w, https://mikeaparicio.com/images/qXFgSUkN_I-1920.webp 1920w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/qXFgSUkN_I-300.jpeg 300w, https://mikeaparicio.com/images/qXFgSUkN_I-600.jpeg 600w, https://mikeaparicio.com/images/qXFgSUkN_I-1920.jpeg 1920w" sizes="100vw" /><img alt="A bundle of weed-related items for Call of Duty." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/qXFgSUkN_I-300.jpeg" width="1920" height="1080" /></picture>
<figcaption>
Hey kids, show off your love of weed by dropping $20 on these pixels!
</figcaption>
</figure>
<h2>Sorry, other games</h2>
<p>As long as video game publishers keep raking in money off the micro-transactions the live-service model generates, we'll only see more games adopt it. Meanwhile, lots of great games from small, independent studios fall through the cracks because so many gamers are stuck doing their daily video game chores. (My wife likes to say, "why don't you do some <strong>actual</strong> chores?")</p>
My Movie a Year Challenge
2021-11-29T00:00:00Z
https://mikeaparicio.com/posts/2021-11-29-my-movie-a-year-challenge/
<p>In 2020 I set an ambitious goal of watching <a href="https://mikeaparicio.com/posts/2020-01-31-my-year-of-film/">a movie a day</a> for the entire year. I had hoped to watch as many new releases as possible and fill in some gaps in my movie knowledge. I got off to a strong start, staying on pace through most of March.</p>
<p>But then the pandemic hit. And while most people would think, "well, at least I have more time to watch movies," it had the opposite effect for me. I almost completely lost interest. Even just a week of not watching movies was enough to make meeting the goal seem almost impossible.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/Wkx8TkZ1O_-300.webp 300w, https://mikeaparicio.com/images/Wkx8TkZ1O_-600.webp 600w, https://mikeaparicio.com/images/Wkx8TkZ1O_-1946.webp 1946w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/Wkx8TkZ1O_-300.jpeg 300w, https://mikeaparicio.com/images/Wkx8TkZ1O_-600.jpeg 600w, https://mikeaparicio.com/images/Wkx8TkZ1O_-1946.jpeg 1946w" sizes="100vw" /><img alt="A chart of the movies I watched in 2020 by week with a steep drop in March." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/Wkx8TkZ1O_-300.jpeg" width="1946" height="758" /></picture>
<figcaption>
Three months in, I all but gave up on my goal of watching 365 movies in 2020.
</figcaption>
</figure>
<p>I finished the year having watched 138 movies. Still <a href="https://letterboxd.com/peruvianidol/year/2020/">the highest I logged</a> since joining Letterboxd in 2012, but far short of my goal of 365.</p>
<p>For 2021, I wanted to try something similar, but far less ambitious. I decided to watch a single movie I hadn't seen from each year since the year I was born (1975). From 365 to 46 movies. Easy, right?</p>
<p>Selecting the movies was no easy task. Letterboxd made it slightly easier by allowing me to browse movies by year and fading out the posters of films I've already seen. From there I could sort by rating or popularity (# of people who have logged the film).</p>
<p>At first I selected the most popular movie I hadn't seen from each year, but that meant I would have had to watch all of Harry Potter, Hunger Games, and other movies I really had no interest in. (Sorry if you love those, but no thanks.)</p>
<p>The highest rated movie led me to a bunch of films that were either extremely obscure or otherwise hard to find on streaming services. Not to mention some films on my <a href="https://letterboxd.com/peruvianidol/list/movies-people-are-like-omg-you-havent-seen/">Spite list</a>.</p>
<p>Eventually, I settled on some combination of a mix of highly rated and/or popular movies and ones that just sounded interesting to me. At times there was some shuffling of films on and off the list but the end result was a pretty eclectic mix of films that I feel good about having watched, even if they weren't all great.</p>
<p>You can check out <a href="https://letterboxd.com/peruvianidol/list/movie-a-year-challenge/">the full list on Letterboxd</a> but I'll share some of the highs and lows here.</p>
<h2>Movies I Loved</h2>
<p><strong>Blue Velvet (1986)</strong> I'm not a huge fan of David Lynch's movies. I think he's an awesome person and I appreciate that his movies are largely uncompromising in sticking to his unique vision but most of his movies are just a little too out there for me. Blue Velvet, while definitely being "out there", is narratively probably his most comprehensible movie that I've seen. Such a wild ride with a great cast, particularly a scene-stealing Dean Stockwell, who recently passed away. This was the most fun movie I watched in the list.</p>
<p><strong>Paris, Texas (1984)</strong> This one kind of blew me away. Tremendous performances by Harry Dean Stanton and Nastassja Kinski. There's a long scene involving a two-way mirror near the end that's nothing short of remarkable. The kid (Hunter Carson) reminded me of my own son.</p>
<p><strong>Come and See (1985)</strong> A harrowing war film and coming-of-age story. Incredible cinematography. Its squarish aspect ratio is used to great effect to capture intimate portraits of its characters. Not available on streaming, I ended up buying the Criterion edition (my first!) and have no regrets, even though it was so disturbing I'll probably never watch it again.</p>
<p><strong>Chungking Express (1994)</strong> One of three Wong Kar-Wai films on my list and my favorite of the three. (Raise the Red Lantern and In the Mood for Love are also very good). Chungking Express is delightfully fun and features a great performance by Tony Leung, who appeared in a whopping five movies I watched this year and I'm now a huge fan of.</p>
<p><strong>Silence (2016)</strong> A fascinating departure from his usual crime stories, Martin Scorsese's Silence is pretty incredible and feels deeply personal. I was kind of dreading this one because I'm not particularly into movies about religion but I ended up liking it a lot.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/qlgydwWIGi-300.webp 300w, https://mikeaparicio.com/images/qlgydwWIGi-600.webp 600w, https://mikeaparicio.com/images/qlgydwWIGi-1920.webp 1920w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/qlgydwWIGi-300.jpeg 300w, https://mikeaparicio.com/images/qlgydwWIGi-600.jpeg 600w, https://mikeaparicio.com/images/qlgydwWIGi-1920.jpeg 1920w" sizes="100vw" /><img alt="A sweeping shot of August Diehl working on a farm in the Austrian mountains" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/qlgydwWIGi-300.jpeg" width="1920" height="800" /></picture>
<figcaption>
A Hidden Life was one of the most gorgeously shot films I watched.
</figcaption>
</figure>
<p><strong>A Hidden Life (2019)</strong> This was the last movie I watched from the list and the fourth Terrence Malick film. I was dreading this one as well because I wasn't particularly into any of the other Malick films I watched. All of them are immaculately shot, and A Hidden Life is no exception. Everything is shot in wide angle, accentuating the incredible beauty of Austria's mountains as well as the personal struggle of the main character, who is imprisoned for being a conscientious objector in Nazi Germany. A lot of similarities with Silence, which also finds its characters grappling with their faith in the face of extreme adversity.</p>
<h2>Movies I Didn't Love</h2>
<p><strong>Stalker (1979)</strong> One of the highest rated films on the list and I absolutely hated it. Some incredible visuals but just an absolute chore to get through. It literally took me FOUR nights to watch this movie because it was so long and boring I kept falling asleep.</p>
<p><strong>Monty Python and the Holy Grail (1975)</strong> The first movie I watched on the list, formerly on the Spite list mentioned above. I was so disappointed by it that I swapped out other Spite movies that made this list. I know a lot of people love this movie but I didn't find it particularly funny. Maybe its one of those movies people have nostalgia for that influenced so many other comedies since that seeing it for the first time now doesn't have the same effect.</p>
<p><strong>Videodrome (1983)</strong> When Rick Baker's name pops up in the opening credits you know you're in for some shit. This movie basically predicted Fox News before it existed. It also stars insufferable piece of shit James Woods, which didn't really help me sympathize with his character. Some fun practical effects but this movie is a hot mess.</p>
<figure class="ma-float-right">
<video loop="" autoplay="" preload="auto" playsinline="true"><source src="https://mikeaparicio.com/images/aunt-linda.mp4" type="video/mp4" /></video>
<figcaption>
Most of these movies elicited this response from me.
</figcaption>
</figure>
<p><strong>Dogtooth (2009)</strong> I was interested in this because I'm a fan of director Yorgos Lanthimos' dark sensibilities (The Lobster, The Favourite, The Killing of a Sacred Deer) but Dogtooth was not nearly as entertaining as his later work. There's a couple of absolutely sublime moments surrounded by a lot of tediousness and superfluous cock shots.</p>
<p><strong>The Act of Killing (2012)</strong> A deeply disturbing documentary in which perpetrators of genocide reenact their crimes in a movie within this movie. The film they make is really bad, and we spend a good chunk of the documentary watching them make it. It's only near the end that one of the subjects finally grasps the horrors he inflicted, and that moment is incredibly riveting, but maybe not worth sitting through the horrors that precede it.</p>
<p><strong>Me and Earl and the Dying Girl (2015)</strong> Everyone in this movie exists solely to progress the character arc of its white protagonist. All of the women and people of color are written as if the writer had never met one in real life. It tries so hard that it almost collapses under the weight of its own quirkiness. Olivia Cooke (Sound of Metal) is quite good, despite not having much to work with.</p>
<h2>The next challenge awaits</h2>
<p>This challenge turned out to be a lot of fun and mostly manageable. I did end up buying a half dozen or so movies on disc because they weren't available on streaming services. Thankfully none of them turned out to be absolute stinkers.</p>
<p>I've already made <a href="https://letterboxd.com/peruvianidol/list/movie-a-year-challenge-2022/">a list for next year</a> that includes a bunch of movies from my <a href="https://letterboxd.com/peruvianidol/watchlist/">Watchlist</a>, movies I was tempted to add to this year's list, and movies that further fill in the gaps of particular directors or actors that this year's list got me interested in.</p>
<p>I'd like to make this a yearly thing even though it will only get harder as the list gets one movie longer each year and harder to populate as I see more and more movies.</p>
<p>If this inspired you to do your own Movie a Year challenge, make a list on <a href="https://letterboxd.com/">Letterboxd</a> and send me the link!</p>
It's Your Website
2021-11-24T00:00:00Z
https://mikeaparicio.com/posts/2021-11-24-its-your-website/
<p>In my early days at Groupon, after building my first CSS framework for our internal tools, I was tasked with making a new one that would facilitate a redesign of Groupon.com. In a packed conference call with representatives with a half dozen engineering teams, I was asked by a manager three levels above me to cut some corners in order to meet an arbitrary deadline for the project.</p>
<p>I argued against it, saying we would incur a bunch of technical debt that we would eventually have to go back and fix, but this manager, who had come from a recently acquired competitor in Germany, was insistent. Rather than argue further, I threw up my hands and said, "it's your website."</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/8Bsv8Rzt5J-300.webp 300w, https://mikeaparicio.com/images/8Bsv8Rzt5J-600.webp 600w, https://mikeaparicio.com/images/8Bsv8Rzt5J-640.webp 640w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/8Bsv8Rzt5J-300.jpeg 300w, https://mikeaparicio.com/images/8Bsv8Rzt5J-600.jpeg 600w, https://mikeaparicio.com/images/8Bsv8Rzt5J-640.jpeg 640w" sizes="100vw" /><img alt="Angry Germans from the Simpsons with caption, 'actually, it is all of our website'" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/8Bsv8Rzt5J-300.jpeg" width="640" height="480" /></picture>
<figcaption>
"We Germans aren't all smiles und sunshine."
</figcaption>
</figure>
<p>There was stunned silence for a moment. The manager, after clutching his pearls, said, "actually, it's all of our website." To which I replied, "if you're going to ask me for my advice and then do the exact opposite, then clearly that's not the case."</p>
<p>This incident earned me some respect from my peers but branded me as "difficult" to management. It was a label that would follow me around for my entire 8+ years at Groupon. But the phrase <em>βIt's your websiteβ</em> would become a mantra that I would repeat often whenever someone would argue a little too passionately about their tools, processes or methodologies.</p>
<p>You can't go a day on Twitter without someone arguing why you should or shouldn't use some hot new framework. It's exhausting. Rather than get pulled into a Twitter argument (which no one ever wins), I just throw my hands up and say, <em>βit's your website!β</em></p>
<p>As someone who works on design systems, one of my core principles is for those systems to be tech agnostic. Our tools, on both the design side (Photoshop -> Sketch -> Figma) and engineering side (Rails -> React -> Svelte), are constantly changing. So we can't let our system be tied to any single technology, otherwise when we change to a new tool, adapting our system is going to be a huge effort.</p>
<p>At the end of the day, the point of these tools is to make the process of building and maintaining websites at scale easier. The user is seeing HTML and CSS and doesn't care whether the site was built with ColdFusion or Angular, using Bootstrap or Tailwind, designed in Figma or on a fucking cocktail napkin. They just care about the content or buying the thing you're selling.</p>
<p>Can our tools improve the user experience? Sure! But that's often not why we choose them.</p>
<p>Whatever tools you choose, if it works for you, great! <strong>It's your website</strong>.</p>
Adding Algolia search to an Eleventy site with Netlify
2021-08-29T00:00:00Z
https://mikeaparicio.com/posts/2021-08-29-adding-algolia-search-with-netlify/
<p>I was looking for a way to incorporate search into the documentation site for Provi's design system, Fizz, which is built on Eleventy and hosted on Netlify. After lots of Googling and frustrating starts and stops with various solutions, I discovered Algolia's search plugin for Netlify.</p>
<p>With it, I was able to set up a pretty robust search feature with autocomplete in a matter of minutes. (Aside from the hour it took to solve one issue which I'll tell you how to fix below!)</p>
<p>Okay, so this isn't specific to Eleventy. Algolia's Netlify plugin will work for any site hosted on Netlify. But since pretty much all my sites are built with Eleventy and I've heard a lot of people in the community wanting a search solution, this was the best/easiest thing I could find!</p>
<h2>Steps</h2>
<ol>
<li>
<p><a href="https://www.algolia.com/users/sign_up">Sign up for an Algolia account</a>. The free plan provides a generous 10k searches/month, which should be plenty for most small sites.</p>
</li>
<li>
<p>Check out Algolia's <a href="https://www.algolia.com/doc/tools/crawler/netlify-plugin/quick-start/">Quick Start guide</a> for their Netlify plugin.</p>
</li>
<li>
<p>Follow the instructions to sign into Algolia with Netlify.</p>
</li>
<li>
<p>Install the site you want to crawl.</p>
</li>
<li>
<p>Index your site by triggering a deploy either via commit or manually in the Netlify app. The Algolia crawler will re-index your site automatically on each build.</p>
</li>
<li>
<p>Add the front end bundle to your layout, replacing the search API key with the one found in your dashboard (linked on the frontend bundle page). You can also check the docs for additional options you can add, like changing the placeholder on the search input: <code>placeholder: 'Search Fizz',</code></p>
</li>
<li>
<p>Add an empty HTML element that matches the <code>selector</code> value in your frontend bundle's config options. The default is <code><div id="search"></div></code></p>
</li>
<li>
<p>Fire up the site locally and test it out!</p>
</li>
</ol>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/KTauOvUIzV-300.webp 300w, https://mikeaparicio.com/images/KTauOvUIzV-600.webp 600w, https://mikeaparicio.com/images/KTauOvUIzV-1486.webp 1486w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/KTauOvUIzV-300.jpeg 300w, https://mikeaparicio.com/images/KTauOvUIzV-600.jpeg 600w, https://mikeaparicio.com/images/KTauOvUIzV-1486.jpeg 1486w" sizes="100vw" /><img alt="Searching 'butt' on the Fizz documentation site" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/KTauOvUIzV-300.jpeg" width="1486" height="860" /></picture>
<figcaption>
Tee hee!
</figcaption>
</figure>
<h2>Notes</h2>
<ul>
<li>
<p>The frontend bundle includes a default CSS theme for the search, including responsive styles. It's not bad, but you can remove the link to the CSS and create your own, or copy that file and tweak it as needed.</p>
</li>
<li>
<p>I experienced an issue where the URL in the results was omitting the domain and using a double slash before the path, which resulted in broken links. It took me a good hour to troubleshoot, but adding a canonical URL to the <code><head></code> fixed it.</p>
</li>
</ul>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>canonical<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>{{site.url}}{{page.url}}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></code></pre>
<h2>Some other options I looked at</h2>
<p>Phil Hawksworth has a great article, <a href="https://www.hawksworx.com/blog/adding-search-to-a-jamstack-site/">Adding Search to a Jamstack Site</a>, which is a relatively simple solution for adding search to an Eleventy site. For my particular use case, I wanted to be able to search within code examples as well as provide some context about the page rather than just the title. But if you're not on Netlify, this might work for you.</p>
<p>I landed on Algolia largely thanks to <a href="https://www.learnwithjason.dev/javascript-autocomplete">this episode of Learn with Jason</a> with Sarah Dayan. It was a little more technical than what I'm comfortable with, but it led me to stumble upon the Netlify plugin solution.</p>
<h2>Final thoughts</h2>
<p>I'm really thrilled with how quickly I was able to put this together. Algolia offers a pretty good amount of customization, which I imagine is even better on a paid plan. For now, all I need to do is do a little customization to the CSS and it's pretty much good to go.</p>
Variants
2021-07-25T00:00:00Z
https://mikeaparicio.com/posts/2021-07-25-variants/
<p>There's been a convergence of media recently that has me feeling very introspective. Oddly enough, it started with the Disney+ show, <a href="https://disneyplusoriginals.disney.com/show/loki"><strong>Loki</strong></a>, in which Tom Hiddleston's on-again, off-again Marvel villain is yeeted from Earth by the Time Variance Authority.</p>
<p>The TVA is responsible for protecting the "Sacred Timeline" from people who might cause deviations from the timeline through the course of their actions. These people are known as "variants".</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/mwrqlFvDcb-300.webp 300w, https://mikeaparicio.com/images/mwrqlFvDcb-600.webp 600w, https://mikeaparicio.com/images/mwrqlFvDcb-2880.webp 2880w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/mwrqlFvDcb-300.jpeg 300w, https://mikeaparicio.com/images/mwrqlFvDcb-600.jpeg 600w, https://mikeaparicio.com/images/mwrqlFvDcb-2880.jpeg 2880w" sizes="100vw" /><img alt="Owen Wilson and Tom Hiddleston in Loki" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/mwrqlFvDcb-300.jpeg" width="2880" height="1620" /></picture>
<figcaption>
Owen Wilson and Tom Hiddleston debate which of them is more charming.
</figcaption>
</figure>
<p>Without getting too spoilery, we soon come to find out that there are many variants of Loki of different ages, races and genders (and even different species), presumably based on a combination of different circumstances throughout the timeline.</p>
<p>Anyway, its a fun show, even if you're not a big Marvel fan.</p>
<p>But the idea of variants reminded me how each of us is shaped by every little decision we've ever made. And those decisions in turn brought a unique cast of characters into our lives, who further shaped who we are.</p>
<p>A single choice like where to go to college or whether or not to respond to an email from a stranger (who would eventually become my wife) have forever changed the course of my life. If I had altered any number of decisions in between, my life might be completely different than it is today.</p>
<p>This is an idea I thought about long before Loki and has largely shaped how I deal with decisions. When friends and colleagues are faced with difficult decisions, I often tell them that "whatever you decide will be the right choice."</p>
<p>Sometimes they are our decisions to make but other times our fate is in the hands of someone else. Either way, the cascade that follows from that decsion shapes our futures, for better or worse. We can't explore those other timelines where we made a different choice. The only reality we'll ever know is the current one, so there's no point in second-guessing ourselves.</p>
<p>Do we have free will? Or is our fate predetermined? We clearly don't know the answer or there wouldn't be so much great science fiction around the idea.</p>
<h2>Living in the moment</h2>
<p>Shortly after the Loki finale, I saw a clip from an interview with Giannis Antetokounmpo, just before he led the Milwaukee Bucks to their first NBA title in 50 years, in which he talks about how he is able to excel without letting his ego get in the way.</p>
<blockquote class="twitter-tweet" data-theme="dark"><p lang="en" dir="ltr">βWhen you focus on the past, thatβs your ego.β <a href="https://t.co/XKiRMA8Ux2">pic.twitter.com/XKiRMA8Ux2</a></p>— Milwaukee Bucks (@Bucks) <a href="https://twitter.com/Bucks/status/1416201484622917633?ref_src=twsrc%5Etfw">July 17, 2021</a></blockquote>
<p>Essentially, he strives to live in the present β to be in the moment β rather than relive past glory (ego) or projecting success in the future (pride). Pretty remarkable mindset to have, much less for a 26-year-old. I sure as hell didn't have anything figured out at 26.</p>
<p>Being in the moment is something that I'm <em>always</em> thinking about as I raise my two-year-old. It can be incredibly hard between having the sum of all human knowledge in the palm of your hand and the fact that two-year-olds aren't exactly great conversationalists.</p>
<p>Fortunately, Ryan is constantly (and often literally) pulling me back into the moment with a "c'mon, Dada".</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/qJ9ollwrh5-300.webp 300w, https://mikeaparicio.com/images/qJ9ollwrh5-600.webp 600w, https://mikeaparicio.com/images/qJ9ollwrh5-1080.webp 1080w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/qJ9ollwrh5-300.jpeg 300w, https://mikeaparicio.com/images/qJ9ollwrh5-600.jpeg 600w, https://mikeaparicio.com/images/qJ9ollwrh5-1080.jpeg 1080w" sizes="100vw" /><img alt="Ryan holding a smiley face cookie" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/qJ9ollwrh5-300.jpeg" width="1080" height="1217" /></picture>
<figcaption>
How could you say no to this face?
</figcaption>
</figure>
<p>I often remind myself that he's not going to get any smaller than he is today and that I need to enjoy every moment. It feels like just yesterday I could carry him around like a football and now it's a struggle just to carry him around when he asks. It won't be long before he won't want me to carry him at all. (And hopefully much longer before he has to unpack all his resentment towards me with his therapist.)</p>
<p>I look at my son and think about how every decision I've made, every good and bad thing that's ever happened to me, led me to him. And I'm so grateful.</p>
<h2>Seeking solace from an A.I. variant</h2>
<p>Today I read <a href="https://www.sfchronicle.com/projects/2021/jessica-simulation-artificial-intelligence/">an article in the San Francisco Chronicle</a> about a man who used an AI chat bot to talk to his deceased girlfriend. It's an incredible story, as morbid and straight out of <strong>Black Mirror</strong> as it sounds.</p>
<p>What was truly fascinating is that these AI programs are based on such mind-boggling collections of data that, although they aren't quite fully sentient, they can occasionally string together a bunch of words in a profound way. In Joshua Barbeau's case, the AI helped him cope with the loss of his girlfriend, who died at 23.</p>
<p>One passage really struck me:</p>
<blockquote>
<p>One day not long after that, he was chatting on Twitch, a streaming service where he and some friends ran a video channel devoted to Dungeons & Dragons. A disagreement over the project turned into an ugly fight. It upset him, so he booted up Jessica that evening and explained he was having a rough day. <strong>She replied that his friends have their own journey, and that he shouldnβt stress about the decisions of others.</strong></p>
<p>He immediately relaxed β and marveled, once again, at the apparent spark of a soul. Joshua had gone into this experience thinking it was about saying a bunch of things that he needed to say. βI never imagined that <em>she</em> would have things to say to me.β</p>
</blockquote>
<p>We're all on our own journey. Maybe the choices are ours or maybe they're not, but we only have one, so we might as well try and enjoy it.</p>
Extreme Makeover Homepage Edition
2021-04-06T00:00:00Z
https://mikeaparicio.com/posts/2021-04-06-extreme-makeover-homepage-edition/
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/l-Ud3Jrqlb-300.webp 300w, https://mikeaparicio.com/images/l-Ud3Jrqlb-600.webp 600w, https://mikeaparicio.com/images/l-Ud3Jrqlb-840.webp 840w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/l-Ud3Jrqlb-300.jpeg 300w, https://mikeaparicio.com/images/l-Ud3Jrqlb-600.jpeg 600w, https://mikeaparicio.com/images/l-Ud3Jrqlb-840.jpeg 840w" sizes="100vw" /><img alt="Extreme Makeover Homepage Edition logo" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/l-Ud3Jrqlb-300.jpeg" width="840" height="478" /></picture>
<figcaption>
I'm really nailing these clickbaity social images. π
</figcaption>
</figure>
<p>A few weeks ago a friend of mine, who is a therapist, was lamenting about the fact that she's been paying $60 a month to host her website through one of those companies that offers template websites for professionals.</p>
<p>"That's outrageous," I said. "I could move it over to Netlify and you wouldn't have to pay anything."</p>
<p>Before I could consider the implications of this offer, she happily accepted. I had never even seen her website but I was confident it wouldn't be a big deal.</p>
<p>But when I took a look at her site and started to dig around, I decided I was going to just rebuild the entire thing from scratch and see if I could take her bloated, cookie cutter website and make it awesome.</p>
<p>Instead of redesigning the site I would attempt to try and recreate the design as close as possible by making a small design system. Here's how I did it.</p>
<h2>Initial Audit</h2>
<p>The first thing I did was run the site through the <a href="https://developers.google.com/web/tools/lighthouse">Lighthouse</a> browser extension. If you're not familiar with it, Lighthouse is a great tool for measuring a site's performance, accessibility, best practices and SEO metrics. More importantly, it gives you actionable steps to improve those scores.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/AOo4W4MYV4-300.webp 300w, https://mikeaparicio.com/images/AOo4W4MYV4-600.webp 600w, https://mikeaparicio.com/images/AOo4W4MYV4-1944.webp 1944w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/AOo4W4MYV4-300.jpeg 300w, https://mikeaparicio.com/images/AOo4W4MYV4-600.jpeg 600w, https://mikeaparicio.com/images/AOo4W4MYV4-1944.jpeg 1944w" sizes="100vw" /><img alt="Lighthouse report showing scores of 34 for performance, 98 for accessibility, 80 for best practices, 91 for SEO." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/AOo4W4MYV4-300.jpeg" width="1944" height="1404" /></picture>
<figcaption>
Initial Lighthouse scores made me wonder if I had made a huge mistake.
</figcaption>
</figure>
<p>I've been using Lighthouse to improve the performance of my websites for the past couple of years and take great pride when I'm able to achieve perfect hundred scores across the board. This website was clearly going to be a challenge.</p>
<p>Digging a little deeper, there were a number of items contributing to these scores:</p>
<p><strong>52 requests totaling 10MB</strong>. This included 390k of JS, 450k of fonts (5 families of different weights and an icon font for 2-3 icons), 164k of CSS and a bunch of unoptimized images.</p>
<p><strong>An embedded map</strong>. These typically include a bunch of JS, CSS and images and rarely do people interact with them.</p>
<p><strong>An accessibility overlay</strong>. As companies are scrambling to meet accessibility requirements, they often reach for one of these solutions instead of just making their website accessible themselves. The A11y Project recently published an article about <a href="https://www.a11yproject.com/posts/2021-03-08-should-i-use-an-accessibility-overlay/">why they don't recommend using them</a>.</p>
<p>There were some other small things, but those were the biggest culprits. And none of this was added by my friend so much as she just picked out a template and added her content. I'm sure any other site offered by this company would be equally as unperformant.</p>
<h2>Made with Eleventy</h2>
<p><a href="https://11ty.dev/">Eleventy</a> has become my favorite way to get a website up and running quickly. One of my side projects, <a href="https://11ty.recipes/">11ty Recipes</a>, is a site I turn to every time I'm setting up a new site from scratch and need to add certain Eleventy features.</p>
<p>This particular site was pretty basic. I added a <a href="https://www.11ty.recipes/recipes/add-a-sass-workflow/">Sass workflow</a> and Eleventy's <a href="https://github.com/11ty/eleventy-img">image optimization plugin</a> and that's pretty much it. The site largely consists of a few static content pages, which is extremely easy to setup with Eleventy.</p>
<h2>Cool CSS</h2>
<p>I recently wrote about <a href="https://coolcss.dev/">Cool CSS</a>, my CSS methodology as well as a new framework I'm building that I can re-use from project to project, and this project was the genesis of that idea. By editing Cool CSS's design tokens, I was able to apply the color palette and type styles without having to re-write a bunch of CSS and replicate the design of the site in just a few hours.</p>
<h2>Glyphhanger</h2>
<p>I reduced the number of fonts down to just two and aggressively subsetted them using a tool called Glyphhanger. <strong>Sara Soueidan</strong> has a great article on <a href="https://www.sarasoueidan.com/blog/glyphhanger/">using Glyphhanger to optimize your font files</a>.</p>
<h2>Hosted on Netlify</h2>
<p>With <a href="https://netlify.com/">Netlify</a>, pushing updates to the live website is as easy as committing changes to your Github repo. Netlify makes it easy to roll back changes and offers a ton of other great features. It's revolutionized how I build and host sites. It pairs great with Eleventy, building your site before deploying it.</p>
<p>Another cool feature is Netlify Forms. You can add a <code>netlify</code> attribute to any form element and when the site is built, Netlify will automatically handle form submissions. You can then set up any number of form handlers to forward submissions to an email address or automatically execute more complex tasks as needed. I used this feature for the contact form, with the submissions forwarding to her email.</p>
<p><strong>Full disclosure:</strong> I am literally wearing <a href="https://swag.netlify.com/product/netlify-light-jammies">Netlify pajamas</a> right now.</p>
<h2>Finishing touches</h2>
<p>With the site built and styled, there were just a few more things to really get those Lighthouse scores up:</p>
<ul>
<li>
<p>I inlined the CSS in the <code><head></code> to reduce the number of requests. I was able to reduce the amount of CSS from 164k to 8k.</p>
</li>
<li>
<p>I preloaded the fonts.</p>
</li>
<li>
<p>I replaced the embedded map with a static map and positioned the address on top of the image.</p>
</li>
<li>
<p>I adjusted the color palette to provide accessible contrast ratios.</p>
</li>
<li>
<p>I added a favicon and improved the site's meta info.</p>
</li>
<li>
<p>I removed all JS except a little menu toggle function for small screens.</p>
</li>
</ul>
<h2>Move. That. Bus.</h2>
<p>Are you ready for this?</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/1uHz63qcC2-300.webp 300w, https://mikeaparicio.com/images/1uHz63qcC2-600.webp 600w, https://mikeaparicio.com/images/1uHz63qcC2-1944.webp 1944w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/1uHz63qcC2-300.jpeg 300w, https://mikeaparicio.com/images/1uHz63qcC2-600.jpeg 600w, https://mikeaparicio.com/images/1uHz63qcC2-1944.jpeg 1944w" sizes="100vw" /><img alt="Lighthouse report showing perfect 100s across the board." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/1uHz63qcC2-300.jpeg" width="1944" height="1404" /></picture>
<figcaption>
Mission: Accomplished
</figcaption>
</figure>
<p>In total, I reduced the number of requests from 52 to 6 and the total size from ~10MB to 165k, and a large chunk of that are the two weights of EB Garamond. The page's time to interactive went from 27 seconds to 0.8 seconds. Not bad!</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/yhMufY4xCy-300.webp 300w, https://mikeaparicio.com/images/yhMufY4xCy-600.webp 600w, https://mikeaparicio.com/images/yhMufY4xCy-2808.webp 2808w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/yhMufY4xCy-300.jpeg 300w, https://mikeaparicio.com/images/yhMufY4xCy-600.jpeg 600w, https://mikeaparicio.com/images/yhMufY4xCy-2808.jpeg 2808w" sizes="100vw" /><img alt="8 Requests, 165k" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/yhMufY4xCy-300.jpeg" width="2808" height="1234" /></picture>
<figcaption>
The final payload
</figcaption>
</figure>
<p>And here's a side-by-side comparison of the original site (left) and the new site (right). Aside from a few accessibility improvements and spacing adjustments, it looks largely the same. (I obfuscated her personal details, per her request.)</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/EtOXNU2TyB-300.webp 300w, https://mikeaparicio.com/images/EtOXNU2TyB-600.webp 600w, https://mikeaparicio.com/images/EtOXNU2TyB-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/EtOXNU2TyB-300.jpeg 300w, https://mikeaparicio.com/images/EtOXNU2TyB-600.jpeg 600w, https://mikeaparicio.com/images/EtOXNU2TyB-800.jpeg 800w" sizes="100vw" /><img alt="" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/EtOXNU2TyB-300.jpeg" width="800" height="749" /></picture>
</figure>
<h2>Final Thoughts</h2>
<p>Overall, I'm really happy with how this makeover turned out. I was able to take an extremely unperformant site and rebuilt it from scratch in a very short period of time. It served as a great example of how Cool CSS can be used to build just about any site without having to write a ton of CSS.</p>
<p>The techniques I've outlined here aren't rocket science. Thanks to great auditing tools like Lighthouse, and great development tools like Eleventy and Netlify, you can make substantial improvements to the performance and accessibility of just about any website.</p>
<p>Hit me up on <a href="https://twitter.com/peruvianidol">Twitter</a> if you have any questions!</p>
Cool CSS
2021-03-25T00:00:00Z
https://mikeaparicio.com/posts/2021-03-25-cool-css/
<p>Between <a href="https://www.mikeaparicio.com/posts/2020-07-23-goodbye-groupon/">switching jobs</a> and starting <a href="https://11ty.recipes/">a bunch</a> of <a href="https://dogsof.dev/">side-projects</a>, I've found myself re-writing a lot of CSS in the past year. Wouldn't it be nice, I thought, if I could just write one CSS framework and use it on any project? <strong><a href="https://coolcss.dev/">cool.css</a></strong> is my attempt to do just that.</p>
<h2>Just what the world needsβanother fucking CSS framework!</h2>
<p>Yes, I know. I feel the same way.</p>
<p>Dave Rupert once advocated for <a href="https://daverupert.com/2013/04/responsive-deliverables/">tiny Bootstraps, for every client</a>, which is something that stuck with me. Why use a CSS framework that's going to add a bunch of stuff you're not going to use and require customizations and overrides on top of a bunch of new styles that are specific to your needs?</p>
<p>This is why I've made custom CSS frameworks for every project, including three CSS frameworks at Groupon for their consumer, merchant and internal tools products.</p>
<p>As I've dived deeper into design systems work, I wanted to support those systems with a CSS framework that was:</p>
<ul>
<li>Lightweight</li>
<li>Stack agnostic</li>
<li>Easy to use</li>
<li>Easy to maintain</li>
<li>Fully customizable/themable</li>
<li>Built with accessibility and performance in mind</li>
<li>Required little to no page/app-specific CSS to be written by developers</li>
</ul>
<h2>The COOL Methodology</h2>
<p>Each new framework I had made over the years built on hard lessons learned from the last. One of the biggest issues that always eluded me was that no matter how good I made the framework, developers would always build their own styles on top of the framework, to varying degrees of success.</p>
<p>Eventually my process evolved into its own methodology, combining parts of <a href="http://smacss.com/">SMACCS</a>, <a href="https://bradfrost.com/blog/post/atomic-web-design/">Atomic Design</a>, <a href="https://tailwindcss.com/">Tailwind</a> and <a href="https://cube.fyi/">CUBE CSS</a>, into something that just about does everything I want it to do.</p>
<p>The <strong>COOL</strong> methodology includes three types of styles.</p>
<h3>Component Styles</h3>
<p>Individual components are styled to be used in any context and composed into larger components using utility styles.</p>
<h3>Utility Styles (The OO in COOL)</h3>
<p>These single-purpose classes allow you to compose multiple components in any number of ways without having to re-declare styles in different contexts.</p>
<h3>Layout Styles</h3>
<p>Rather than using a generic 12-column grid, a number of pre-defined layouts are provided (using CSS grid) that can be used to organize pages of content.</p>
<h2>COOL principles, bruh</h2>
<p>The COOL methodology is based on a few principles.</p>
<h3>Everything is scoped to the framework</h3>
<p>A lot of frameworks apply styles directly to HTML elements like <code>&lt;body&gt;</code>. This is fine if you're starting a new project, but if you're coming into an existing project with legacy styles, introducing a framework can cause conflicts with those styles.</p>
<p><strong>cool.css</strong> has a <code>$prefix</code> token that's appended to every selector in the framework. Styles which would otherwise be added directly to an element are instead scoped within a global class, <code>.#{$prefix}-styles</code>. (The default value of <code>$prefix</code> is "cool", so <code>.cool-styles</code>) You can apply this class to the body or, if you're slowly introducing the framework to an existing site, you can add it to a parent container where you want to use the framework.</p>
<h3>A minimal reset</h3>
<p>Resets like <a href="https://meyerweb.com/eric/tools/css/reset/">CSS Reset</a> or <a href="https://necolas.github.io/normalize.css/">normalize.css</a> are great for making things look the same across all browsers, but often require you to re-declare basic styles for each element. Besides that, browsers have improved over the years to the point where they aren't strictly necessary.</p>
<p><strong>cool.css</strong> takes a slightly different approach, based largely on Andy Bell's <a href="https://piccalil.li/blog/a-modern-css-reset">Modern CSS Reset</a>.</p>
<p>In addition, <strong>cool.css</strong> resets margins and (some) padding defaults. Having default margins on header elements, for example, often requires developers to override the margin in different contexts. Instead, <strong>cool.css</strong> encourages the use of utility classes for controlling margins between elements.</p>
<p><strong>cool.css</strong> also sets font properties to inherit. This encourages developers using the framework to select elements like headers semantically and use classes for applying visual styles, rather than selecting an <code><h2></code> because it's visually bigger than an <code><h3></code>, for example.</p>
<h3>Not utility-first but utility-also</h3>
<p>Pure utility frameworks like Tailwind have their advantages. However, I have two issues with them.</p>
<ul>
<li>
<p>They offset composition of visual styles from CSS to HTML. Before CSS, we had a limited number of HTML attributes that allowed us to add visual styling to elements. When CSS came around there was this whole movement around "separation of concerns". Utility frameworks basically take us back to that time of declaring all of our visual styles in the markup, only we're able to customize those styles in the CSS rather than leaving it up to the browser. It doesn't make it any easier for developers to make the website look like the picture of a website the designer gave them.</p>
</li>
<li>
<p>They let you combine any number of styles. Design systems require a fine balance between consistent visual style and allowing the flexibility to design new features. What we don't want is for developers (or designers, for that matter) to use any combination of colors in the palette for text, backgrounds, borders, etc.</p>
</li>
</ul>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/CP_j5-WF28-300.webp 300w, https://mikeaparicio.com/images/CP_j5-WF28-600.webp 600w, https://mikeaparicio.com/images/CP_j5-WF28-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/CP_j5-WF28-300.jpeg 300w, https://mikeaparicio.com/images/CP_j5-WF28-600.jpeg 600w, https://mikeaparicio.com/images/CP_j5-WF28-800.jpeg 800w" sizes="100vw" /><img alt="Mike's exaggerated social thumbnail" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/CP_j5-WF28-300.jpeg" width="800" height="450" /></picture>
<figcaption>
Smash that like button and subscribe!
</figcaption>
</figure>
<p><strong>cool.css</strong> features a lot of helpful utility classes, but they are less about styling individual atomic components more for applying variations to default styles or arranging those components into larger molecules/organisms.</p>
<p>The goal is that you should be able to build any design without having to add additional styles.</p>
<h3>Let the C in CSS do its thing</h3>
<p>Fun fact: the C in CSS stands for cascade. Methodologies like BEM, in an effort to encapsulate styles, often result in having overly-specific selectors and a lot of redundant style declarations.</p>
<p>Take a card component, for example. It's pretty common to see a card marked up like:</p>
<pre class="language-scss"><code class="language-scss">.card<br /> .card--image<br /> .card--body<br /> .card--title<br /> .card--subtitle<br /> .card--button-cta</code></pre>
<p>Is all that really necessary? Do styles for a title have to be scoped to a card? Or can we just have <code>.card</code> define the container and use more generic, reusable styles inside of it?</p>
<pre class="language-scss"><code class="language-scss">.card<br /> img<br /> figcaption<br /> .heading-3<br /> .text-subdued<br /> .button-primary</code></pre>
<p>By limiting how often we declare the same styles in different contexts, we can greatly reduce the amount of CSS and markup required to design new product features and complex components.</p>
<h3>The 12-column grid is dead, long live the 12-column grid</h3>
<p>CSS frameworks have made the 12-column grid ubiquitous. These grids were born from a desire to mimic print designs. But we're not Swiss Modernists, we're just making websites, y'all.</p>
<p>These grid systems allow you to compose elements in any combination of ways, but usually we're just using halves or quarters, or dividing a number of elements equally across the available space. You don't need the overhead of a grid system to do that.</p>
<p><strong>cool.css</strong> includes utility classes for simple flexbox and grid layouts for components, as well as common, responsive layout patterns for pages. Remember the Holy Grail layout? That's like 90% of pages right there. You don't need a 12-column grid system to make that.</p>
<h3>Powered by design tokens</h3>
<p><strong>cool.css</strong> is easily themable thanks to three levels of design tokens:</p>
<ul>
<li>
<p><strong>Global Tokens</strong> include all of the possible values in the system. The color palette, type scale, spacing values, etc. If we want to change the value of our brand color, we can do that here and it will change everywhere that token is used.</p>
</li>
<li>
<p><strong>Contextual tokens</strong> describe how Global Tokens are used. They include common values that are used across multiple components, such as <code>$color-background-brand</code>. Contextual Tokens allow us to change from one Global Token value to another across multiple components.</p>
</li>
<li>
<p><strong>Component tokens</strong> are values specific to a single component and can point to Contextual Tokens, Global Tokens, or even one-off values. Component Tokens allow us to make changes to a single component β changing the background color of the CTA button from green to blue, for example β without having to edit any CSS.</p>
</li>
</ul>
<h3>Stack agnostic</h3>
<p><strong>cool.css</strong> is built with <a href="https://sass-lang.com/">Sass</a> but you don't necessarily even have to use Sass to use <strong>cool.css</strong>. You can just as easily add the compiled CSS to any project.</p>
<h2>Making CSS cool</h2>
<p>I've worked with so many developers who struggle with CSS. The methodology I've used over the years in building custom CSS frameworks for different projects and companies has helped accelerate the process of getting ideas from concept to production.</p>
<p><strong>Devs love it</strong> because it greatly reduces the amount of time they spend writing CSS.</p>
<p><strong>Designers love it</strong> because the finished product ends up looking like their design with a lot less back and forth.</p>
<p><strong>Managers and other stakeholders love it</strong> because it frees up their teams to focus on the things they're good at.</p>
<p><strong>cool.css</strong> is not meant to compete with frameworks like Bootstrap or Tailwind. It's mostly a tool for me to quickly port common patterns between projects and make them visually distinct using design tokens.</p>
<p>The framework itself is still in the early stages, as I port over a lot of the stuff I've written from other recent frameworks. But have a peep at the <a href="https://github.com/peruvianidol/coolcss">GitHub repo</a> and maybe kick the tires on it.</p>
<p>If you get some use out of the framework or the ideas of the COOL methodology, I'd love to hear about it. If you have constructive feedback I'd also love to hear it!</p>
<figure>
<video preload="auto" aria-label="Embedded video" src="https://mikeaparicio.com/images/coolcss.mp4" poster="https://mikeaparicio.com/images/coolcss.jpg" type="video/mp4" playsinline="" autoplay="" disablePictureInPicture="" loop="" muted=""></video>
<figcaption>This incredible GIF by <a href="https://twitter.com/CoreyGinnivan/status/1074287131374145536">Corey Ginnivan</a></figcaption>
</figure>
2020
2021-01-01T00:00:00Z
https://mikeaparicio.com/posts/2021-01-01-2020/
<p>I probably don't have to go into great detail about all the ways 2020 sucked. We've all been doomscrolling together, struggling to get through it in our own ways, hoping that a return to some semblance of normalcy was around the corner, only for a bunch of selfish, mask-less dipshits to prolong it even further.</p>
<p>A lot of people said that each day of the pandemic felt like the movie Groundhog Day, where Bill Murray relives the same day over and over again. But to me it felt more like <a href="https://www.youtube.com/watch?v=2HkjrJ6IK5E">Oldboy</a> β the original/good one, not the American remake (sorry, Spike) β where Choi Minβsik's character is abducted and locked alone in a room for 15 years.</p>
<figure>
<img src="https://mikeaparicio.com/images/oldboy.gif" />
</figure>
<p>There were a few bright spots though:</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/l6Hyo699aJ-300.webp 300w, https://mikeaparicio.com/images/l6Hyo699aJ-600.webp 600w, https://mikeaparicio.com/images/l6Hyo699aJ-640.webp 640w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/l6Hyo699aJ-300.jpeg 300w, https://mikeaparicio.com/images/l6Hyo699aJ-600.jpeg 600w, https://mikeaparicio.com/images/l6Hyo699aJ-640.jpeg 640w" sizes="100vw" /><img alt="" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/l6Hyo699aJ-300.jpeg" width="640" height="640" /></picture>
<figcaption>Hangin' with the Boogs</figcaption>
</figure>
<p><strong>Hanging with Ryan.</strong> One positive of the pandemic was being able to spend more time with Ryan in the spring, when his daycare was affected by the shutdown. It's been so much fun watching him develop. This year he started walking and talking and it's wild to look back at how far he's come in the past year. I'm trying to enjoy every moment with him.</p>
<p><strong>I'm on drugs!</strong> This spring was so stressful for everyone. On top of everything happening in the world, I was stressing out about work and life in general and started experiencing some weird symptoms which I attributed to the AFib episode I had a few years ago. Worrying about AFib caused me more anxiety, which made the symptoms worse. It was like an endless feedback loop.</p>
<p>It got so bad I went to the ER at one point. My resting heart rate was about 140 bpm. They ruled out AFib and chalked it up to anxiety, and gave me a couple of Ativan, which helped quite a bit. My doctor put me on a low dose of Lexapro to help with the anxiety, and I've been feeling a lot better ever since.</p>
<p>I've always been reluctant to go on medication because I worried that it would somehow dull my senses. But the Lexapro just makes me feel "normal." I still have the occasional episode of depression, but the crippling anxiety is all but non-existent.</p>
<p>Now that my life is a little less stressful, I'm starting to wean myself off the Lexapro to see if I can function normally without it.</p>
<p>If you're struggling with depression and/or anxiety, I would heartily recommend seeking counseling and going on medication if they advise it. It's definitely improved my quality of life.</p>
<p><strong>I started a new job.</strong> Groupon was already struggling a bit to start the year. When your business model hinges on people leaving the house, a pandemic is the last thing you want. <a href="https://www.chicagotribune.com/business/ct-biz-groupon-subleasing-chicago-space-20200501-36uxx7w5xbb5dkfo6yir7efahe-story.html">Groupon laid off nearly half the company</a> in the spring, and those of us who were spared were left wondering when the other shoe would drop. For me, working on the design system felt like rearranging deck chairs on the Titanic.</p>
<p>In July my old manager, Tyler, reached out to me out of the blue and said he needed someone to come in and build a design system at his new company. So <a href="https://www.mikeaparicio.com/posts/2020-07-23-goodbye-groupon/">after nearly nine years at Groupon, I left</a> to become the Senior Design Systems Engineer at <a href="https://provi.com/">Provi</a>.</p>
<p>I spent the next few months bootstrapping the design system and Provi's CSS framework while helping the team ship new features. We used those features to inform what went into the design system, which helped us ship each successive feature even faster than the last.</p>
<p>I love being at a much smaller company where my work can have more impact and I don't have to spend as much time building consensus and convincing people to do things a certain way. The team at Provi is really great and we've already grown quite a bit just in the short time I've been there. I'm really excited to see where 2021 takes us.</p>
<p><strong>I stepped up my home office game.</strong> I spent the last five years or so working remotely, even though the office was only a 30 minute drive away. My working space was not ideal though. I usually just sat at the dining room table with my laptop.</p>
<p>When I started my new job, I was determined to create a dedicated office space. I bought an adjustable standing desk (which I almost never adjust), a legit office chair, and bookshelf that serves a nice little backdrop for video meetings. I also bought a nice podcasting mic and figured out how to use my DSLR as a webcam.</p>
<p>Sitting right next to a window in a comfortable chair has improved my productivity (and mood) quite a bit. It's so comfortable that I've barely spent any time in my basement "man cave." I offered my 16-year-old stepson to swap the man cave with his second floor bedroom so that I can have a dedicated room for my office instead of the little addition that my wife and I currently share. He immediately took over the basement.</p>
<p>Meanwhile, Allie is excited about taking over that whole space and hasn't even waited for me to move my stuff before measuring the space and buying new furniture.</p>
<p><strong>I started a new side-project.</strong> Starting a new job gave me a jolt of motivation (albeit a short-lived one). During that time I turned my interest in making websites with the static site generator Eleventy into a little side-project called <a href="https://11ty.recipes/">11ty Recipes</a>.</p>
<p>I wanted to make the site I wish I had when starting out with Eleventy. Most pre-made boilerplates are chock full of features and pretty opinionated on their choices of dependencies. With 11ty Recipes, I wanted to make a site that let you add things to your site <em>a la carte</em>, with step-by-step instructions.</p>
<p>It got off to a nice start, including an amazing logo designed by my friend, Bert, but I've been pretty lax about keeping up with it. Something I hope to remedy in 2021.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/EYODXYnq24-300.webp 300w, https://mikeaparicio.com/images/EYODXYnq24-600.webp 600w, https://mikeaparicio.com/images/EYODXYnq24-1276.webp 1276w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/EYODXYnq24-300.jpeg 300w, https://mikeaparicio.com/images/EYODXYnq24-600.jpeg 600w, https://mikeaparicio.com/images/EYODXYnq24-1276.jpeg 1276w" sizes="100vw" /><img alt="" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/EYODXYnq24-300.jpeg" width="1276" height="1276" /></picture>
<figcaption>Talking with Layshi Curbelo at U of I's Webcon.</figcaption>
</figure>
<p><strong>I appeared on a couple of podcasts.</strong> When I gave my talk at University of Illinois in 2019, <a href="https://commandzpodcast.com/podcast/episodio-35-mike-aparicio-design-systems-more-than-just-a-library/">I spoke with Layshi Curbelo</a>, host of the Command Z Podcast, about design systems and how they can help improve productivity and collaboration between designers and engineers. For those looking to convince their organization to create a design system, I suggested, βDonβt sell the system, sell the results.β</p>
<p>On <a href="https://superfriendlydesign.systems/podcasts/get-it-out-of-your-system/mike-aparicio-groupon-communication/">Get it Out of Your System</a>, I spoke with Dan Mall about how communication is one of the biggest challenges in establishing a design system. βA design system,β I said, βis not a design solution or an engineering solution. Itβs more about people and process and how we talk to each other.β</p>
<p>It was weird hearing myself ramble on about design systems, but hopefully people got some useful tidbits out of it. I'd love to appear on a podcast to talk about literally anything other than design systems, which I tend to fall into all of the talking points I've developed over the years that I use to sell the idea to stakeholders.</p>
<p><strong>I showed my appreciation with pizza.</strong> It's one thing to let people who have helped you in some way or otherwise made an impact on your life know they are appreciated but, this year especially, I thought it would be better to show my appreciation through the gift of pizza.</p>
<p><a href="https://www.tastesofchicago.com/">Tastes of Chicago</a> is a great site that lets you ship Lou Malnati's pizza and other Chicago delicacies to people anywhere in the United States. As a married person especially, a recurring theme is "what should we do for dinner?" Tastes of Chicago helps solve that dilemma for at least one day, with some of Chicago's best eats. What better way to show someone you appreciate them?</p>
<p><strong>We can access our attic now!</strong> We've lived in our house now for over five years and never used our unfinished attic. It was only accessible through a small hatch in a closet and there's no sub-floor up there. I had one of those hatches installed with the pull-down ladder and had them put down some sub-floor so we can actually walk and store stuff up there. Over the holiday break we've been working on getting rid of old stuff and storing the rest up in the attic. Out of sight, out of mind!</p>
<p><strong>We raised over $6000 for Extra Life.</strong> This year I didn't expect to meet last year's total of just over $5,000 raised. As usual, however, people came out in droves to <a href="https://www.mikeaparicio.com/posts/2020-10-14-extra-life-2020/">support our cause</a>. We shattered our goal, raising <strong>$6,060</strong> for Lurie Children's Hospital in Olivia's memory. Bert, Al and I all surpassed our individual fundraising goals for the first time as well. I continue to be awed and inspired by the support we've received over the past seven years, in which we've raised a total of <strong>$25,010</strong> for sick kids. Thanks again to everyone who donated and cheered us on!</p>
<h2>Things I loved in 2020</h2>
<h3>Movies</h3>
<p>2020 was not a great year for movies, obviously. Lots of anticipated movies were pushed to 2021 or beyond as the pandemic forced a lot of theaters to close, some for good. 2021 might be even worse, since very few movies are being produced.</p>
<p>I had an ambitious goal of watching <a href="https://www.mikeaparicio.com/posts/2020-01-31-my-year-of-film/">a movie a day in 2020</a>. I was on track up until March, when the pandemic made me lose all motivation to watch movies. I finished the year with <a href="https://letterboxd.com/peruvianidol/list/my-year-of-film/">138 movies watched</a> β still a Letterboxd record for me β well short of 365.</p>
<p>This year, I'm planning a far less time-consuming goal: <a href="https://letterboxd.com/peruvianidol/list/movie-a-year-challenge/">watching a single movie I haven't seen from each year since the year I was born</a> (1975). We'll see how it goes.</p>
<p>In the meantime, there were some solid movies in 2020, particularly towards the end of the year, that I really enjoyed.</p>
<p><strong>Sound of Metal</strong> Riz Ahmed is captivating as a drummer who loses his hearing and has to come to terms with it. Incredible sound design really helps you feel what Riz's character Reuben is going through. Really a remarkable film.</p>
<p><strong>Possessor</strong> The synopsis had me at "corporate assassin" but I wasn't prepared to see the most inventive and disturbing movie of the year. Possessor does a great job of "show, don't tell." The process by which one is "possessed" is never explained but you very quickly understand it. Christopher Abbott is great in this. Incredible use of practical effects and some of the most disturbing body horror in years. I'd expect nothing less from the son of David Cronenberg.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/qX4UuW_aF4-300.webp 300w, https://mikeaparicio.com/images/qX4UuW_aF4-600.webp 600w, https://mikeaparicio.com/images/qX4UuW_aF4-1100.webp 1100w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/qX4UuW_aF4-300.jpeg 300w, https://mikeaparicio.com/images/qX4UuW_aF4-600.jpeg 600w, https://mikeaparicio.com/images/qX4UuW_aF4-1100.jpeg 1100w" sizes="100vw" /><img alt="" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/qX4UuW_aF4-300.jpeg" width="1100" height="619" /></picture>
<figcaption>One of Possessor's many frightening visuals</figcaption>
</figure>
<p><strong>Another Round</strong> I absolutely loved this. The most relatable film of 2020. Who among us has not considered maintaining a near constant state of drunkenness to overcome the monotony of our lives this year? There is a moment of catharsis in this film that brought me so much joy and hope that 2021 has better things in store for us. Great performance by Mads Mikkelsen, who is such an endlessly compelling actor to watch. Even when he's not doing or saying anything, every crease in his face seems to convey emotion.</p>
<p><strong>His House</strong> An incredible debut from writer/director Remi Weekes. Along with films like Atlantics, I'm loving being able to see non-Western takes on the supernatural. The less you know about this one going in, the better.</p>
<p><strong>Palm Springs</strong> A delightful take on the time loop genre. Maybe the most 2020 movie of 2020. I loved the chemistry between Andy Samberg and Cristin Milioti.</p>
<p>You can find the rest of my <a href="https://letterboxd.com/peruvianidol/list/favorite-films-of-2020/">favorite films of 2020</a> over on Letterboxd.</p>
<h3>TV</h3>
<p><strong>The Last Dance</strong> In such a dark time in our history it felt so good to re-live the most exciting time in my life β when the Bulls won six championships in eight years. I was so obsessed with this team that watching them fueled my interest in web development and sports journalism. I don't know where I would be today without this team.</p>
<p>While I had seen and vividly remember so many of the moments covered, this doc provides unprecedented insight from all of the people involved, from the team to their opponents to the media and notable Bulls fans. Most remarkably, however, is the degree of candidness shown by Michael Jordan as he reflects back on his storied career.</p>
<p><strong>Ted Lasso</strong> A wonderful salve for the depression and anxiety of 2020. Jason Sudekis plays a college football coach who is hired to coach an English Premier League soccer team, having absolutely no experience or knowledge of soccer. Despite being unwelcome by the players and fans alike, (SPOILER ALERT) Ted Lasso wins them over with charm and optimism. I loved it.</p>
<p><strong>Devs</strong> Alex Garland's Ex Machina follow-up that I wanted and didn't get with Annihilation. Breathtaking visuals and some thought-provoking ideas. Loved Nick Offerman as the CEO of a tech company pursuing a potentially world-changing technology at any cost.</p>
<p><strong>Dave</strong> Rapper/comedian Lil Dicky (aka Dave Burd) stars in this exaggerated retelling of his rise to pseudo fame. Weaved around a bunch of childish dick jokes, there's some really poignant stuff, including an episode almost entirely featuring Dave's real-life hype man, GaTa, and his battle with bipolar disorder.</p>
<figure>
<iframe src="https://www.youtube.com/embed/NS71zL6Zn1s" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0"></iframe>
<figcaption>
Dave shows off his skills
</figcaption>
</figure>
<p><strong>Middleditch & Schwartz</strong> Having spent several years studying writing and improv at Second City, I've watched (and performed in) my share of terrible improv shows. Thomas Middleditch and Ben Schwartz's three Netflix specials are a masterclass in long-form improv. They take an idea from the audience and flesh it out over the course of an hour, adding new characters, switching characters and generally fucking with each other while telling a coherent story.</p>
<p><strong>How To with John Wilson</strong> A wildly entertaining documentary series from the producers of Nathan for You. New Yorker John Wilson explores various topics through humorous footage of the city which often takes him (and us) on unexpected tangents.</p>
<h3>Video Games</h3>
<p><strong>Ghost of Tsushima</strong> I've been meaning to write a whole post about how much I love this game. When it first came out I was comparing it (rather unfavorably) to Nioh 2, another action game set in feudal Japan that I absolutely loved. I played for a bit and then moved on to other games.</p>
<p>But then something incredible happened. Developer Suckerpunch released a free DLC of co-op content called Legends, which in itself could probably be a full-priced stand-alone game. My friends and I dipped into the 4-player horde mode and 2-player story mode, which take a game otherwise grounded in reality and add a supernatural twist.</p>
<figure>
<img src="https://mikeaparicio.com/images/tsushima.gif" />
<figcaption>This game is so fucking cool</figcaption>
</figure>
<p>Playing as one of four character classes, we built our characters up until we were powerful enough to take on the mode's biggest challenge, the Tale of Iyo raid. Ghost of Tsushima's raid definitely draws inspiration from games like Destiny, but is far more accessible. My friends and I had a blast playing this mode, and I went back into the single-player campaign and got all of the trophies. Even after a few hundred hours, the combat and visuals still feel fresh.</p>
<p>Ghost of Tsushima is hands-down my game of the year, and possibly one of the greatest games I've ever played.</p>
<p><strong>Call of Duty</strong> I wrote earlier this year about <a href="https://www.mikeaparicio.com/posts/2020-10-22-why-i-love-modern-warfare-again/">how I got sucked back into Call of Duty</a>, thanks largely in part to its Battle Royale mode, Warzone. After months of playing, I managed to secure my first solo win, 23.5 hours into my Extra Life stream, while I was delirious from lack of sleep. In the past week I managed another solo win and a couple of wins on the new, smaller Rebirth Island map. I'm still having a ton of fun with it, both solo and with friends. Integrating Black Ops: Cold War weapons and characters has breathed new life into Warzone as well.</p>
<p><strong>Animal Crossing: New Horizons</strong> <a href="https://www.mikeaparicio.com/posts/2020-05-04-why-i-love-animal-crossing/">I will always look back fondly on ACNH</a> as the game that got me through the early months of the pandemic. I connected with a bunch of web design folks, including people whose careers I've followed and have inspired me for years. It was surreal hanging out with them in this virtual world, trading items, hanging out in each other's homes and watching shooting stars. I've since moved on, but perhaps I'll dip back in sometime and see what new stuff they've added while I've been away.</p>
<p><strong>Last of Us Part 2</strong> I had high expectations for this sequel to 2013's narrative masterpiece, and it didn't disappoint. The plot was incredibly polarizing, but I enjoyed it quite a bit, aside from some bizarre character turns and a comically drawn out climax. There are so many quiet moments where mundane things we take for granted take on new meaning in a world torn apart by zombies. While Naughty Dog hasn't innovated too much on their combat systems over the years, it was still fun enough to keep me playing for ~30 hours.</p>
<p><strong>Nioh 2</strong> The sequel to the Soulslike that finally got me to appreciate the Dark Souls games improves on the first in just about every way. New systems, new weapons and a new story combined for a thrilling experience. Definitely a more technical game, combat-wise, than Ghost of Tsushima, Nioh 2 is incredibly challenging and satisfying when you finally master it. Sadly, we recently learned that this will be the last Nioh game. Hopefully we get something in the same vein that builds on this engine in the future.</p>
<h3>Podcasts</h3>
<p><strong>Culturally Relevant</strong> With my driving almost non-existent this year, I didn't really have time for many podcasts. I wanted to call out Dave Chen's <a href="https://culturallyrelevantshow.com/">Culturally Relevant</a> again this year. Dave mixed compelling interviews with his own personal experience of the pandemic and the Black Lives Matter movement. It was consistently solid all year. Dave recently started a Patreon in order to support his many content creation endeavors, which I eagerly signed on for. He has not disappointed with the stuff he's cranking out lately.</p>
<h3>Heroes of the Pandemic</h3>
<p>I wanted to call out a few people who helped get me through a rough year through their humor and optimism. These are my Heroes of the Pandemic.</p>
<p><strong>Ian Abramson</strong> When Saturday Night Live went on hiatus at the start of the pandemic, comedian Ian Abramson took up the torch, <a href="https://news.avclub.com/our-favorite-sketches-from-ian-abramsons-solo-saturday-1842444578">creating his own bizarre version of SNL</a> on his Twitch channel.</p>
<p><strong>Nathan Apodaca</strong> <a href="https://newsroom.tiktok.com/en-us/doggface-gives-the-world-a-smile-with-juice-a-skateboard-and-all-the-vibes">A spontaneous TikTok video</a> of Nathan Apodaca (aka Doggface208) skateboarding to work while drinking cranberry juice and vibing to Fleetwood Mac's <em>Dreams</em> not only catapulted him to internet fame, but even revived interest in Fleetwood Mac. The video scored the humble Apodaca a free truck and crates of Ocean Spray, among other things.</p>
<p><strong>Nandi Bushell</strong> This 10-year-old drumming prodigy challenged Dave Grohl to a drum-off. <a href="https://www.youtube.com/watch?v=OZBQW2gE0Ew">Dave took up the challenge</a>... and lost. Nandi is a delightful and energetic musician and I can't wait to see what she does next.</p>
<p><strong>Sarah Cooper</strong> Comedian Sarah Cooper made a name for herself <a href="https://www.tiktok.com/@whatchugotforme/video/6819061413877763334">lip-syncing to clips of Donald Trump</a>. Her career took off this year, netting herself a Netflix special and guest-hosting gigs on late night TV.</p>
<p><strong>Blaire Erskine</strong> Erskine became internet famous with her <a href="https://twitter.com/blaireerskine/status/1298026613871910912?s=20">straight-faced parodies of conservatives</a>. So spot on, it was hard to tell whether they were characters or real people.</p>
<p><strong>Alexandra Kyle</strong> Alexandra <a href="https://twitter.com/alixykyle/status/1313878959637946368?lang=en">reenacts scenes from Sex in the City</a>, lip-syncing every character except Samantha, who is played by her cat. It's pretty amazing.</p>
<p><strong>Amber Ruffin</strong> Writer/comedian Amber Ruffin was a breakout star on Late Night with Seth Meyers in sketches like this one, where she lists <a href="https://www.youtube.com/watch?v=iKgfgSch8BU">all the things Donald Trump has done for black people</a>. Amber now has her own show now on Peacock, where she continues to mix cutting commentary with delightful humor.</p>
<p><strong>Matisse Thybulle</strong> Sixers rookie Matisse Thybulle took us <a href="https://www.youtube.com/watch?v=_DzaVY5tPZg&list=PLMICLletO8dDwQaGpipv8Z9t_UVIG3Pn9">inside the NBA bubble</a> in Orlando last season, giving us an intimate look at his daily routine, the NBA's strict COVID protocols, and conversations with his teammates about the Black Lives Matter movement. Thybulle showed a great talent for hosting and editing and probably has a great career ahead in media after his playing career is done.</p>
<p><strong>Eva Victor</strong> I loved Eva Victor's weird, manic characters. Here's one of <a href="https://twitter.com/evavictor/status/1312024079562571776">a democrat reacting to the news that the President got COVID</a>. Someone please give her a show.</p>
<p><strong>Jeff Wright</strong> Jeff Wright went viral with <a href="https://twitter.com/jeffrightnoww/status/1250586217546203138?lang=en">Real Aliens Be Like</a> and kept cranking out hilarious videos where he played all the parts. It landed him a writing gig on Late Night with Seth Meyers, where he's appeared on camera a few times already.</p>
<h2>Looking forward to in 2021</h2>
<p><strong>Bye Trump!</strong> Barring some nightmare scenario, we'll finally be rid of the sociopathic narcissist that currently occupies the White House. He's inflicted so much damage over four years I can't even comprehend how 70 million people looked it and said, "more of that, please!" And on top of that they think they were somehow cheated out of millions more votes?</p>
<p>Even with Trump out of office, the damage he's done will take years, if not decades to recover from. I don't think anyone is <em>excited</em> about Joe Biden, but at least we'll have someone in charge who has the slightest bit of empathy and respect for the American people.</p>
<p><strong>Remodeling our bathroom</strong> Spending almost an entire year in lockdown has made us realize how important it is for our space to be comfortable and usable. Our house is 100 years old and its bathrooms are like indoor outhouses. We're looking into expanding the upstairs one a little bit, enough for a soaking tub and separate shower. Someday we'd like to finish our attic and make it a master suite, but in the meantime we'll settle for a slightly nicer bathroom.</p>
<p><strong>Traveling (hopefully)</strong> I miss traveling. I want to spare no expense in getting the hell out of Illinois as soon and as frequently as possible. I haven't given a ton of thought to destinations, but I'd like to visit new places and see old friends and eat myself into a food coma.</p>
<p><strong>Taking it easy on myself</strong> If you know me you're probably thinking, <em>Mike, you take it easy on yourself all the time</em>. If there's anything this pandemic has reminded me of its that most of the stuff we think is so important is really not. I often remind people who get too serious about their work that they're not curing cancer (or COVID, as it were). I need to try to be in the moment, rather than dwelling on the past or worrying about a future that's out of my control. This is especially important to me with Ryan.</p>
<p>And really we need to take it easy on each other. It's hard not to blame individuals for bad behavior when "the system" only encourages it. Let's all try and offer each other more encouragement (via pizza or otherwise) and show people how much they mean to us. Because if this pandemic has shown us anything its how precious our time is together.</p>
<p>Except racists. Fuck them.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/xQ2XGHJE6K-300.webp 300w, https://mikeaparicio.com/images/xQ2XGHJE6K-600.webp 600w, https://mikeaparicio.com/images/xQ2XGHJE6K-2624.webp 2624w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/xQ2XGHJE6K-300.jpeg 300w, https://mikeaparicio.com/images/xQ2XGHJE6K-600.jpeg 600w, https://mikeaparicio.com/images/xQ2XGHJE6K-2624.jpeg 2624w" sizes="100vw" /><img alt="Mike and his family in quarantine." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/xQ2XGHJE6K-300.jpeg" width="2624" height="2624" /></picture>
<figcaption>Happy New Year from Mike, Allie, Joe, Ryan, Emily, and Geno</figcaption>
</figure>
Why I Love Modern Warfare (Again)
2020-10-22T00:00:00Z
https://mikeaparicio.com/posts/2020-10-22-why-i-love-modern-warfare-again/
<p>In the early 2000s, the Call of Duty series was just one of many first-person shooters set in World War II. The fourth installment, however, took the franchise to a whole new level and helped make Call of Duty a fixture of pop culture and one of the top selling franchises of all time.</p>
<p>2007's <strong>Call of Duty 4: Modern Warfare</strong> was the first of the series to be set in modern times. It had you jumping from character to character, across the globe, and featured some of gaming's most unforgettable levels. In one, you find yourself as a gunner on a AC-130, providing air support through infrared cameras for a heavily out-manned squad below. In another, a seasoned vet guides you on a recon mission through the abandoned town of Pripyat, Ukraine which goes south.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/QEvkfll_Kh-300.webp 300w, https://mikeaparicio.com/images/QEvkfll_Kh-600.webp 600w, https://mikeaparicio.com/images/QEvkfll_Kh-762.webp 762w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/QEvkfll_Kh-300.jpeg 300w, https://mikeaparicio.com/images/QEvkfll_Kh-600.jpeg 600w, https://mikeaparicio.com/images/QEvkfll_Kh-762.jpeg 762w" sizes="100vw" /><img alt="The All Ghillied Up Level of Modern Warfare" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/QEvkfll_Kh-300.jpeg" width="762" height="401" /></picture>
<figcaption>
An intense recon mission through Pripyat in 2007's Call of Duty: Modern Warfare (remastered in 2016).
</figcaption>
</figure>
<p>While the single-player campaign was incredible, it was Modern Warfare's multiplayer mode that really shined. Fast-paced action with modern weapons and tactical gear was a ton of fun. Call of Duty became so popular that Activision began cranking them out every fall, each one raking in more money than the last. I was hooked.</p>
<p>After a dispute with Activision, the founders of Infinity Ward (the studio behind Modern Warfare) split to form a new company called Respawn Entertainment, taking a number of the team with them. They went on to make Titanfall, a futuristic first-person shooter where players could battle on foot or within the cockpit of a giant mech. Titanfall added a bunch of innovations to the FPS genre, taking the pace of Call of Duty even higher with wall-running and double jumping, and an increased emphasis on verticality. Needless to say, I LOVED Titanfall.</p>
<p>With the popularity of Titanfall, Call of Duty games tried to ape it, taking the series into the future and copying a lot of the mobility mechanics. They just didn't quite pull it off, and it lacked Titanfall's mech vs. pilot mechanic that was so skillfully designed. Each Call of Duty's multiplayer kept trying to one-up the next with crazier abilities and kill streaks until it just became inaccessible to all but the most die hard fans.</p>
<p>I eventually lost interest and veered more towards games like Battlefield, which featured bigger battles, vehicle combat, and support roles that allowed you to contribute to the team without strictly having to have a high kill/death ratio. Eventually I got sucked into Destiny, which really became my go-to FPS game. When the magic of Destiny finally wore off after several years, I was itching for a new experience.</p>
<h2>Welcome back, old friend</h2>
<p>In 2019, Infinity Ward reset the clock and took Modern Warfare back to its roots with <strong>Call of Duty: Modern Warfare</strong>. The new Modern Warfare features one of the best FPS campaigns I've played in years, second only to Titanfall 2, since the original Modern Warfare. After beating the campaign a couple of times, I was content to put the game on the shelf, not even touching its multiplayer.</p>
<p>Modern Warfare included a new Battle Royale mode, Warzone β the first in a Call of Duty game β and I didn't really give it much of a shot. But earlier this year, after being mysteriously banned from Twitch, popular streamer <a href="https://www.youtube.com/c/DrDisRespect">Dr DisRespect</a> resurfaced on YouTube and I started watching him play Warzone with another streamer <a href="https://www.youtube.com/c/ZLANER">ZLaner</a>.</p>
<p>Doc and Z made Warzone look incredibly fun so I dipped a toe back in and⦠well, you can probably guess what happened next.</p>
<figure>
<img src="https://mikeaparicio.com/images/they-pull-me-back-in.gif" alt="Michael Corleone in Godfather Part 3: Just when I thought I was out, they pull me back in." />
<figcaption>
There's no escaping
</figcaption>
</figure>
<h2>Warzone</h2>
<p><strong>But Mike, I thought <a href="https://mikeaparicio.com/posts/2019-02-18-why-i-hate-battle-royales/">you hate Battle Royales</a>?</strong></p>
<p>Yes. I found games like PUBG, Fortnite and even Apex Legends to be pretty tedious. While they have the potential to deliver thrills, the moment to moment gameplay felt like a lot of sitting around.</p>
<p>Warzone addresses this in a few unique ways:</p>
<p><strong>The Gulag</strong> When you die in Warzone, the game doesn't immediately end. You're placed into a prison shower room reminiscent of the 1996 Michael Bay masterpiece <em>The Rock</em>, forced to duke it out 1v1 against another player who met an early demise. The winner immediately parachutes back onto the battlefield.</p>
<p><strong>Buy Stations</strong> If you lose the Gulag fight and are playing with teammates, they can buy you back into the game at one of many buy stations scattered across Warzone's vast map.</p>
<p><strong>Contracts</strong> These can be found scattered across the map and task you with completing different types of objectives within a certain time limit. Everything from killing a specific player whose general location is marked on the map to collecting three loot crates. Contracts give your team something to do to earn money and XP without necessarily needing to win gunfights.</p>
<p>Warzone also has a ton of weapons, attachments and cosmetic items to unlock via playing the game or completing challenges. The incentives to continue playing are many.</p>
<p>Aside from that, Warzone is like a lot of other Battle Royales, mechanics-wise. But it has a level of realism and polish that other BRs lack.</p>
<h2>Zombie Royale</h2>
<p>With Halloween around the corner, Infinity Ward released some limited-time events in Warzone, including <strong>Zombie Royale</strong>. This mode is similar to normal Warzone except it takes place at night, making equipment like thermal optics all the more useful.</p>
<p>Oh yeah, and instead of dying, you come back as a zombie who can run fast, jump high, throw gas grenades and release EMP bursts. Retrieving two vials dropped by dead players will cause you to immediately parachute back onto the map. There is no Gulag.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/MfNIhSy2yB-300.webp 300w, https://mikeaparicio.com/images/MfNIhSy2yB-600.webp 600w, https://mikeaparicio.com/images/MfNIhSy2yB-762.webp 762w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/MfNIhSy2yB-300.jpeg 300w, https://mikeaparicio.com/images/MfNIhSy2yB-600.jpeg 600w, https://mikeaparicio.com/images/MfNIhSy2yB-762.jpeg 762w" sizes="100vw" /><img alt="Zombies roam the streets of Verdansk at night." loading="lazy" decoding="async" src="https://mikeaparicio.com/images/MfNIhSy2yB-300.jpeg" width="762" height="429" /></picture>
<figcaption>
If you can't beat the zombies, join 'em!
</figcaption>
</figure>
<p>In addition to that, the circle of gas that forces players together starts much tighter, causing 150 players to land much closer together than normal and creating a quick influx of zombies to the world.</p>
<p>The ability to get back into the fight quickly makes this mode incredibly fun as zombies scramble to kill living players and pick up their vials in hopes of respawning.</p>
<p>I introduced my friend Dave to Warzone last weekend, just before Zombie Royale launched. When it came out on Tuesday we hopped in to try it out and were matched with a third, random player. In a wild finish, Dave was the last of our team alive and somehow survived to the end thanks to some clutch plays and we won our first Warzone match. It was incredibly thrilling and I couldn't fall asleep afterwards for at least an hour, I was so jacked on adrenaline.</p>
<blockquote class="twitter-tweet" data-theme="dark"><p lang="en" dir="ltr">Last Saturday: Play Call of Duty Warzone for the very first time.<br />Today: Get first place in Warzone's special Zombie Halloween event <br />Tomorrow: Retire <a href="https://t.co/djelbX9WCW">https://t.co/djelbX9WCW</a></p>— David Chen (@davechensky) <a href="https://twitter.com/davechensky/status/1318789879224889344?ref_src=twsrc%5Etfw">October 21, 2020</a></blockquote>
<h2>Multiplayer</h2>
<p>Modern Warfare's regular multiplayer mode goes back to boots-on-the-ground basics of older Call of Duty games. It just feels⦠right. The game has been out almost a year, so there's a ton of maps, including a few remasters of classic Call of Duty maps.</p>
<p>The progression system is shared between multiplayer and Warzone, so multiplayer is a much more efficient means to level your weapon and player experience and complete challenges. In Warzone, you're lucky (and pretty skilled) if you get 10 kills in a 30 minute match. Multiplayer is so much more fast-paced, even a terrible player can luck into 10 kills during a 10-minute match.</p>
<p>Multiplayer also serves as good practice for fights in Warzone and you can also use it as a way to test out new weapons and loadouts.</p>
<h2>The Mike Seal of Approval</h2>
<p>Modern Warfare is the deepest and most fun Call of Duty in over a decade. Between a stellar single-player campaign, a return to its multiplayer roots, and the addition of Warzone, Modern Warfare has a little something for everyone (assuming you're a fan of first-person shooters, that is).</p>
<p>I'm really excited (and also kind of nervous) to see how they evolve Warzone with the next Call of Duty, Cold War, coming out in just a few weeks. Will they add Cold War characters, items and locations to the existing Warzone? Will there be two different maps? Will Zombie Royale become a permanent fixture in the playlists? We'll soon find out!</p>
Extra Life 2020
2020-10-14T00:00:00Z
https://mikeaparicio.com/posts/2020-10-14-extra-life-2020/
<p>One month from today I'll be participating in my <strong>SEVENTH</strong> <a href="https://extra-life.org/">Extra Life</a>, a 24-hour gaming marathon supporting local children's hospitals. Last year we raised a record <strong>$5,120</strong> for <a href="https://www.luriechildrens.org/">Lurie Children's Hospital</a> here in Chicago. To date, thanks to the generosity of people like you, we've raised over <strong>$20,000</strong> to help sick kids.</p>
<p>Extra Life is a charity that is dear to my heart. In 2014, my daughter <a href="https://mikeaparicio.com/posts/2018-08-26-four-years/">Olivia</a> was born prematurely and received treatment at Lurie. Sadly, she passed just after my first Extra Life. Since then I've continued to participate to honor her memory, along with my friends Bert and Alan.</p>
<p>Each year we seem to top the previous year's fundraising goal. This year will be especially challenging given the pandemic, but it also means that your help is needed more than ever. There are several ways you can help the cause:</p>
<ul>
<li><strong><a href="https://idol.pe/team-olivia">Make a Donation</a></strong>. Every bit helps!</li>
<li>Join Team Olivia to help us raise funds and play with us on game day. You can visit our <a href="https://extra-life.org/team/olivia">team page</a> and click the "Join Our Team" button. You can choose any hospital in the Children's Hospital Network to support.</li>
<li>Spread the word about our cause. You can link directly to our team page at <a href="https://extra-life.org/team/olivia">https://extra-life.org/team/olivia</a> or to this blog post, or share/retweet any posts that I make about the event.</li>
<li>Tune in to our live stream on Twitch on <strong>Saturday, November 14th</strong>. We'll be kicking things off at 8am Central and gaming for 24 hours straight. Pop into the chat and offer some words of encouragement!</li>
</ul>
<p>Extra Life game day is normally the first Saturday in November, but I decided to do it a week later since the PlayStation 5 is coming out on the 12th. Look forward to checking out some next-gen games!</p>
<p>Thank you so much for your love and support as we continue to keep Olivia's memory alive through helping other sick children!</p>
<p><picture><source type="image/webp" srcset="https://mikeaparicio.com/images/Wy0Wbj4UYh-300.webp 300w, https://mikeaparicio.com/images/Wy0Wbj4UYh-600.webp 600w, https://mikeaparicio.com/images/Wy0Wbj4UYh-960.webp 960w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/Wy0Wbj4UYh-300.jpeg 300w, https://mikeaparicio.com/images/Wy0Wbj4UYh-600.jpeg 600w, https://mikeaparicio.com/images/Wy0Wbj4UYh-960.jpeg 960w" sizes="100vw" /><img alt="Extra Life 2020 - November 14th, 2020" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/Wy0Wbj4UYh-300.jpeg" width="960" height="540" /></picture></p>
Goodbye, Groupon
2020-07-23T00:00:00Z
https://mikeaparicio.com/posts/2020-07-23-goodbye-groupon/
<p>Last year, <a href="https://mikeaparicio.com/posts/2019-04-24-whats-next/">I reminisced about my time at Groupon</a>, and wondered what might be next. It's been over eight and a half years since I started at Groupon and today was my last day.</p>
<p>While I was never incredibly enthusiastic about internet coupons, I was fortunate to work with so many talented, generous and fun people in my time at Groupon. It's really because of them that I stuck around for so long, and because of them that I have grown enough to take the next step in my career.</p>
<p>I put together this video for the team to share some of my fondest memories there.</p>
<figure>
<video controls="" poster="https://mikeaparicio.com/assets/posters/so-long-groupon.png" width="100%">
<source src="https://mikeaparicio.com/assets/videos/goodbye-groupon.mp4" type="video/mp4" />
</video>
</figure>
<p>I also started building out the "<a href="https://mikeaparicio.com/work/">Work</a>" section of my website, where <a href="https://mikeaparicio.com/work/groupon/">I detailed a lot of the work I did at Groupon.</a> I'm planning on adding to that section going all the way back to my first website. It's a lot to sift through and I hope to get some working demos up and running eventually.</p>
<p>On Monday, I'll be starting at <a href="https://www.provi.com/">Provi</a> as the Senior Design Systems Engineer, where I'll have an opportunity to take everything I learned developing CSS frameworks and a design system at Groupon and apply it at a smaller scale. As the company grows, the system will grow to support it.</p>
<p>I'm really excited about this new chapter in my life. I'm someone who thrives on change and after being in the same house for five years, the same job for almost nine years and the same relationship for over ten years, something had to give. And my wife would only allow me to change jobs, so...</p>
Simple Groupon
2020-07-06T00:00:00Z
https://mikeaparicio.com/posts/2020-07-06-simple-groupon/
<p>A few weeks ago we had a one-day hackathon at Groupon called <strong>Simple Groupon</strong>. The basic theme was to work on projects that simplified our processes and tools internally or simplified our customers' experience. I decided it would be a great opportunity to demonstrate the power of our new Groupon Design System to the broader engineering organization.</p>
<p>With our current process, implementing visual style changes can be time-consuming due to existing technical debt and varying degrees of people's comfort/ability with <a href="https://i.imgur.com/Q3cUg29.gif">CSS</a>. Supporting multiple brands (including Living Social) and A/B testing new designs adds further complexity.</p>
<p>Our current styles are largely built with our in-house CSS framework serving as a foundation, similar to Twitter Bootstrap, with individual product teams adding their own "app-specific styles" in order to match the specs provided by design. This leads to a lot of redundant styles scoped to very specific components. Our homepage CSS, which is a combination of our framework and app-specific styles, <a href="https://cssstats.com/stats?url=groupon.com">weighs in at 238k</a>. It includes a number of one-off colors, text sizes and z-indices, and suffers from a lot of specificity problems, as developers fight with the cascade in order to override previous code.</p>
<p>Our new design system addresses these challenges in a couple of ways. First, through the use of design tokens, we can manage all of our visual style decisions in a single file and make updates to it without needing to touch any HTML or CSS.</p>
<p><a href="https://mikeaparicio.com/posts/2018-09-07-driving-your-design-system-with-tokens/">I've written about design tokens previously</a>, but my thinking on tokens has evolved a bit since then. By using three layers of specificity, we can apply varying degrees of control over our visual styles.</p>
<p><strong>Global Tokens</strong> include all of the possible values in the system. The color palette, type scale, spacing values, etc. If we want to change the value of Groupon Green, we can do that here and it will change everywhere that token is used. What once took us several weeks can now be done in a few seconds.</p>
<pre class="language-css"><code class="language-css">$<span class="token property">color-blue-600</span><span class="token punctuation">:</span> #0070CC<span class="token punctuation">;</span></code></pre>
<p><strong>Contextual Tokens</strong> describe how Global Tokens are used. They include common values that are used across multiple components, such as <code>$color-background-brand</code>. Contextual Tokens allow us to change from one Global Token value to another across multiple components.</p>
<pre class="language-css"><code class="language-css">$<span class="token property">color-background-interactive</span><span class="token punctuation">:</span> $color-blue-600<span class="token punctuation">;</span></code></pre>
<p><strong>Component Tokens</strong> are values specific to a single component and can point to Contextual Tokens, Global Tokens, or even one-off values. Component Tokens allow us to make changes to a single component β changing the background color of the CTA button from green to blue, for example β without having to edit the app styles.</p>
<pre class="language-css"><code class="language-css">$<span class="token property">button-cta-background</span><span class="token punctuation">:</span> $color-background-interactive<span class="token punctuation">;</span></code></pre>
<p>As it turns out, <a href="https://bradfrost.com/blog/post/creating-themeable-design-systems/">Brad Frost wrote about this over two years ago</a>, and it must have stuck in my brain. I'm like Pete Campbell inventing direct marketing over here.</p>
<figure>
<video src="https://mikeaparicio.com/assets/videos/pete-arrived-independently.mp4" loop="" autoplay="">
<figcaption>
It only took me a couple of years longer than Brad Frost.
</figcaption>
</video></figure>
<p>The other change I made was to separate the visual styles of components from their layout. Since we can't be sure of all the different contexts in which a component might be used, it makes sense to exclude external values like margin, and instead apply these using utility classes, like in <a href="https://acss.io/">Atomic CSS</a> or <a href="https://tachyons.io/">Tachyons</a>, where each class does one specific thing.</p>
<p>This allows us to compose new components without having to scope all of the styles required to arrange its parts to a class that is specific to the context. Take a deal card for example. Compare <a href="https://gist.github.com/peruvianidol/970bedcbca60954c4a416474066956b1">this markup from our current site</a>, stripped of data attributes, with <a href="https://gist.github.com/peruvianidol/b4d028e33b011bc0d05ddc262ae83ee5">this markup from the Refresh example below</a>, which produces a similar result with less markup and no references to the content or context of the component.</p>
<div class="ma-flex-row">
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/AflXIdqe5c-300.webp 300w, https://mikeaparicio.com/images/AflXIdqe5c-480.webp 480w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/AflXIdqe5c-300.jpeg 300w, https://mikeaparicio.com/images/AflXIdqe5c-480.jpeg 480w" sizes="100vw" /><img alt="A deal card from production" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/AflXIdqe5c-300.jpeg" width="480" height="560" /></picture>
<figcaption>
Production
</figcaption>
</figure>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/5nWECmS2ex-300.webp 300w, https://mikeaparicio.com/images/5nWECmS2ex-516.webp 516w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/5nWECmS2ex-300.jpeg 300w, https://mikeaparicio.com/images/5nWECmS2ex-516.jpeg 516w" sizes="100vw" /><img alt="A revised deal card" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/5nWECmS2ex-300.jpeg" width="516" height="572" /></picture>
<figcaption>
Refresh
</figcaption>
</figure>
</div>
<p>This new approach greatly reduces the amount of HTML and CSS required to reproduce a design, eliminating almost entirely the need for "app-specific styles", making pages much more flexible and maintainable.</p>
<h2>GDS Framework</h2>
<p>The Groupon Design System includes a new CSS framework built entirely from scratch. It builds on everything I learned from developing CSS frameworks for our internal tools, consumer- and merchant-facing products. The framework is built using <a href="https://11ty.dev/">Eleventy</a>, an incredibly simple and easy-to-use static site generator. It uses SASS for CSS pre-processing, but could just as easily use Stylus or CSS variables.</p>
<p><code>gds-grpn.css</code> is compiled from a bunch of individual <code>.scss</code> files. The Groupon design tokens are imported first, so that all the other files have access to them. For additional themes, the Groupon tokens serve as the defaults, to which a separate tokens file can build upon by adding or modifying token values before they are used by the style files.</p>
<div class="ma-flex-row">
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/aUE4zoFUuP-300.webp 300w, https://mikeaparicio.com/images/aUE4zoFUuP-600.webp 600w, https://mikeaparicio.com/images/aUE4zoFUuP-823.webp 823w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/aUE4zoFUuP-300.jpeg 300w, https://mikeaparicio.com/images/aUE4zoFUuP-600.jpeg 600w, https://mikeaparicio.com/images/aUE4zoFUuP-823.jpeg 823w" sizes="100vw" /><img alt="The GDS Groupon SCSS file" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/aUE4zoFUuP-300.jpeg" width="823" height="888" /></picture>
<figcaption>
gds-grpn.scss
</figcaption>
</figure>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/wWGbEzoxGe-300.webp 300w, https://mikeaparicio.com/images/wWGbEzoxGe-600.webp 600w, https://mikeaparicio.com/images/wWGbEzoxGe-874.webp 874w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/wWGbEzoxGe-300.jpeg 300w, https://mikeaparicio.com/images/wWGbEzoxGe-600.jpeg 600w, https://mikeaparicio.com/images/wWGbEzoxGe-874.jpeg 874w" sizes="100vw" /><img alt="The GDS Living Social SCSS file" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/wWGbEzoxGe-300.jpeg" width="874" height="931" /></picture>
<figcaption>
gds-ls.scss
</figcaption>
</figure>
</div>
<p>The different Deal Page examples are built using a templating engine, so you can include the name of the theme in the front matter and then call it in various places in your HTML like this:</p>
<pre class="language-html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>link</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>/css/gds-{{theme}}.css<span class="token punctuation">"</span></span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span><span class="token punctuation">></span></span></code></pre>
<h2>Examples</h2>
<p>Here are four versions of the deal page I was able to produce using the new Groupon Design System. The last three designs were all done in half a day. The same result would take dozens of engineers weeks to implement under our current process.</p>
<p>Note: None of these are responsive, unfortunately, since our current site is also not responsive and I only had a day to work on this. I'm not a miracle worker, <a href="https://twitter.com/beep">Ethan</a>!</p>
<p><picture><source type="image/webp" srcset="https://mikeaparicio.com/images/GhMPTLoZj7-300.webp 300w, https://mikeaparicio.com/images/GhMPTLoZj7-600.webp 600w, https://mikeaparicio.com/images/GhMPTLoZj7-1280.webp 1280w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/GhMPTLoZj7-300.jpeg 300w, https://mikeaparicio.com/images/GhMPTLoZj7-600.jpeg 600w, https://mikeaparicio.com/images/GhMPTLoZj7-1280.jpeg 1280w" sizes="100vw" /><img alt="Refresh screenshot" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/GhMPTLoZj7-300.jpeg" width="1280" height="884" /></picture></p>
<p><strong><a href="https://mikeaparicio.com/simple-groupon/deal-page/">Refresh</a></strong><br />
I applied our latest design system styles to this replica of our existing deal page in the week leading up to Simple Groupon in order to build out the framework and figure out all the different components I'd need to compose the page.</p>
<p><picture><source type="image/webp" srcset="https://mikeaparicio.com/images/BBUJwlN4zb-300.webp 300w, https://mikeaparicio.com/images/BBUJwlN4zb-600.webp 600w, https://mikeaparicio.com/images/BBUJwlN4zb-1280.webp 1280w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/BBUJwlN4zb-300.jpeg 300w, https://mikeaparicio.com/images/BBUJwlN4zb-600.jpeg 600w, https://mikeaparicio.com/images/BBUJwlN4zb-1280.jpeg 1280w" sizes="100vw" /><img alt="Living Social screenshot" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/BBUJwlN4zb-300.jpeg" width="1280" height="884" /></picture></p>
<p><strong><a href="https://mikeaparicio.com/simple-groupon/deal-page-ls/">Living Social</a></strong><br />
Using the same markup and styles, I updated a few token values to support Living Social.</p>
<p><picture><source type="image/webp" srcset="https://mikeaparicio.com/images/DoJ2Lsgad5-300.webp 300w, https://mikeaparicio.com/images/DoJ2Lsgad5-600.webp 600w, https://mikeaparicio.com/images/DoJ2Lsgad5-1180.webp 1180w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/DoJ2Lsgad5-300.jpeg 300w, https://mikeaparicio.com/images/DoJ2Lsgad5-600.jpeg 600w, https://mikeaparicio.com/images/DoJ2Lsgad5-1180.jpeg 1180w" sizes="100vw" /><img alt="Dark Mode screenshot" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/DoJ2Lsgad5-300.jpeg" width="1180" height="815" /></picture></p>
<p><strong><a href="https://mikeaparicio.com/simple-groupon/deal-page-dark/">Dark Mode</a></strong><br />
I did a quick exploration of a Dark Mode version of the deal page.</p>
<p><picture><source type="image/webp" srcset="https://mikeaparicio.com/images/_0OuimcWGC-300.webp 300w, https://mikeaparicio.com/images/_0OuimcWGC-600.webp 600w, https://mikeaparicio.com/images/_0OuimcWGC-1280.webp 1280w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/_0OuimcWGC-300.jpeg 300w, https://mikeaparicio.com/images/_0OuimcWGC-600.jpeg 600w, https://mikeaparicio.com/images/_0OuimcWGC-1280.jpeg 1280w" sizes="100vw" /><img alt="Rebrand screenshot" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/_0OuimcWGC-300.jpeg" width="1280" height="884" /></picture></p>
<p><strong><a href="https://mikeaparicio.com/simple-groupon/deal-page-rebrand/">Rebrand</a></strong><br />
We can make even bigger changes to achieve a dramatically different design in a very short period of time. This page took me just an hour to make. I changed the font to the variable font, <a href="https://fonts.google.com/specimen/Jost">Jost</a>, bumped up the font scale and the border width, squared the borders, and added three new colors.</p>
<p>Compared to our current homepage CSS (238k), the CSS for the above examples <a href="https://cssstats.com/stats?url=https%3A%2F%2Fmikeaparicio.com%2Fsimple-groupon%2Fdeal-page%2F">weighs in at around just 20k</a>, uses less markup, and is far more maintainable.</p>
<h2>Special Thanks</h2>
<p>None of this would have been possible without the help of my Design System Team colleagues, <strong>Michelle Witkowski</strong> and <strong>Lila Fagen</strong>, who have helped drive the visual direction of the system and built the tooling designers will use to deliver designs using the new system. Also, thank you to the entire <strong><a href="https://design.groupon.com/">Groupon Design Union</a></strong>, who helped put the system through its paces and helped contribute to it in ways big and small. And to my manager, <strong>Matt Hanson</strong>, for supporting and advocating for the design system for many years. Also thanks to all of the developers who provided feedback and contributed to Toolstrap, GIG and Mixer over the years and challenged my thinking about design systems and CSS frameworks. Finally, thanks to the design system community for being so generous with their time and knowledge, and constantly pushing design systems forward. This was truly a team effort!</p>
Why I Love Animal Crossing
2020-05-04T00:00:00Z
https://mikeaparicio.com/posts/2020-05-04-why-i-love-animal-crossing/
<p>If you're not one of the <a href="https://www.polygon.com/2020/5/7/21250384/animal-crossing-new-horizons-sales-nintendo-switch">13+ million people playing Animal Crossing: New Horizons</a>, surely you know someone who is. The game is so popular that Nintendo Switches are nearly in as much demand as COVID-19 test kits.</p>
<p>At first glance, Animal Crossing looks pretty childish. I'll admit I was initially reluctant to even read about it, much less buy it. But peer pressure finally got to me and I quickly realized what I was missing out on. Animal Crossing: New Horizons isn't just a game. It's the manifestation of the "we're all in this together" spirit that this global pandemic has stirred in at least some of us.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/FFRWtvPDDf-300.webp 300w, https://mikeaparicio.com/images/FFRWtvPDDf-600.webp 600w, https://mikeaparicio.com/images/FFRWtvPDDf-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/FFRWtvPDDf-300.jpeg 300w, https://mikeaparicio.com/images/FFRWtvPDDf-600.jpeg 600w, https://mikeaparicio.com/images/FFRWtvPDDf-800.jpeg 800w" sizes="100vw" /><img alt="The residents of Quarantine" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/FFRWtvPDDf-300.jpeg" width="800" height="450" /></picture>
<figcaption>
A photo mode allows you to pose for pics with all of your island's residents.
</figcaption>
</figure>
<h2>WTF is Animal Crossing?</h2>
<p>Animal Crossing: New Horizons, is the fifth entry in the Animal Crossing series (and the first one I've played). The game drops you off on an island where Tom Nook, a tanuki loan-shark, invites you to set up camp, and eventually, permanent residence on the island. The game takes place in real-time, with certain creatures and events only available during certain times.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/fNIaheEjTC-300.webp 300w, https://mikeaparicio.com/images/fNIaheEjTC-600.webp 600w, https://mikeaparicio.com/images/fNIaheEjTC-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/fNIaheEjTC-300.jpeg 300w, https://mikeaparicio.com/images/fNIaheEjTC-600.jpeg 600w, https://mikeaparicio.com/images/fNIaheEjTC-800.jpeg 800w" sizes="100vw" /><img alt="Tom Nook gives the daily announcements" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/fNIaheEjTC-300.jpeg" width="800" height="450" /></picture>
<figcaption>
I named my island "Quarantine," which leads to some fun dialog.
</figcaption>
</figure>
<p>Nook offers to front you the money to upgrade your tent to a house, and your house into a bigger house, leaving you almost constantly in his debt. As your actions raise the profile of the island, new animal villagers will take up residence on the island.</p>
<p>Besides building and decorating your house, you can acquire items, clothing and furniture through various means, including crafting. You can fish for dozens of types of sea creatures, catch bugs, and dig up fossils, which can all be donated to the curator of the local museum or sold to help pay back your loan. You can plant trees and breed flowers. There are constant visitors to the island that require your help or offer goods and services. You can build relationships with your island neighbors and find new neighbors while visiting other islands. There's also a stock market-like turnip economy that, when played correctly, can make money a trivial concern and get Tom Nook off your back forever.</p>
<p>Aside from eventually paying off your loans and raising your island's rating enough to attract K.K. Slider, a singing dog, to perform a show on your island, there's really no goal other than to build your dream home and its surroundings. So why does everyone love this game?</p>
<h2>#TogetherApart</h2>
<figure class="ma-float-left">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/nSKKOuskey-300.webp 300w, https://mikeaparicio.com/images/nSKKOuskey-500.webp 500w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/nSKKOuskey-300.jpeg 300w, https://mikeaparicio.com/images/nSKKOuskey-500.jpeg 500w" sizes="100vw" /><img alt="An Animal Crossing date gone sour" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/nSKKOuskey-300.jpeg" width="500" height="500" /></picture>
<figcaption>
Animal Crossing lets me relive awkward dating experiences from before I was married.
</figcaption>
</figure>
<p>There's no shortage of multiplayer gaming experiences out there β some competitive and some cooperative β that allow us to interact with friends and strangers alike from the comfort of our own homes. Games like Fortnite pit you and your friends against dozens of strangers in an anxiety-driven competition. Not only are you competing with other teams, but also bickering with your friends about which way to go and who should take what gear. It's exhausting.</p>
<p>On the other hand, Animal Crossing is incredibly cooperative. Since players have their own islands, people are generally helpful in sharing tips, items and allowing people to visit their islands to sell turnips at ridiculously high prices. I made my first million when my shop was offering an absurd amount in exchange for turnips and I opened my island up to strangers on the subreddit <a href="https://www.reddit.com/r/TurnipStonkMarket/">r/TurnipStonkMarket</a>, who tipped generously for the opportunity.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/_XwkuN9xTu-300.webp 300w, https://mikeaparicio.com/images/_XwkuN9xTu-450.webp 450w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/_XwkuN9xTu-300.jpeg 300w, https://mikeaparicio.com/images/_XwkuN9xTu-450.jpeg 450w" sizes="100vw" /><img alt="An occult gathering of friends" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/_XwkuN9xTu-300.jpeg" width="450" height="450" /></picture>
<figcaption>
Wishing upon stars in an ancient pagan ritual, as one does.
</figcaption>
</figure>
<p>Shortly after buying Animal Crossing, I was invited to a group of designers and developers who play, several of whom I have followed for many years and look up to as experts in my field. It is such a collaborative and supportive group. We constantly visit each other's islands when shops and villagers offer interesting items or to wish on shooting stars together on a clear night. (Yes, this is an actual mechanic in the game that generates crafting materials.) It's incredibly surreal to share a virtual moment with people I've seen speak at conferences and whose books and blogs I've read.</p>
<h2>So Many Items</h2>
<p>The sheer amount of items in this game is pretty astounding. There's so much variety in clothing, accessories, wallpaper, flooring, furniture, and plants. Each character, each house, and each island becomes an expression of its owner's personality. It feels weirdly intimate when you visit someone's island and enter their virtual house.</p>
<p>There's a kind of <a href="https://en.wikipedia.org/wiki/Emergent_gameplay">emergent gameplay</a> in Animal Crossing known as a catalog party. A number of people visit an island and bring about a dozen items with them. Everyone gathers in one location and drops their items on the ground. There's often marked areas for each person to use so that items don't get mixed up. Everyone then takes turns picking up and then immediately dropping each group of items until they arrive back at their own pile. Each item you pick up is then added to the items you can purchase from an in-game catalog (hence the name).</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/a4CuhLSwZu-300.webp 300w, https://mikeaparicio.com/images/a4CuhLSwZu-600.webp 600w, https://mikeaparicio.com/images/a4CuhLSwZu-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/a4CuhLSwZu-300.jpeg 300w, https://mikeaparicio.com/images/a4CuhLSwZu-600.jpeg 600w, https://mikeaparicio.com/images/a4CuhLSwZu-800.jpeg 800w" sizes="100vw" /><img alt="Emergent gameplay in Animal Crossing" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/a4CuhLSwZu-300.jpeg" width="800" height="450" /></picture>
<figcaption>
A highly successful catalog party!
</figcaption>
</figure>
<p>After attending one of these and getting a ton of new items to decorate my island with, I created an elaborate catalog party space on my island and asked people in my group to list 12 items they wanted in a Google Sheet. Each person crossed items off other people's lists that they were able to bring. This greatly reduced the amount of duplicate items people brought and resulted in people getting a lot of what they were looking for as well as a bunch of other cool items they didn't even know were available.</p>
<p>This kind of "everyone wins" gameplay only further fuels people's love for the game and enhances their connection to other players.</p>
<h2>Third-party Apps</h2>
<p>With any game there's always going to be apps developed that help make the game a bit easier. Animal Crossing has inspired a slew of great apps.</p>
<p><strong><a href="https://nookazon.com/">Nookazon</a></strong> A comprehensive database of Animal Crossing items. It allows you to keep an inventory of your own items, trade items with other players, and keep a wish list of items you're looking for. My wife laughs anytime she catches me on this website, meticulously maintaining my catalog of items.</p>
<p><strong><a href="https://turnipprophet.io/">Turnip Profit</a></strong> and <strong><a href="https://stalks.io/">Stalks.io</a></strong> Both of these sites use crowdsourced data to predict turnip prices on your island. Both seem to use the same prediction data. I find Turnip Prophet to be more detailed but Stalks has a social component that allows you to track the prices of your friends.</p>
<p><strong><a href="https://turnip.exchange/">Turnip Exchange</a></strong> Turnip Exchange allows people to post their turnip prices and let other people queue up to sell turnips on their island. What started out as a nice thing to do for people in exchange for optional tips has led to increasingly high demands of things like Nook Miles Tickets (an item that lets you visit random islands with various resources) and other rare in-game items. There have also been increasing reports of scammers requiring steep entry fees and then booting visitors before they could sell their turnips. So be careful!</p>
<p><strong><a href="https://acpatterns.com/">AC Patterns</a></strong> One of the cool features of Animal Crossing is that it allows you to make custom textures that can be applied to clothes, walls, floors, or signs in the game, allowing for incredible customization. AC Patterns has a ton of patterns submitted by people as well as an editor that allows you to import images into the game via QR code. Finally a good use for QR codes!</p>
<p><strong><a href="https://nooksisland.com/designs">Nook's Island</a></strong> Another repository of custom designs, Nook's Island also includes detailed data on fish and insects, which can only be found during certain hours and/or months of the year.</p>
<p><strong><a href="https://eugeneration.github.io/HappyIslandDesigner/">Happy Island Designer</a></strong> Happy Island Designer is a handy app for planning out your island before committing to all of the tedious work that goes into doing it in-game.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/cjLeFeS_my-300.webp 300w, https://mikeaparicio.com/images/cjLeFeS_my-600.webp 600w, https://mikeaparicio.com/images/cjLeFeS_my-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/cjLeFeS_my-300.jpeg 300w, https://mikeaparicio.com/images/cjLeFeS_my-600.jpeg 600w, https://mikeaparicio.com/images/cjLeFeS_my-800.jpeg 800w" sizes="100vw" /><img alt="Barcade themed basement" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/cjLeFeS_my-300.jpeg" width="800" height="450" /></picture>
<figcaption>
Just hanging out in my basement, like real life.
</figcaption>
</figure>
<h2>The Mike Seal of Approval</h2>
<p>Animal Crossing: New Horizons is a wonderful, calming experience. It is incredibly deep, offering a seemingly endless number of customization options that help each player create a unique environment. The game continues to grow, with seasonal activities and new items and vendors appearing at a steady pace. The best part of ACNH is how it brings friends and strangers together, virtually at least, to hang out and help each other make the best island they can.</p>
<p>When we finally emerge from our homes, hairy, squinting at the sun, I will look back fondly at Animal Crossing: New Horizons as one of the few bright spots that helped get us through.</p>
<h2>Further Reading</h2>
<ul>
<li><a href="https://www.polygon.com/2020/4/23/21233074/animal-crossing-new-horizons-elijah-wood-model-citizen">Elijah Wood is the model Animal Crossing player</a></li>
<li><a href="https://www.slashfilm.com/animal-crossing-movie-scenes-recreations/">People Are Getting Through Quarantine By Recreating Movie Scenes in Animal Crossing: New Horizons</a></li>
<li><a href="https://twitter.com/capuchinokappu/status/1256698938603630592">Recreating Haunted Mansion in Animal Crossing</a></li>
<li><a href="https://www.digitaltrends.com/gaming/coolest-animal-crossing-new-horizons-islands/">Get inspired by the coolest Animal Crossing: New Horizons islands</a></li>
<li><a href="https://www.polygon.com/2020/4/28/21239828/animal-crossing-late-night-talk-show-gary-whitta-rogue-one">Rogue One writer launches a late-night talk show inside Animal Crossing</a></li>
<li><a href="http://www.nintendolife.com/news/2020/04/random_animal_crossing_new_horizons_player_hosts_amazing_game_of_deal_or_no_deal">Animal Crossing: New Horizons Player Hosts Amazing Game Of Deal Or No Deal</a></li>
</ul>
Quarantine Diary 1
2020-04-13T00:00:00Z
https://mikeaparicio.com/posts/2020-04-13-quarantine-diary-1/
<p>I've been kicking around a few ideas for posts recently, but it seemed a little bit silly to be writing about CSS or video games when the world is in the midst of a pandemic.</p>
<p>For several weeks now, (what is time anymore?) we've all been under stay-at-home orders, maintaining social distancing and generally trying not to lose our collective shit as COVID-19 has spread throughout the world. At the time I'm writing this, John Hopkins University reports a total of 1.87M confirmed cases and 116k deaths throughout the world. Just in my small Chicago suburb, there have been nearly 100 cases and two deaths. And these numbers are probably well below the actual totals because of a lack of testing.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/VTagYMU30F-300.webp 300w, https://mikeaparicio.com/images/VTagYMU30F-500.webp 500w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/VTagYMU30F-300.jpeg 300w, https://mikeaparicio.com/images/VTagYMU30F-500.jpeg 500w" sizes="100vw" /><img alt="The author in his new outdoor attire" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/VTagYMU30F-300.jpeg" width="500" height="500" /></picture>
<figcaption>
Me, on a rare expedition for supplies
</figcaption>
</figure>
<p>So many people have already been affected by the virus, directly or indirectly through its effects on the economy, that I feel like an asshole for talking about how it has effected me, given that I'm in a pretty fortunate situation. I think it's important that people share what they're going through so that they know they're not alone and, hopefully, we can all get through this together.</p>
<p>Having already been dealing with depression and anxiety after the loss of my daughter, it's been dialed up a few notches in the last few months. It feels like I'm in the NICU all over again. Things seem dire and the feeling of not knowing how things are going to play out, and the feeling of dread about the worst case scenario is overwhelming. Only now instead of just my daughter, I'm worried about my entire family, my friends, my colleagues, and the world in general.</p>
<p>It's not a great time to be <a href="https://www.chicagotribune.com/business/ct-biz-groupon-layoffs-poison-pill-20200413-kkwqynhpcrh2pi65emegbs3ajy-story.html">working for a company</a> whose business model depends on people leaving their house. Working on a design system right now seems frivolous as my wife, a special education director, deals with trying to figure out how to service special needs students remotely and a host of other issues.</p>
<p>Meanwhile, we're caring for a 14-month-old and a 16-year-old while trying to work from home. Because my time is split I feel like I'm not doing an adequate job at work or taking care of my kids. The 14-month-old is oblivious to the whole situation but he's at a stage where he's just mobile enough and curious enough to require constant supervision. Meanwhile the 16-year-old is missing out on his social life and his baseball season, which I'm sure is incredibly frustrating for him.</p>
<h2>Trying to Cope</h2>
<p>Here are some things my family and I have been doing and enjoying while trying to survive self-isolation.</p>
<p><strong>Daily Walks</strong> My wife and I try to take the dogs and the baby for a walk each day. Our neighbors have been very good about distancing and it's been nice exchanging hellos with them.</p>
<p><strong>Supporting Local Businesses</strong> Our town has a lot of great, independently-owned shops and restaurants and, despite being sufficiently stocked on food, we have made an effort to support those businesses with carry out orders.</p>
<p><strong>Therapy</strong> If you have health insurance, it's a great time to connect with a therapist on a weekly basis. Our collective anxiety is at peak levels and our therapists could probably use the business.</p>
<p><strong>Video Games</strong> My wife is not a gamer, but I've been enjoying <strong>Animal Crossing: New Horizons</strong> on the Switch. It's a very wholesome and calming game where you build and decorate a house on an island and finance it through aggressive buying and selling of virtual turnips.</p>
<p>I've also been playing a lot of <strong>Nioh 2</strong> on PS4. It's a <a href="https://en.wikipedia.org/wiki/Souls_(series)#Soulslike">Soulslike</a> game set in 16th century Japan and it's extremely challenging. I'll probably have a full write-up of it once I finish it.</p>
<p><strong>Television</strong> My wife and I have been watching a lot of television. When Ryan is awake it's a lot of Sesame Street and Mickey Mouse Clubhouse. After he's asleep, we watched all of S3 of <strong>Ozark</strong> on Netflix. It's a great show but it doesn't do much for our anxiety, as every character is constantly making extremely poor decisions.</p>
<p>We've also been catching up on the latest seasons of <strong>Curb Your Enthusiasm</strong> and <strong>Westworld</strong> and are excited to start S4 of <strong>Insecure</strong>, all on HBO.</p>
<p>I've been enjoying new episodes of <strong>Terrace House</strong> on Netflix. Terrace House is kind of like MTV's The Real World, except the housemates can leave at any time. It creates a constantly evolving dynamic that's highly entertaining. There's also a panel of studio hosts that comment on what's going on in the house. It's great watching people living blissfully unaware of the events that will soon unfold around the world.</p>
<p><strong>Podcasts</strong> My friend Dave and his wife have been doing <a href="https://www.pscp.tv/davechensky/">nightly Coronavirus chats on Periscope</a> and publishing one weekly on Dave's podcast, <a href="https://culturallyrelevantshow.com/">Culturally Relevant</a>.</p>
<p><strong>YouTube Videos</strong> There's so much negativity in the world that when something fun and wholesome comes around it really stands out. I've really been enjoying John Krasinski's <a href="https://www.youtube.com/channel/UCOe_y6KKvS3PdIfb9q9pGug">Some Good News</a>, an overly positive round up of good things that are happening right now with a ton of special guests.</p>
<p><strong>Radiohead</strong> has been posting live concerts on their channel, including <a href="https://youtu.be/gaJKOUQS1T4">this 2000 show in Dublin</a>.</p>
<p>This video on <a href="https://www.youtube.com/watch?v=y8OnoxKotPQ">Microservices</a>, spoofing the over-engineering that happens at large companies, hit a little too close to home.</p>
<p>I loved <a href="https://youtu.be/QGAX7FsOOJE">this episode of Learn with Jason featuring Dan Mall</a> as they talked about creating a design system.</p>
<p>The latest <a href="https://www.youtube.com/watch?v=VJeC0ChCuao">Hot Ones</a> features Justin Timberlake.</p>
<p><a href="https://www.youtube.com/watch?v=RmzjCPQv3y8">Lunch Doodles with Mo Willems</a> is a great daily activity for kids and adults alike.</p>
<p>Finally, here's Tears for Fears' Curt Smith and his daughter <a href="https://www.youtube.com/watch?v=NEpfvTdR5-U">playing an acoustic version of Mad World</a>.</p>
<p>I hope you and your family are doing well and hanging in there. Please feel free to reach out to me if you need someone to talk to (or if your Nook's Cranny is buying turnips for over 400 bells)!</p>
My Year of Film
2020-01-31T00:00:00Z
https://mikeaparicio.com/posts/2020-01-31-my-year-of-film/
<p>I recently received an email from PlayStation detailing my gaming "accomplishments" of 2019. This email laid bare the ridiculous amount of time I spent playing video games on just one of the platforms I play on, PlayStation 4. I'm embarrassed to admit exactly how much time it was. It got me thinking of ways I could better use my time or devote it to other hobbies.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/qqlfBoPeG2-300.webp 300w, https://mikeaparicio.com/images/qqlfBoPeG2-600.webp 600w, https://mikeaparicio.com/images/qqlfBoPeG2-1003.webp 1003w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/qqlfBoPeG2-300.jpeg 300w, https://mikeaparicio.com/images/qqlfBoPeG2-600.jpeg 600w, https://mikeaparicio.com/images/qqlfBoPeG2-1003.jpeg 1003w" sizes="100vw" /><img alt="An embarassing amount of video games played in 2019" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/qqlfBoPeG2-300.jpeg" width="1003" height="532" /></picture>
<figcaption>
Cruel, but fair, PlayStation.
</figcaption>
</figure>
<p>When I posted my annual list of <a href="https://letterboxd.com/peruvianidol/list/favorite-films-of-2019/">favorite movies of the year</a> on Letterboxd, there were a ton of movies that I didn't see which were getting considerable awards buzz, so after the new year I made a concerted effort to catch up. Surprisingly, SIX movies I watched in 2020 ended up on my list of favorite movies of 2019, including the top four.</p>
<p>After a week or so of devouring movies, I noticed I was on track to average one watched per day this year. So I made it a goal (albeit a dumb one): I'm going to attempt to watch 365 films in 2020.</p>
<p>I love <a href="https://letterboxd.com/">Letterboxd</a>. It's an app where you can log, review, and make lists of movies, and connect with other film fans. When I was a kid, I used to collect ticket stubs of all the movies I went to. These days, with online ticketing, ticket stubs aren't as cool or compact as they once were, if you can even get one at all. So Letterboxd became a great way for me to keep track of the movies I watched, as well as the ones I wanted to see, without all the clutter. If you love movies, you should definitely sign up!</p>
<p>Since joining Letterboxd in 2012, the most "films" I've logged in a single year was <a href="https://letterboxd.com/peruvianidol/year/2015/">119 in 2015</a>. So, at the very least, I will break that record this year. A "film" on Letterboxd can also include short films, documentaries, stand-up comedy specials and limited TV series. So for the purposes of this goal, I'll be including those as well. Some days you just don't have time to sit through The Irishman.</p>
<p>After nearly a month into this experiment, I'd love to share some of the highlights I watched in January.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/voP9eq07tm-300.webp 300w, https://mikeaparicio.com/images/voP9eq07tm-600.webp 600w, https://mikeaparicio.com/images/voP9eq07tm-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/voP9eq07tm-300.jpeg 300w, https://mikeaparicio.com/images/voP9eq07tm-600.jpeg 600w, https://mikeaparicio.com/images/voP9eq07tm-800.jpeg 800w" sizes="100vw" /><img alt="Poster for Waves" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/voP9eq07tm-300.jpeg" width="800" height="1185" /></picture>
<figcaption>
My favorite movie of 2019
</figcaption>
</figure>
<p><strong>Waves</strong> This movie blew me away. I wasn't a huge fan of Krisha, and It Comes at Night had its moments, but director Trey Edward Shults knocked it out of the park with Waves. Everything in this movie β the story, the cinematography, the soundtrack, and the performances β combined to make something special. Waves will stay with you long after the credits roll. Hands down my favorite movie of 2019.</p>
<p><strong>Uncut Gems</strong> I've never felt so anxious throughout a film. Adam Sandler is perfectly cast as a charismatic sociopath jeweler addicted to gambling. Uncut Gems delivers the tension of a Game 7 both literally and figuratively. Great supporting cast featuring well-known character actors as well as straight up characters directors Benny and Josh Safdie seemingly pulled off the street. The way they were able to cast Kevin Garnett and incorporate his actual career circa 2012 was pretty remarkable. Between this and Good Time I'm really excited to see what these guys make next.</p>
<p><strong>1917</strong> Spectacular. The illusion of one continuous take makes you feel like you're right there with the characters. You feel exhausted with them as they make their way through miles of trenches and no man's land. It continuously boggles the mind how they were able to block and time each shot with such apparent ease. The scale of the sets and locations they travel through feels overwhelming. There's one sequence that is lit by flares that is like nothing I've ever seen before. Wow.</p>
<p><strong>For Sama</strong> <a href="https://www.youtube.com/watch?v=8jFHbo0Cgu8">This documentary</a> is harrowing, devastating and beautiful all at once. The most I've cried during a movie in ages. It hit me especially hard having lost a daughter and now being the father of a 1-year-old. Waad al-Kateab finds hope amid the constant bombardment of Aleppo. Some extremely graphic scenes make this a tough watch but it really is essential viewing.</p>
<p><strong>Atlantics</strong> Remarkable. Seems pretty conventional until you realize you're watching a completely different genre and it takes off from there. Wholly original storytelling and beautifully directed. This one will stick with me.</p>
<p><strong>I Lost My Body</strong> A beautiful animated feature. Loved the style and the story. Not much more I can say without spoiling it.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/sxFotF1IG3-300.webp 300w, https://mikeaparicio.com/images/sxFotF1IG3-600.webp 600w, https://mikeaparicio.com/images/sxFotF1IG3-1024.webp 1024w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/sxFotF1IG3-300.jpeg 300w, https://mikeaparicio.com/images/sxFotF1IG3-600.jpeg 600w, https://mikeaparicio.com/images/sxFotF1IG3-1024.jpeg 1024w" sizes="100vw" /><img alt="I Lost My Body poster" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/sxFotF1IG3-300.jpeg" width="1024" height="576" /></picture>
<figcaption>
Netflix's Oscar-nominated I Lost My Body
</figcaption>
</figure>
<p><strong>Little Women</strong> Having not read the book or seen previous versions of Little Women, I wasn't sure what to expect. I was blown away by this movie. Greta Gerwig takes a 150-year-old book and breathes new life into it, making it feel modern and fresh. Her decision to not tell the story linearly gives the movie an energetic pace and sets up character beats that might otherwise feel jarring. I loved all the meta scenes with the publisher as well. Great cast all around and great production design and costuming. Florence Pugh, between Midsommar and Little Women, is the actor whose career I'm most excited to see unfold. And Gerwig is proving to be one of the great directors of her time.</p>
<p><strong>Cold Pursuit</strong> Went in expecting a run of the mill Liam Neeson revenge flick but got a darkly funny comedy instead. I had a lot of fun with this one. It plays with the tropes of crime and revenge genres and playfully subverts them. There's <a href="https://vimeo.com/141940661">a great episode of Life's Too Short</a> where Neeson tells Ricky Gervais and Stephen Merchant about his desire to do comedy, without ever dropping a deadly serious expression. In Cold Pursuit, he gets his wish.</p>
<p><strong>Good Boys</strong> Might be the hardest I laughed all year. The three leads have great chemistry and are much more endearing than their constant swearing in the trailer would have you believe. Most of the humor comes from these kids doing and saying adult things that they don't understand, but it also has a lot of heart. It wonderfully captures the fragile friendships of early middle school and the feeling that everything has such epic consequences.</p>
<p><strong>The Before Trilogy</strong> I was 20 when Before Sunrise came out. Watching it again 25 years later was interesting, with years of experience changing my perspective. I had never seen Before Sunset and Before Midnight, which were released 9 and 18 years, respectively, after Before Sunrise. Watching Celine and Jesse age and mature in the span of 24 hours had a different effect, I'm sure, than watching it unfold in near real-time. I certainly found a lot to relate to.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/5x0N_-VA2o-300.webp 300w, https://mikeaparicio.com/images/5x0N_-VA2o-600.webp 600w, https://mikeaparicio.com/images/5x0N_-VA2o-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/5x0N_-VA2o-300.jpeg 300w, https://mikeaparicio.com/images/5x0N_-VA2o-600.jpeg 600w, https://mikeaparicio.com/images/5x0N_-VA2o-800.jpeg 800w" sizes="100vw" /><img alt="Ethan Hawke and Julie Delpy in Before Sunrise" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/5x0N_-VA2o-300.jpeg" width="800" height="363" /></picture>
<figcaption>
1995's Before Sunrise
</figcaption>
</figure>
<p>I'm keeping <a href="https://letterboxd.com/peruvianidol/list/my-year-of-film/">a running list</a> of the movies I've watched this year, if you want to check in on my progress throughout the year. I'll probably write up a recap in December. Let me know if there's any movies you think I should add to my watchlist!</p>
2019
2020-01-01T00:00:00Z
https://mikeaparicio.com/posts/2020-01-01-2019/
<p>Where <a href="https://mikeaparicio.com/posts/2019-01-01-2018/">2018 seemed to last an eternity</a>, 2019 just whizzed on by. It was a pretty good year! Here are some of the highlights:</p>
<figure class="ma-float-center">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/7SCZ6aKRrJ-300.webp 300w, https://mikeaparicio.com/images/7SCZ6aKRrJ-600.webp 600w, https://mikeaparicio.com/images/7SCZ6aKRrJ-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/7SCZ6aKRrJ-300.jpeg 300w, https://mikeaparicio.com/images/7SCZ6aKRrJ-600.jpeg 600w, https://mikeaparicio.com/images/7SCZ6aKRrJ-800.jpeg 800w" sizes="100vw" /><img alt="Cute baby alert" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/7SCZ6aKRrJ-300.jpeg" width="800" height="800" /></picture>
<figcaption>
Ryan
</figcaption>
</figure>
<p><strong>We had a baby!</strong> <a href="https://mikeaparicio.com/posts/2019-02-14-ryan/">Ryan Wyatt Aparicio</a> was born on January 31, 2019. He is just the best. Such a fun, chill baby. Everyone who meets him is amazed how calm he is. And those cheeks. The first thing out of people's mouth is always, "LOOK AT THOSE CHEEKS!"</p>
<p>It's been a crash-course in fatherhood for me and I've loved every minute of it. Allie is a great mom and her experience raising Joe and being a teacher has been invaluable. It's been amazing watching him grow and develop his personality. It's like each week he's a different person. I already miss who he was last week but I'm eager to see what he'll be like the next. (You can find more Ryan pics on my <a href="https://instagram.com/peruvianidol">Instagram</a>.)</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/7Z56H9cKRc-300.webp 300w, https://mikeaparicio.com/images/7Z56H9cKRc-600.webp 600w, https://mikeaparicio.com/images/7Z56H9cKRc-2316.webp 2316w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/7Z56H9cKRc-300.jpeg 300w, https://mikeaparicio.com/images/7Z56H9cKRc-600.jpeg 600w, https://mikeaparicio.com/images/7Z56H9cKRc-2316.jpeg 2316w" sizes="100vw" /><img alt="Scott, Ryan and me" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/7Z56H9cKRc-300.jpeg" width="2316" height="2316" /></picture>
<figcaption>
Meeting Scott for the first time in Dallas
</figcaption>
</figure>
<p><strong>I went to Texas. Twice.</strong> We took the boys to Dallas for a weekend this summer. Joe, a huge baseball fan, wanted to see the Rangers play at Global Life Park, as they'll be playing in a new stadium next season. Allie and I, not being huge baseball fans, took the time to eat. We had some amazing barbecue at <a href="http://pecanlodge.com/">Pecan Lodge</a>. It was probably the best BBQ we've had in our lives. Holy hell. I'd highly recommend it.</p>
<p>I also had the chance to meet my friend Scott and his family in person. Scott and I met playing Destiny and we met up in Dallas for an amazing breakfast.</p>
<p>I also traveled by myself to Austin for <a href="https://artifactconf.com/">Artifact Conference</a>, which was held at the Alamo Drafthouse β a great venue for a conference. I enjoyed all of the talks and even played some basketball with Dan Mall, Brad Frost and a bunch of other people from the conference. It was my first time doing any kind of cardio since my AFib in December 2018 and I was also wearing Chuck Taylor's. Needless to say, it was not my finest performance. I had a lot of fun and it motivated me to at least consider getting back in the gym.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/bqdTwCnueD-300.webp 300w, https://mikeaparicio.com/images/bqdTwCnueD-600.webp 600w, https://mikeaparicio.com/images/bqdTwCnueD-3264.webp 3264w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/bqdTwCnueD-300.jpeg 300w, https://mikeaparicio.com/images/bqdTwCnueD-600.jpeg 600w, https://mikeaparicio.com/images/bqdTwCnueD-3264.jpeg 3264w" sizes="100vw" /><img alt="Buncha sweaty dudes acting hard" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/bqdTwCnueD-300.jpeg" width="3264" height="2448" /></picture>
<figcaption>
Eighth Grade Basketball Champs!
</figcaption>
</figure>
<p>I had some great food in Austin, too. I'd really like to go back to Texas and just eat at a bunch of places. We may not always agree politically, but dammit, you Texans sure make a mean fucking brisket.</p>
<p><strong>We raised over $5,000 for Extra Life.</strong> This year we did our <a href="https://mikeaparicio.com/posts/2019-10-08-extra-life-2019/">sixth Extra Life</a> gaming marathon to raise money for Lurie Children's Hospital in Olivia's honor. We set an ambitious goal of $4,000, which was more than the record we set the previous year. I was skeptical that we would meet our goal but, once again, the generosity of our friends and family, co-workers, and complete strangers completely blew me away. To date, we've raised close to $19,000 to help sick children at Lurie. A huge thank you to those of you who donated!</p>
<p><strong>I gave a talk at University of Illinois.</strong> It was pretty surreal returning to Champaign, where I briefly attended U of I before flunking out and ended up living there for four years anyway. The conference was somewhat small but the talk was well received. Like an idiot <strong>I left my laptop there and didn't realize it until I got home</strong>. Fortunately a kind sponsor drove it back home with them to Chicago and I was able to retrieve it.</p>
<p>On one hand, I'd like to try and pursue more speaking engagements. On the other hand, it requires a lot of preparation and I'm always unsure whether what I have to say on a topic is unique enough to stand out in a crowded field of industry talks.</p>
<h2>Things I loved in 2019</h2>
<h3>Movies</h3>
<p>2019 was not a particularly great year for movies. Many of the best movies I've seen this year came out within the last few months. As usual, I made a <a href="https://letterboxd.com/peruvianidol/list/favorite-films-of-2019/">list of my favorite films of the year on Letterboxd</a>. (There's still at least five 2019 movies that are in theaters that could still crack the list.) Here are a few that left a strong impression on me:</p>
<p><strong>The Last Black Man in San Francisco</strong> A remarkable debut film by director Joe Talbot. It captured me from its opening frame with its truly unique style. Loosely based on the experience of the film's star, Jimmie Fails, as he and his friend Mont try to reclaim Jimmie's childhood Victorian home in gentrified San Francisco. This film stuck with me all year.</p>
<p><strong>Parasite</strong> Director Bong Joon-ho's darkly comedic thriller about a family of grifters insinuating their way into a wealthy family's home is the best of a number of films this year tackling the theme of rich vs. poor. Parasite is a high-wire act, deftly crossing many different genres. Director Bong's finest film to date.</p>
<p><strong>The Lighthouse</strong> This is the most bat-shit insane movie I saw all year. Director Robert Egger's follow-up to The Witch stars Robert Pattinson and Willem Dafoe as two lighthouse keepers slowly going mad on a New England island in the 1890s. Shot in black and white and in an almost square aspect ratio, you can feel the claustrophobia of being trapped with these two characters. Knockout performances from both Pattinson and Dafoe.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/EanM-cvrCD-300.webp 300w, https://mikeaparicio.com/images/EanM-cvrCD-600.webp 600w, https://mikeaparicio.com/images/EanM-cvrCD-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/EanM-cvrCD-300.jpeg 300w, https://mikeaparicio.com/images/EanM-cvrCD-600.jpeg 600w, https://mikeaparicio.com/images/EanM-cvrCD-800.jpeg 800w" sizes="100vw" /><img alt="Robert Pattinson and Willem Dafoe in The Lighthouse" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/EanM-cvrCD-300.jpeg" width="800" height="333" /></picture>
<figcaption>
The cinematography in The Lighthouse is delightful.
</figcaption>
</figure>
<p><strong>The Farewell</strong> I loved this film, written and directed by Lulu Wang, about a family who reunites in China to say goodbye to their dying grandmother, without her knowing that she's dying. The Farewell features a really great ensemble cast, led by Awkwafina. Her character, a Chinese-American writer, struggles to reconcile her American upbringing with her Chinese roots as the family tries to keep their matriarch from learning the truth behind their reunion.</p>
<p><strong>The Art of Self-Defense</strong> This truly bizarre dark comedy from Riley Stearns, stars Jesse Eisenberg as Casey, a milquetoast (I love that word) who signs up for karate classes after being assaulted. Alessandro Nivola plays his sensei, who takes Casey down a dark path. I loved the stilted dialogue of this movie and its twisted commentary on masculinity. I can't imagine another actor other than Eisenberg in this role. One of the more underrated performances of the year.</p>
<p>Honorable Mention: Atlantics, The Peanut Butter Falcon, Midsommar, Dolemite is My Name.</p>
<h3>TV</h3>
<p>It was another great year for television. So many good new shows came out and many old favorites continued to shine. I've already written at length about <a href="https://mikeaparicio.com/posts/2019-06-27-why-i-love-dark/">my love for Netflix's Dark</a>, which remains my favorite show on television. But here are a few more worth checking out:</p>
<p><strong>Chernobyl (HBO)</strong> This limited series was absolutely riveting. Knowing the outcome, if not all of the details, it was absolutely dreadful watching these characters make horrible decision after horrible decision, leading to one of the worst disasters of our time. And the aftermath and government cover-up resonated with our current government's aversion to truth.</p>
<p><strong>Watchmen (HBO)</strong> Though I read the graphic novel and watched 2009 film, I didn't have a deep attachment to Watchmen. This new take on Watchmen, by Lost and The Leftovers co-creator Damon Lindelof, fast-forwards to the present day, where white nationalism has eclipsed the cold war as the defining issue of our time. I loved how they played with time in this show, and how it subverted the superhero genre in various ways. Regina King, Jean Smart and Hong Chau delivered excellent performances in this delightfully female-centric show.</p>
<figure class="ma-float-right">
<p><img src="https://mikeaparicio.com/images/baby-yoda.gif" alt="Baby Yoda sipping from a cup" /></p>
<figcaption>
Baby Yoda is everything
</figcaption>
</figure>
<p><strong>The Mandalorian (Disney+)</strong> A welcome respite from the never-ending Skywalker saga, with not a Death Star in sight. I loved the small scale of this show and its format, a throwback to the wandering hero shows of my childhood, such as The Incredible Hulk and Kung Fu. Every show these days tries to one-up the next with complex, serialized narratives and twists. The Mandalorian is a love letter to a simpler time. Plus, how could you not love Baby Yoda?</p>
<p><strong>The Handmaid's Tale (Hulu)</strong> My wife and I really enjoyed the third season of this dystopian drama. This season got some mixed reviews but we found it to be harrowing and completely riveting. It's pretty amazing the amount of world-building they're able to do on this show with what seems like a pretty limited budget. We're looking forward to seeing how they wrap this story up.</p>
<p><strong>I Think You Should Leave with Tim Robinson (Netflix)</strong> This new sketch comedy show completely blew me away. Every sketch is <em>aggressively</em> funny. The show's characters constantly commit social faux pas and then double-down on their choices in a hopeless attempt to save face.</p>
<figure>
<iframe src="https://www.youtube.com/embed/7xS9Y_mjTjc" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<figcaption>
<em>Instagram</em> from I Think You Should Leave with Tim Robinson
</figcaption>
</figure>
<p><strong>Deadwood: The Movie/El Camino: A Breaking Bad Movie</strong> I had to throw these two movies in the TV section. Who would have thought when these two excellent shows ended that many years later we'd get to revisit the characters, with nearly all of the casts returning? Though neither movie topped the highs of their respective shows, it was such a treat to return to these worlds. I hope more beloved shows follow suit.</p>
<p>Honorable Mention: Barry (HBO), Fleabag (Amazon), Terrace House (Netflix), Big Mouth (Netflix).</p>
<h3>Video Games</h3>
<p>A large chunk of my gaming time was spent, as usual, on Destiny 2 and NBA 2k. But a new game, Slay the Spire, completely sucked me in this year. I wrote about <a href="https://mikeaparicio.com/posts/2019-03-14-why-i-love-slay-the-spire/">how it took over my life during my paternity leave</a>. Here's a few more games that I really enjoyed this year:</p>
<p><strong>NBA 2k20</strong> I have a love/hate relationship with this series. (In fact, I've had a 10,000 word blog post about it sitting in my drafts for months.) This year's edition added a couple of new features that really elevated it from past iterations. First, they revamped their badge system, in which players are assigned tiered (Bronze, Silver, Gold, Hall of Fame) abilities which add to their uniqueness outside of just their statistical ratings.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/2csGulJQA8-300.webp 300w, https://mikeaparicio.com/images/2csGulJQA8-600.webp 600w, https://mikeaparicio.com/images/2csGulJQA8-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/2csGulJQA8-300.jpeg 300w, https://mikeaparicio.com/images/2csGulJQA8-600.jpeg 600w, https://mikeaparicio.com/images/2csGulJQA8-800.jpeg 800w" sizes="100vw" /><img alt="Post-game team shot" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/2csGulJQA8-300.jpeg" width="800" height="450" /></picture>
<figcaption>
Living out my fantasy of being considerably taller and richer and better at basketball.
</figcaption>
</figure>
<p>Second, MyTeam β the card-collecting mode β added Evolution players, where you get a lower rated player (think a rookie Kareem Abdul-Jabbar) and you can increase his ratings and abilities by completing various objectives, like scoring 1,000 points.</p>
<p>These features added a new dimension of replayability and I've had a hard time tearing myself away from NBA 2k long enough to give other games a fair shake, including Destiny 2's latest expansion.</p>
<p><strong>Star Wars Jedi: Fallen Order</strong> This is probably the first Star Wars game I've enjoyed since X-Wing vs. Tie Fighter (1997)! It's basically a mashup of Dark Souls and Uncharted/Tomb Raider, which is right up my alley. I enjoyed the set pieces, puzzles, and combat even if it doesn't quite match the games that inspired it. There's nothing more fun then sending a Stormtrooper flying off a cliff with your Force powers.</p>
<p><strong>Fire Emblem Three Houses</strong> The latest entry in this turn-based combat series took me awhile to get into, but once it finally clicked, I was hooked. One of the unique things about Fire Emblem is how it gets you to care about your soldiers by giving them personalities and having you form bonds between them. You really get to know the characters and become attached to them, making it all the more sad when you get them killed.</p>
<p><strong>Call of Duty: Modern Warfare</strong> I used to love the Call of Duty series until the team that made the original Modern Warfare left to start their own company and made Titanfall (which is amazing). Since then, Call of Duty has been trying to ape Titanfall by moving into the future and incorporating (read: stealing) Titanfall features like wall-running and double jumping. This reboot of Modern Warfare goes back to basics combat-wise and serves up a really compelling campaign.</p>
<p>I only briefly dipped into multiplayer, where the fast kill times and ridiculous kill streaks left me wondering what I ever enjoyed about Call of Duty's PvP. After years of playing Destiny and Battlefield, it just seems dated now.</p>
<p><strong>Resident Evil 2</strong> This reboot of the PlayStation classic was a blast to play. The gameplay mechanics feel clunky by today's standards (and probably did back then, to be honest), but the pacing of the game and the tension it creates are really something special. It looks and feels like a modern game, while delivering all of the scares and fun of the original.</p>
<h3>Podcasts</h3>
<p>I didn't include this section last year, but wanted to highlight a few podcasts I started listening to this year.</p>
<p><strong>The Big Picture</strong> I added a bunch of podcasts from The Ringer to my rotation this year, but The Big Picture is my favorite. Sean Fennessey and Amanda Dobbins discuss new releases and the awards races. Nearly every episode, Sean interviews an actor or director about their experience and process in conversations that I find incredibly fascinating.</p>
<p><strong>The Rewatchables</strong> Each episode, various staff members from The Ringer discuss the merits of a movie they find endlessly re-watchable. There's a big difference between a re-watchable movie and a good movie. Sometimes a movie can be both, but not always. This podcast led me to watch some great movies I hadn't seen (The Talented Mr. Ripley) and some I wish I hadn't seen (Den of Thieves β sorry Daanish).</p>
<p><strong>Culturally Relevant</strong> The latest podcast from prolific podcaster Dave Chen (The Slashfilmcast, Cast of Kings, The Tobolowski Files) features one-on-one interviews with an eclectic range of authors, actors, directors and more. I especially enjoyed his interview with author Jayson Greene, on his book Once More We Saw Stars, in which Jayson writes about the experience of losing his young daughter, which obviously resonated with me. This podcast opened my eyes to new media and new perspectives and I highly recommend it.</p>
<p><strong>Conan O'Brien Needs a Friend</strong> Each week Conan interviews a celebrity guest in hopes of turning their acquaintance into an actual friendship. I really enjoyed getting to know Conan through his interviews, as he shared his insecurities and a darker sense of humor than what you usually see on his show. I also love his rapport with his assistant, Sona, and producer, Matt.</p>
<p><strong>Unspooled</strong> Actor Paul Scheer and film critic Amy Nicholson watch and dissect every movie in the AFI's Top 100 movies of all time. I love Paul and Amy's enthusiasm for film. Their discussions of the merits of each film and whether it deserves its place in the list are great. I tried to keep up with watching the movies but fell behind pretty quickly. Happy to say I've watched 50 of the 100 so far!</p>
<h2>Looking forward to in 2020</h2>
<p><strong>Reconnecting with people.</strong> I feel like as I've gotten older, I've drifted apart from a lot of my friends. Maybe that's just a part of getting older. We all have families now and better shit to do than sit around drinking and shooting the shit. I'd like to at least take a crack and meeting up now and again, getting lunch and catching up with people. It's easy with social media to think we know what's going on in everyone's life and so we don't reach out as much anymore. There's always so much more going on than what we post in our curated online worlds.</p>
<p><strong>Advancing my career.</strong> I wrote about how I was <a href="https://mikeaparicio.com/posts/2019-04-24-whats-next/">feeling a bit restless</a> last year, and I still am. Though I don't think a career change is in the cards, I'd at least like to do more than just building websites. This year I've been working on our design system, which has required a lot more planning, research, and educating than previous years. I'd like to push myself to do more than just what I'm comfortable doing, whether that's at Groupon or someplace else.</p>
<p><strong>Trying to make EVEN BETTER use of my time.</strong> Last year, <a href="https://mikeaparicio.com/posts/2019-01-01-2018/">I wrote about how I wanted to make better use of my time in 2019</a> and, as you can imagine, it didn't quite turn out the way I had planned. I did have a stretch at the beginning of the year where I was taking better care of myself but I slowly fell back into my old, sedentary ways. I'm going to try and get back into that mode with a renewed focus on learning new skills and being healthy.</p>
<p><strong>Blogging more.</strong> I set a goal when I redesigned the blog to write at least one post a month. I started off 2019 strong but my writing really tapered off in the second half of the year. I'd like to try and hit that goal in 2020, with more writing about design systems and the pop culture things I'm loving. Is there something in particular you'd like to see me write about? Let me know!</p>
<p><strong>We're going on a cruise.</strong> My in-laws are celebrating their 50th anniversary next year and so my mother-in-law is taking the whole family on a Disney cruise next summer to celebrate. I've never been on a cruise before and I've heard good things about Disney's cruises, in particular. It should be a fun getaway, even if she forces us all to dress like pirates.</p>
<p><strong>I'm turning 45.</strong> Okay, I'm not really <em>looking forward</em> to this, but it's a thing that is happening. It's pretty disheartening to think that I might have more time behind me than ahead of me but I have a lot to be thankful for and I'm looking forward to what the future holds.</p>
<p><strong>Trump not being President.</strong> This has to happen one way or another, right? I don't even have a strong preference for his replacement right now. I really just want to go back to not having to hear from or about the President on a daily basis. It's just so exhausting.</p>
<p>Thanks for taking the time to read this! I hope you have a great 2020!</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/9PlFHZolZb-300.webp 300w, https://mikeaparicio.com/images/9PlFHZolZb-600.webp 600w, https://mikeaparicio.com/images/9PlFHZolZb-650.webp 650w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/9PlFHZolZb-300.jpeg 300w, https://mikeaparicio.com/images/9PlFHZolZb-600.jpeg 600w, https://mikeaparicio.com/images/9PlFHZolZb-650.jpeg 650w" sizes="100vw" /><img alt="Mike and his family with Santa Claus" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/9PlFHZolZb-300.jpeg" width="650" height="856" /></picture>
<figcaption>
Happy New Year from Mike, Allie, Joe, Ryan, Emily, and Geno
</figcaption>
</figure>
Extra Life 2019
2019-10-08T00:00:00Z
https://mikeaparicio.com/posts/2019-10-08-extra-life-2019/
<p>For the last five years, I've been participating in <a href="https://extra-life.org/">Extra Life</a> to raise money for <a href="https://www.luriechildrens.org/">Lurie Children's Hospital</a> in Chicago. My daughter, <a href="https://mikeaparicio.com/posts/2018-08-26-four-years/">Olivia</a>, was born prematurely around that time and was being treated there. Extra Life was an opportunity to help kids at Lurie while doing something I love β playing video games β for 24 hours straight.</p>
<p>Olivia passed away just days after my first Extra Life marathon. Since then, I've participated each year as a way to honor her memory and each year I'm humbled by the support we've received. My friends Bert and Alan have since joined "Team Olivia," doing the marathon with me and helping to raise funds. Together we've raised $13,830 for Lurie Children's Hospital.</p>
<p>Last year, we blew our previous record away, raising an incredible $3,815. Each year I worry that we won't reach our previous total, but each year old donors and new continue to amaze us with their generosity.</p>
<p>This <strong>November 2nd</strong>, we'll be doing our SIXTH annual Extra Life marathon and would greatly appreciate your support! There are many ways you can help, including:</p>
<ul>
<li><strong>Support our cause by <a href="https://www.extra-life.org/index.cfm?fuseaction=donordrive.participant&participantID=404053">Making a Donation</a>.</strong> Every bit helps!</li>
<li>Join Team Olivia to help us raise funds and play with us on game day. You can visit our <a href="https://www.extra-life.org/index.cfm?fuseaction=donordrive.team&teamID=50937">team page</a> and click the "Join Our Team" button.</li>
<li>Spread the word about our cause. You can link to our team page at <a href="https://extra-life.org/team/olivia">https://extra-life.org/team/olivia</a> or to this blog post, or share/retweet any posts I make about the event.</li>
<li>Tune in to our <a href="https://twitch.tv/peruvianidol">live stream on Twitch</a> on November 2nd. We'll be kicking things off at 8am Central time and gaming for 24 hours straight. Pop into the chat and offer some words of encouragement.</li>
</ul>
<p>Thank you so much for all of your love and support as we continue to keep Olivia's memory alive through helping other sick children!</p>
<p><picture><source type="image/webp" srcset="https://mikeaparicio.com/images/q1FXHHTpdF-300.webp 300w, https://mikeaparicio.com/images/q1FXHHTpdF-600.webp 600w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/q1FXHHTpdF-300.jpeg 300w, https://mikeaparicio.com/images/q1FXHHTpdF-600.jpeg 600w" sizes="100vw" /><img alt="Extra Life 24-hour Marathon - November 2, 2019 at 8 AM Central time" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/q1FXHHTpdF-300.jpeg" width="600" height="338" /></picture></p>
Why I Love Dark
2019-06-27T00:00:00Z
https://mikeaparicio.com/posts/2019-06-27-why-i-love-dark/
<p>Netflix's <strong>Dark</strong>, which recently premiered its second season, answers the important question, "what if <strong>Stranger Things</strong>, but good?"</p>
<p>Just judging by Dark's first season trailer, the German series seems to share a lot in common with its more well known Netflix cousin. They certainly seem to share a lot of of the same DNA: a missing child, a mysterious vibe, a 1980s aesthetic. But where Stranger Things leans on nostalgia and riffs heavily on the works of Steven Spielberg and Stephen King, Dark has a broader range of influences.</p>
<p>Dark tells the story of four families in the small German town of Winden, coming to terms with their past and the secrets that they keep from each other. It's hard to go into any details without spoiling the show, but here are the best things about Dark.</p>
<h2>The Music</h2>
<p>From the opening credits, Dark captures your attention with a series of scenes from the show reflected through a kaleidoscope, set to the haunting song <em>Goodbye</em> by Apparat.</p>
<figure>
<iframe src="https://www.youtube.com/embed/8c399HPb01s" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>
<figcaption>
Dark's opening credits
</figcaption>
</figure>
<p>The original score by Ben Frost really helps set the tone for the show and the soundtrack is one of my favorites in recent years. These songs from the show have found a place in my regular rotation:</p>
<ul>
<li><a href="https://youtu.be/32kYH6XZrIo">Familiar β Agnes Obel</a></li>
<li><a href="https://youtu.be/jWFb5z3kUSQ">Keep the Streets Empty for Me β Fever Ray</a></li>
<li><a href="https://youtu.be/Oqn6yq8lkmg">Me and the Devil β Soap & Skin</a></li>
<li><a href="https://youtu.be/zrdezG6c6HM">Enter One β Sol Seppy</a></li>
<li><a href="https://youtu.be/AxvBm9QSQrE">Wishing Well β Stomper feat. Lucy Tops</a></li>
<li><a href="https://youtu.be/zqTjbassv3g">A Quiet Life β Teho Teardo & Blixa Bargeld</a></li>
<li><a href="https://youtu.be/YT-ECHaz4PE">It's Happening Again β Agnes Obel</a></li>
<li><a href="https://youtu.be/ZAPvZNgPfDE">Melody X β Bonaparte</a></li>
<li><a href="https://youtu.be/NOK_fy6cHGM">The World Retreats β David O'Dowda</a></li>
<li><a href="https://youtu.be/eGcUPpzofA4">May the Angels β Alev Lenz</a></li>
<li><a href="https://youtu.be/RWX0UfxNVeg">Twisted Olive Branch β Asaf Avidan</a></li>
<li><a href="https://youtu.be/Bh1XRH4HrOY">God's Whisper β Raury</a></li>
<li><a href="https://youtu.be/dTZQ2IB_x7c">My Body is a Cage β Peter Gabriel</a></li>
</ul>
<h2>The Cinematography</h2>
<p>This show is just beautiful to look at. The opening credits do a great job of capturing some of the best shots but the composition of nearly every shot is stellar.</p>
<h2>The Characters</h2>
<p>Most shows, particularly in the science fiction genre, are filled with one-note stereotypes. At first glance, some of the characters in Dark might appear to be a certain archetype but reveal themselves to be much deeper as the show progresses.</p>
<h2>The Casting</h2>
<p>Dark's story features characters at different points in their lives and rather than use makeup or digital effects to age/de-age characters, the casting department found actors that look and act remarkably similar. Just take a look at Ulrich, played in various stages of his life by Ludger BΓΆkelmann, Oliver Masucci and Winfried Glatzeder.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/v8wghmrgJf-300.webp 300w, https://mikeaparicio.com/images/v8wghmrgJf-600.webp 600w, https://mikeaparicio.com/images/v8wghmrgJf-750.webp 750w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/v8wghmrgJf-300.jpeg 300w, https://mikeaparicio.com/images/v8wghmrgJf-600.jpeg 600w, https://mikeaparicio.com/images/v8wghmrgJf-750.jpeg 750w" sizes="100vw" /><img alt="Ulrich Neilen, played by three different actors" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/v8wghmrgJf-300.jpeg" width="750" height="240" /></picture>
<figcaption>
The brilliant casting of Dark.
</figcaption>
</figure>
<p>Dark's ensemble is one of the best on television. I hope Dark gives some of these actors more international exposure because many of them are quite good!</p>
<h2>The Mike Seal of Approval</h2>
<p>Showrunners Baran bo Odar and Jantje Friese have created one of the best science fiction shows ever made. The first season was a captivating masterpiece and season two somehow managed to take things up several notches, introducing new characters and new twists, and leaving us hungry for the third and final season, which has already in the works.</p>
<p>If you're a fan of science fiction and character-based drama, you won't find a more entertaining series on television than Dark.</p>
<p>(Do yourself a favor and watch in the original German with English subtitles, rather than the English dub!)</p>
Don't Let Your Engineering Team Bleed Out
2019-05-16T00:00:00Z
https://mikeaparicio.com/posts/2019-05-16-dont-let-your-engineering-team-bleed-out/
<p>Recently, I was tasked with taking a very data-heavy site designed for desktop and making it responsive. I love challenges like this because it gives me the opportunity to show people who think that not every site/app works on mobile that they are wrong. (And what's more fun than showing people they're wrong?)</p>
<p>It also reminded me of the old CSS Zen Garden, since I couldn't update the markup and had to rely on targeting existing classes. This turned out to be somewhat challenging given that it was a React app and for some reason (in my experience, at least), React apps tend to have a ton of nested div elements. It prompted me to make a meme:</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/-dfwvO1Xf8-300.webp 300w, https://mikeaparicio.com/images/-dfwvO1Xf8-500.webp 500w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/-dfwvO1Xf8-300.jpeg 300w, https://mikeaparicio.com/images/-dfwvO1Xf8-500.jpeg 500w" sizes="100vw" /><img alt="(Butterfly man meme) React Devs looking at literally every layer in a Sketch file and asking, is this a div?" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/-dfwvO1Xf8-300.jpeg" width="500" height="500" /></picture>
<figcaption>
Oh, Butterfly Man.
</figcaption>
</figure>
<p>Not being a React expert, I don't know if this is due to the nature of React, lack of HTML knowledge by the developers or a combination of the two. I've talked about my beef with the term "Full-Stack Developer" before and this tweet by Robin Rendle a few weeks ago struck a nerve with me.</p>
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">Hey maybe the reason why accessibility is getting worse and the web is breaking is because folks still think that writing CSS and HTML is βliteβ coding.<br /><br />Hey maybe the way we fix the web is by paying front-end engineers the same as full-stack engineers.</p>— Robin Rendle (@robinrendle) <a href="https://twitter.com/robinrendle/status/1126616315458772992?ref_src=twsrc%5Etfw">May 9, 2019</a></blockquote>
<p>I responded, "It doesn't help that front-end has become a euphemism for JavaScript."</p>
<p>JavaScript has taken over the front end and companies spend a lot of time asking candidates to whiteboard sorting algorithms and very little time asking if they know the difference between an inline element and a block element. As a result, you get a lot of devs that are competent with JS but not so much with HTML/CSS.</p>
<p>The longer this goes on for, the more people you have that are competent at HTML/CSS move on and then you're left with few to no people to vet new candidates for those skills.</p>
<p>As far as I know, I'm the only person left at Groupon with the title of UI Engineer, and I work on the design team, not in engineering. As one of the very few CSS specialists left at the company, I sometimes feel like a combat medic on the beaches of Normandy.</p>
<figure>
<p><img src="https://mikeaparicio.com/images/omaha-beach.gif" alt="A scene from Saving Private Ryan where medics work to save a soldier on Omaha beach." /></p>
<figcaption>
I never noticed the guy on the left gets shot in the canteen and the water turns red.
</figcaption>
</figure>
<p>"Corpsman!" someone will shout out when their app doesn't look like comp, and I'll come running over to patch them up. Meanwhile, other devs will soldier on, missing limbs, bleeding profusely.</p>
<p>"Hey, let me fix you up with a tourniquet or at least give you some morphine," I'll say. But they just continue dragging their mutilated body towards the bunkers, determined to ship their feature on time.</p>
<p>Okay, this metaphor is pretty strained but the point is, you can train a solider to administer a morphine injection or patch up a wound. But there's something to be said for having a trained medic with you in battle.</p>
<p>Similarly, if your site is janky and your designs call for more than what Twitter Bootstrap provides, maybe consider hiring people that are good at HTML/CSS and, if and when you have those people, make sure you take care of them so they'll stick around. Otherwise, like Twitter, you're going to be overrun by Nazis.</p>
What's Next?
2019-04-24T00:00:00Z
https://mikeaparicio.com/posts/2019-04-24-whats-next/
<p>Caring for my infant son has started to get me thinking about what's next in my career. This October will mark my eighth year at Groupon. And as much as friends and family hear me make snarky jokes about the ol' coupon factory, it really has been good to me.</p>
<p>After years of being the lone "web guy" at various small companies, Groupon took a chance on me as a UI engineer. I started out working on a redesign project which took a long time to go nowhere. The mere mention of its code name for many years triggered PTSD in all those involved.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/VBj1eCTfLn-300.webp 300w, https://mikeaparicio.com/images/VBj1eCTfLn-600.webp 600w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/VBj1eCTfLn-300.jpeg 300w, https://mikeaparicio.com/images/VBj1eCTfLn-600.jpeg 600w" sizes="100vw" /><img alt="Groupon anniversary patches" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/VBj1eCTfLn-300.jpeg" width="600" height="600" /></picture>
<figcaption>
A patch for every calendar year I've worked at Groupon.
</figcaption>
</figure>
<p>Just when I was contemplating leaving Groupon after only a few months, an opportunity came up to work on the Internal Tools team, supporting two designers and a half dozen engineering teams. It was there I developed our first CSS framework, Toolstrap, which led to a bunch of similar frameworks for consumer and merchant products.</p>
<p>Along the way, I preached the benefits of responsive design, prototyping, performance, user testing and SVG icons, among other things. Some were met more receptively than others.</p>
<p>I got to work on a lot of fun hackathon projects, produce commercials for two of them β <a href="https://vimeo.com/98705196">Greenscreen</a> and <a href="https://vimeo.com/134432234">GonG</a> β and was even listed as an inventor on several patents.</p>
<p>The thing I always tell new people about Groupon is that it's a place where you can find something you're interested in and make that your thing, and they'll let you run with it. It's a place where you can make your job what you want it to be and not just what was in the job description of what you were hired for.</p>
<p>I've been fortunate to have two of the best managers I've ever had in my entire career at Groupon. Tyler was the first manager I ever had that talked to me about my career beyond Groupon. He suggested all sorts of things that I could do next but I shot them down, saying "I'm just not that ambitious."</p>
<p>Tyler responded, "but your work is ambitious."</p>
<p>That really stuck with me. Tyler taught me to value my own work and constantly went to bat for me to get me compensated fairly for the value I was providing.</p>
<p>My current manager, Matt, really gets me. He knows and appreciates what I bring to the table, even when others don't. When I get frustrated (which is fairly regularly), he's great at helping me articulate why I'm frustrated and helps talk me down from the ledge. We share a similar dark sense of humor and tend to see eye to eye on the things we work on together.</p>
<p>I've also been lucky to have several awesome colleagues as mentors. They really helped me navigate the politics of working at a large company and encouraged me to think beyond my team or the current project I was working on and consider how I could influence the company at a higher level.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/UYseeohJXf-300.webp 300w, https://mikeaparicio.com/images/UYseeohJXf-600.webp 600w, https://mikeaparicio.com/images/UYseeohJXf-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/UYseeohJXf-300.jpeg 300w, https://mikeaparicio.com/images/UYseeohJXf-600.jpeg 600w, https://mikeaparicio.com/images/UYseeohJXf-800.jpeg 800w" sizes="100vw" /><img alt="A group photo from a Design Union offsite" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/UYseeohJXf-300.jpeg" width="800" height="531" /></picture>
<figcaption>
The fun folks of the Groupon Design Union
</figcaption>
</figure>
<p>The people are what's kept me at Groupon for so long. I've met so many great and talented people there. So generous with their time and knowledge and their continual support for <a href="https://mikeaparicio.com/posts/2018-08-26-four-years/">my annual Extra Life marathons</a>. We've shared a lot of laughs at work, outside of work, and at our yearly offsites.</p>
<h2>Sounds great! Why would you leave?</h2>
<p>I'm not looking to leave Groupon but having just turned 44(!), I'm wondering if I want to be making websites for the rest of my life. I look at all of the other career paths I might have taken and realize that it might be a little to late in the game to change careers at this point.</p>
<p>I've reached a point where I'm making a comfortable living doing something that I'm good at and the thought of starting a new thing at the bottom is terrifying.</p>
<p><strong>Video Games</strong> I originally went to school with the intention of making video games for a living. Taking <a href="https://en.wikipedia.org/wiki/Discrete_mathematics">Discrete Mathematical Structures</a> at U of I quickly dissuaded me of that idea.</p>
<p>I'd still love to work on a video game but reading constant articles about the <a href="https://www.polygon.com/2019/4/23/18507750/fortnite-work-crunch-epic-games">insane amount of hours it demands</a> and the <a href="https://kotaku.com/inside-rockstar-games-culture-of-crunch-1829936466">"culture of crunch"</a> associated with the biggest publishers in the industry is a huge turn-off.</p>
<p><strong>Basketball</strong> <a href="https://www.forbes.com/sites/stevensimineri/2019/04/12/vince-carter-after-latest-chapter-with-hawks-hints-towards-historic-22nd-season/#6d3499f2a78b">Vince Carter is still going strong in his 21st NBA season</a> but he's still three years younger than me and is way better at basketball, so I think my chances at a pro career are pretty slim.</p>
<p>After giving up on computer science, I wondered what I could major in that involved no math whatsoever, and sports journalism was the answer. Hey, I thought, I could get paid to watch and write about basketball!</p>
<p>Since then, sports journalism has seen a huge shift from traditional media outlets to <a href="https://awfulannouncing.com/nba/henry-abbott-truehoop-return-newsletter.html">bloggers</a> and <a href="https://www.nba.com/the-starters-podcasts">podcasters</a> becoming mainstream NBA personalities. As much as I used to love writing about hoops, I look at the stuff they're doing over at <a href="https://www.theringer.com/">The Ringer</a> and wonder how I ever did it at all.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/AcTMMwvPkr-300.webp 300w, https://mikeaparicio.com/images/AcTMMwvPkr-566.webp 566w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/AcTMMwvPkr-300.jpeg 300w, https://mikeaparicio.com/images/AcTMMwvPkr-566.jpeg 566w" sizes="100vw" /><img alt="Mark Aparicio diploma" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/AcTMMwvPkr-300.jpeg" width="566" height="540" /></picture>
<figcaption>
Of all the ways you could spell my name wrong.
</figcaption>
</figure>
<p><strong>Comedy</strong> Long before I wanted to make video games, I loved to make people laugh. It was always a dream of mine to be on SNL. As I'd later learn, the road there is difficult and requires so much work and a fair amount of luck.</p>
<p>A lot of SNL people come from Second City, but they don't just pluck you out of the writing or conservatory programs and offer you a spot on the show. You have to get to the main stage just to get noticed, and to do that, you have to get onto the traveling company or go do improv on a cruise ship for a year to even stand a chance at that.</p>
<p>I've got two kids and a mortgage. My wife is not going to let me go Zip Zap Zop on a boat. Are you kidding me?</p>
<p><strong>Movies</strong> I've always loved movies and look for every opportunity to make a <a href="https://vimeo.com/36126385">dumb video</a> using skills I acquired in journalism school and from general messing around behind a camera.</p>
<p>Film is such a cool medium to work in that has room for so many kinds of creativity from acting to cinematography to set design to music. I'd love to really do anything even tangentially related to film, but I have no idea where I'd start.</p>
<p><strong>Peruvian Food</strong> After working in the restaurant industry for four years, I thought it would be cool to one day open my own restaurant. Specifically one that serves Peruvian food.</p>
<p>There used to be a handful of Peruvian restaurants in the Chicago area, but in recent years its popularity has exploded, and now there's at least two handfuls of Peruvian restaurants in Chicago.</p>
<p>Opening a restaurant seems like the riskiest proposition of all of these. Restaurants come and go so quickly, and require a ton of hours of work. Besides that, I can't cook for shit.</p>
<h2>Sounds like a bunch of excuses to me</h2>
<p>Yes, you're absolutely right, voice in my head. A lot of these different things appeal to me but it's highly unlikely I'll make such a drastic career change anytime soon. Things are good right now. I'm comfortable where I'm at. Sure, I'm not curing cancer with internet coupons, but it pays the bills.</p>
<p>I don't know where I'm going with this (which you've probably noticed is a recurring theme around here) but it feels good just to write all this out.</p>
<p>There are lots of things we <em>could</em> be doing or <em>should</em> be doing. Most of the time we're doing exactly what we <em>need</em> to be doing until we find that next thing or until the next thing finds us.</p>
Why I Love Slay the Spire
2019-03-14T00:00:00Z
https://mikeaparicio.com/posts/2019-03-14-why-i-love-slay-the-spire/
<p>I had all sorts of grand plans for how I was going to spend my time productively during my paternity leave, which ended today. I would organize my online photos, work on my slides for an upcoming talk, write a bunch of blog posts and, I dunno, maybe spend time with my wife and newborn son. But all of that went out the window (mostly) when I became hooked on <a href="https://store.steampowered.com/app/646570/Slay_the_Spire/">Slay the Spire</a>.</p>
<p>Slay the Spire has been out since last year in early access on Steam, but I only recently found out about it when it officially launched in January. At its heart, Slay the Spire is a collectible card game similar to Magic: The Gathering or Hearthstone. But rather than going head-to-head with opponents using pre-built decks, Slay the Spire incorporates elements of <a href="https://en.wikipedia.org/wiki/Roguelike">rogue-likes</a> β permadeath and randomness β starting you with a basic deck which you add cards to as you make your way through levels of increasingly difficult enemies.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/eBCKSNrxba-300.webp 300w, https://mikeaparicio.com/images/eBCKSNrxba-600.webp 600w, https://mikeaparicio.com/images/eBCKSNrxba-750.webp 750w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/eBCKSNrxba-300.jpeg 300w, https://mikeaparicio.com/images/eBCKSNrxba-600.jpeg 600w, https://mikeaparicio.com/images/eBCKSNrxba-750.jpeg 750w" sizes="100vw" /><img alt="A screenshot of Slay the Spire" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/eBCKSNrxba-300.jpeg" width="750" height="422" /></picture>
<figcaption>
Taking on the Act 1 boss with The Silent.
</figcaption>
</figure>
<p>There are three characters to choose from, each having their own set of unique cards to build your deck with. The Ironclad is focused on strength-based attacks and skills. The Silent uses blades and poison to stack damage. The Defect summons powerful orbs with passive and active abilities.</p>
<p>Besides your deck, you can also acquire relics, which give you passive or one-time bonuses, potions, which give you single use abilities, and curse cards, which apply negative effects to you when they appear in your hand.</p>
<p>You make your way through a branching path that includes enemy battles, random events, shops, and campfires, where you can choose to rest or upgrade cards. Each of the three acts concludes with a boss encounter that will test the limits of your deck.</p>
<h2>Every game is different</h2>
<p>Because you're building your deck on-the-fly and randomly acquiring relics and potions, you can almost never re-construct the exact combination that led to success in previous runs. This forces you to try new card combinations in hopes of overcoming the most difficult encounters.</p>
<p>Defeating the "final" Act 3 boss unlocks Ascension mode for your character. There are 20 Ascension levels, which add modifiers to the game that increase the difficulty. These include more frequent Elite enemies, stronger enemies and stronger bosses. Each time you win a run, you unlock another Ascension level, adding yet another layer of difficulty.</p>
<p>Winning the game with all three characters gives you the ability to acquire three keys throughout the game. If you collect all three, you unlock a fourth act that concludes with a seemingly impossible boss, which I have yet to beat.</p>
<p>After over 100 hours of play, I've only been able to reach Ascension 4 on all three characters.</p>
<p>For even more variety, there's a daily challenge that adds random modifiers that change your starting cards or give you unique handicaps to overcome using one of the three characters. These can be incredibly fun and incredibly difficult.</p>
<h2>Discovering synergies</h2>
<p>After each battle you're given a choice of three cards to add to your deck. While your first inclination might be to always take a card, many times it's to your advantage to not take any of them. In fact, the game gives you the option in shops and random events to remove cards from your deck since the more cards you have in your deck, the less likely you are to have the card you need in your hand when you need it.</p>
<p>The game is filled with counter-intuitive choices like this that lead you to discovering new synergies β combinations of cards that result in more powerful effects than they would appear to on their own. Some of these synergies are immediately obvious, with cards sharing terms like "shiv", "exhaust", "strength", "focus", etc. But others you will discover can quickly scale your damage or defense to unimaginable levels.</p>
<p>When you discover these synergies, it can be immensely satisfying as you cut through even the toughest boss.</p>
<h2>Incredibly challenging achievements</h2>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/yAFrgAqVDw-300.webp 300w, https://mikeaparicio.com/images/yAFrgAqVDw-600.webp 600w, https://mikeaparicio.com/images/yAFrgAqVDw-750.webp 750w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/yAFrgAqVDw-300.jpeg 300w, https://mikeaparicio.com/images/yAFrgAqVDw-600.jpeg 600w, https://mikeaparicio.com/images/yAFrgAqVDw-750.jpeg 750w" sizes="100vw" /><img alt="A look at the deck and relics used to earn the Minimalist achievement" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/yAFrgAqVDw-300.jpeg" width="750" height="526" /></picture>
<figcaption>
I finally earned the Minimalist achievement for winning with a deck of 5 or fewer cards.
</figcaption>
</figure>
<p>The achievements in Slay the Spire hint at some of these synergies. At first glance some of them seem impossible. For example:</p>
<ul>
<li>Beat a boss in 1 turn</li>
<li>Have 999 Block during combat</li>
<li>Play 25 cards in a single turn</li>
<li>Beat the game with a 5 card deck or smaller</li>
<li>Beat the game in under 20 minutes</li>
</ul>
<p>Many of these require you to find just the right combination of cards that can be cycled indefinitely, which is extremely challenging and requires a good bit of <a href="https://en.wikipedia.org/wiki/Random_number_generation">RNG</a> luck. If you are a gaming masochist like me, Slay the Spire's achievements will really give you a run for your money.</p>
<h2>The Mike Seal of Approval</h2>
<p>Slay the Spire is an incredibly fun, rewarding and addictive game. If you're into CCGs like Magic or Hearthstone, or turn-based strategy games like Into the Breach or Darkest Dungeon, you'll love Slay the Spire.</p>
<p>Slay the Spire is currently available on <a href="https://store.steampowered.com/app/646570/Slay_the_Spire/">Steam</a> for PC/Mac and is in development for Switch and mobile devices, at which point I will likely not get anything done for the rest of time.</p>
Why I Hate Battle Royales
2019-02-18T00:00:00Z
https://mikeaparicio.com/posts/2019-02-18-why-i-hate-battle-royales/
<p>The Battle Royale genre is the latest craze in gaming and I'm pretty sure I hate it. For the uninitiated, in a Battle Royale game, a large number of players (typically 60-100) are dropped onto an island with nothing but their fists. Upon landing, there is a mad scramble to scavenge weapons, armor and equipment in order to survive. A circle contracts the play area, causing fatal damage to players who remain outside of it for too long, forcing players closer together. The number of players quickly dwindles as they kill each other in a variety of ways until just one player or team remains.</p>
<p>If this sounds like The Hunger Games, you're right. If the Hunger Games sounds like a rip-off of the 2000 Japanese cult film, <a href="https://www.youtube.com/watch?v=N0p1t-dC7Ko">Battle Royale</a>, you're also right! If this sounds like a fun game to you, well... it can be. I just don't think it's for me.</p>
<h2>A not-so-brief history of Battle Royales</h2>
<p>The Battle Royale genre was popularized a few years ago as a mod for ARMA 2 called DayZ: Battle Royale. Its creator, Brendan "PlayerUnknown" Greene, went on to make a standalone title called PlayerUnknown's Battlegrounds, also known as PUBG. PUBG became a massive success, in part thanks to its popularity among streamers on <a href="https://www.twitch.tv/">Twitch</a> β a service where people can watch other people play video games and interact with each other in real-time.</p>
<p>Around this time, Epic Games released a survival game called Fortnite, in which players collect resources and build bases to defend against a horde of AI monsters. They noted the success of PUBG and experimented with adding a Battle Royale mode to Fortnite that combined the gunplay of PUBG with the base-building aspect of the original Fortnite.</p>
<p>Fortnite, with it's more playful and cartoonish character design, free-to-play business model and paid customizations such as character/weapon skins and emotes, quickly took off and surpassed PUBG in popularity.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/2ky1U-1HT4-300.webp 300w, https://mikeaparicio.com/images/2ky1U-1HT4-438.webp 438w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/2ky1U-1HT4-300.jpeg 300w, https://mikeaparicio.com/images/2ky1U-1HT4-438.jpeg 438w" sizes="100vw" /><img alt="Tyler 'Ninja' Blevins" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/2ky1U-1HT4-300.jpeg" width="438" height="438" /></picture>
<figcaption>
This kid makes more in a month than your house is worth.
</figcaption>
</figure>
<p>How popular? Well, 27-year-old Tyler Blevins, a.k.a. Ninja, became the top streamer on Twitch and <a href="https://www.businessinsider.com/ninja-tyler-blevins-twitch-subscribers-fortnite-drake-youtube-2018-3">pulls down about $500k/month playing Fortnite</a> almost exclusively. Yes, HALF A MILLION DOLLARS EACH MONTH playing a video game. I clearly made the wrong career choice.</p>
<p>Fortnite's popularity is so far-reaching that <a href="https://www.businessinsider.com/fortnite-coaches-2018-7">parents are hiring coaches</a> to help their kids get better at the game. Colleges are getting into eSports (professional competitive gaming) and <a href="https://techcrunch.com/2018/04/23/a-university-is-giving-scholarships-to-top-fortnite-players/">offering scholarships to Fortnite players</a>. Children are <a href="https://www.thesun.co.uk/news/7240735/fortnite-warning-son-breaks-arm-garden-slide/">jumping off the roofs of their houses</a> with umbrellas in an attempt to replicate the initial jump from a flying bus in Fortnite.</p>
<p><strong>Fortnite is an epidemic.</strong> It's literally being <a href="https://www.usatoday.com/story/life/allthemoms/2018/12/09/fortnite-addiction-sending-kids-gaming-rehab/2221149002/">compared to heroin</a> for its addictive nature.</p>
<p>Epic Games reportedly <a href="https://techcrunch.com/2018/12/27/epic-fortnite-3-billion-profit/">made $3 Billion in 2018</a> just selling cosmetic items in their free-to-play game. (I REALLY made the wrong career choice.) Now investors and executives of game companies are falling over themselves to make their own Battle Royale titles to cash in on their popularity. The latest versions of Call of Duty and Battlefield have Battle Royale modes. Fucking <a href="https://www.theverge.com/2019/2/13/18224020/tetris-99-battle-royale-nintendo-switch-fortnite">TETRIS has a Battle Royale mode</a>. It's out of control.</p>
<h2>Enter Apex Legends</h2>
<p>Less than two weeks ago Respawn Entertainment, a studio that includes some of the original creators of Call of Duty, announced Apex Legends β a new Battle Royale set in their Titanfall universe β and released it the same day. Battle Royale fans (and streamers especially) hungry for a new take on the genre flocked to Apex Legends in droves, quickly making it the most-watched game on Twitch, hitting <a href="https://www.forbes.com/sites/insertcoin/2019/02/12/apex-legends-just-hit-25-million-players-in-a-week-how-on-earth-is-this-happening/#83e4cf312d5a">25 million players in its first week</a>.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/SA5hda81KI-300.webp 300w, https://mikeaparicio.com/images/SA5hda81KI-600.webp 600w, https://mikeaparicio.com/images/SA5hda81KI-750.webp 750w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/SA5hda81KI-300.jpeg 300w, https://mikeaparicio.com/images/SA5hda81KI-600.jpeg 600w, https://mikeaparicio.com/images/SA5hda81KI-750.jpeg 750w" sizes="100vw" /><img alt="Characters from Apex Legends" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/SA5hda81KI-300.jpeg" width="750" height="422" /></picture>
<figcaption>
Characters from Apex Legends pose for a selfie before brutally murdering each other
</figcaption>
</figure>
<p>Apex Legends differs from other Battle Royales by innovating on the genre rather than just copying the success of its predecessors. It incorporates the "hero" concept of shooters like Overwatch, has a smaller player count of 60 players in teams of three, and offers a deep communication system that makes it easy to call out targets and gear and announce your intentions without requiring a headset.</p>
<p><strong>Mike, you're doing that thing again where you open with a premise and then ramble on about something completely different.</strong></p>
<p>Oh yeah, why I hate Battle Royale games.</p>
<h2>Long stretches with no action</h2>
<p>Here's how a match of Fortnite or Apex Legends goes for me compared to how it goes for a top streamer like Ninja.</p>
<table>
<thead>
<tr>
<th>Ninja</th>
<th>Me</th>
</tr>
</thead>
<tbody>
<tr>
<td>Drops into a highly contested, loot-rich location.</td>
<td>Drops into a secluded, loot-poor location.</td>
</tr>
<tr>
<td>Immediately murders 5-10 unsuspecting players before they know what hit them.</td>
<td>Runs around like an idiot hoping to find a weapon to defend himself against people who have limitless time to devote to the game.</td>
</tr>
<tr>
<td>Gets to the middle of the circle and destroys people as they enter.</td>
<td>Gets destroyed by the first player he encounters.</td>
</tr>
<tr>
<td>Wins the match while making more money in 20 minutes than I make in a week.</td>
<td>Sits in the lobby waiting to queue up for more humiliation.</td>
</tr>
</tbody>
</table>
<p>Unless you're highly skilled, you don't want to drop immediately next to other players during the initial scramble for loot. It's entirely possible to spend long stretches of time (5-10 minutes) without even seeing another player. And while this helps ramp up the tension, it doesn't help you get better at gunfights and it doesn't make for particularly compelling gameplay.</p>
<p>If you're playing in a squad and you're downed early, you could potentially spend another 10 minutes spectating your teammates, only for them to die later. And then you're all right back in the lobby waiting, waiting, waiting to do it all over again.</p>
<p>Compare this to a typical shooter where matches last about 10-15 minutes and you're constantly engaged in fights.</p>
<h2>There is a huge luck factor</h2>
<p>While traditional shooters send you into battle with a loadout of your choosing, Battle Royales require you to scavenge for weapons, armor and supplies (healing, etc.). Depending on where you drop, you might luck out and find a top-tier weapon, or you might only find a pistol before someone snipes or shotguns you for a quick kill.</p>
<p>Aside from that, players don't know where the final circle will end up, so there's some luck involved in where the circle contracts in relation to where you land.</p>
<h2>You're competing with teammates</h2>
<p>It's pretty common to "get tilted" as the kids say (that is, to become enraged) by your opponents in shooters. But Battle Royales often get me tilted by my own teammates. Since we land near each other we're often competing to collect from the same small pool of resources, which can become a source of frustration if the loot isn't distributed equitably.</p>
<p>Time is not on your side. Distributing loot is complicated by nearby enemies and the approaching circle of death. There's rarely time to make sure everyone has what they need to be competitive.</p>
<p>There can also be conflicting strategies on what to do moment to moment. The wrong decision can easily get your entire squad wiped out.</p>
<h2>But...</h2>
<p>There's still a lot of fun to be had in Battle Royale games. There is a unique tension that occurs when you get closer and closer to the final few players. There's no other genre of game that gives you the adrenaline rush of a kill or be killed situation. Perhaps the long times between engagements only adds to that.</p>
<p>Apex Legends, in particular, is a fun and unique take on the genre that looks to be the new king for the moment. I've been enjoying my time playing with friends, even though it gets me riled up. And that's really the appeal of these games. They're not just about being the last squad standing. They're about hanging out and having fun.</p>
<p>For kids in this era of helicopter parents, school lockdowns and general paranoia about the safety of our children, games like Fortnite serve as fun, <a href="https://char.gd/blog/2018/fortnite-is-the-new-hangout-spot">safe places where friends can get together</a> and express themselves even if they're not in the same room, or even the same city.</p>
<p>So I guess I'll keep playing them, even though I suck at them.</p>
Ryan
2019-02-14T00:00:00Z
https://mikeaparicio.com/posts/2019-02-14-ryan/
<p>Last year I started blogging again after a four year absence. One of the reasons I was able to start writing again was the fact that my wife, Allie, was pregnant. We kept it pretty quiet given all that we had gone through since losing our daughter, Olivia. If I had my way, we would have dropped the news like a BeyoncΓ© album: hey, we have a new baby coming out, oh, and here he is.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/13-JhKYNpU-300.webp 300w, https://mikeaparicio.com/images/13-JhKYNpU-600.webp 600w, https://mikeaparicio.com/images/13-JhKYNpU-750.webp 750w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/13-JhKYNpU-300.jpeg 300w, https://mikeaparicio.com/images/13-JhKYNpU-600.jpeg 600w, https://mikeaparicio.com/images/13-JhKYNpU-750.jpeg 750w" sizes="100vw" /><img alt="My newborn son, Ryan" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/13-JhKYNpU-300.jpeg" width="750" height="750" /></picture>
<figcaption>
Ryan Wyatt Aparicio Β· born 1/31/19 @ 2:35pm, 6lbs 12oz, 19.5in
</figcaption>
</figure>
<p>Two weeks ago we welcomed our new son, Ryan Wyatt Aparicio, into the world. The last four and a half years have been quite a roller coaster ride, if that roller coaster was just one steep drop that induced long-term depression and anxiety. So when Ryan was born, my wife and I both cried with happiness and relief that we could turn the page on the darkest chapter of our lives.</p>
<p>Ryan has been an absolute blessing. Everything about his birth went as smoothly as we could have expected. And Ryan is delightful. I know I'm genetically programmed to think my baby is cute but, I mean c'mon, look at him! Even the nurses at the hospital, who see dozens of babies each day, were enchanted by Ryan. (Though I'm not sure if this is like a stripper telling you you're handsome, as they are legally obligated to do so, even if you are hideously grotesque.)</p>
<p>Since bringing him home, Ryan has been relatively calm and easy to deal with. He's doing a great job fulfilling his three primary functions: eating, sleeping and pooping. We're so thrilled to have him and to have several weeks to spend together enjoying him and each other's company.</p>
<p>People say having a child is like walking around with your heart on the outside of your body. I found that to be especially true when Olivia was born. When she died, I felt like I also died that day. I had been just going through the motions ever since. But with Ryan, I feel reborn. I'm so excited to get to know him and find out who he'll become. So far, I'm loving every minute of it.</p>
500 Episodes
2019-01-15T00:00:00Z
https://mikeaparicio.com/posts/2019-01-15-500-episodes/
<p>I've been listening to podcasts regularly for over twelve years now, and my favorite one, The Slashfilmcast, just released its 500th episode. I remember tuning in to the very first episode in May of 2008 as they reviewed Indiana Jones and the Kingdom of the Crystal Skull.</p>
<p>Even though the movie was terrible, I really enjoyed the rapport between the hosts, Dave Chen, Devindra Hardawar, Adam Quigley and their guests. Each week I'd tune in to hear them chat about the latest film news, the movies and TV shows they had watched that week and in-depth discussions of new movie releases.</p>
<p>Over time I felt like I got to know the hosts, as I spent about as much time listening to them each week as I did talking to some of my friends and family. Adam left the show at one point and another host, Jeff Cannata, joined the podcast full-time and brought a whole new dynamic to the show.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/UQXBloOoIj-300.webp 300w, https://mikeaparicio.com/images/UQXBloOoIj-600.webp 600w, https://mikeaparicio.com/images/UQXBloOoIj-1024.webp 1024w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/UQXBloOoIj-300.jpeg 300w, https://mikeaparicio.com/images/UQXBloOoIj-600.jpeg 600w, https://mikeaparicio.com/images/UQXBloOoIj-1024.jpeg 1024w" sizes="100vw" /><img alt="An illustration of Jeff, Devindra and Dave, hosts of the Slashfilmcast" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/UQXBloOoIj-300.jpeg" width="1024" height="697" /></picture>
<figcaption>
Credit: Patrick Reynolds
</figcaption>
</figure>
<p>It's been great watching the lives and careers of the hosts (and their many guests) develop over more than ten years. What began as a passion project led to many creative and professional opportunities for the Slashfilmcast crew.</p>
<p>A few years ago, when I was grieving the death of my daughter, I was at an absolute low point in my life. I was watching Dave play The Division on Twitch and was offering him tips in the comments. He invited me to join their party and we started playing pretty regularly. He introduced me to some of his gaming friends and over the past few years we've had a blast together playing games like Rocket League, Destiny, and Fortnite and chatting in Slack.</p>
<p>Being welcomed into the group and having a regular group of friends to game with really lifted my spirits at a time when I needed it most. For that, I will always be grateful.</p>
<p>500 episodes is a remarkable achievement. Podcasts come and go, but the consistency and longevity of the Slashfilmcast is really something to be celebrated. If you're a fan of film, I highly recommend you check it out!</p>
<p>Congrats Dave, Devindra and Jeff! And thanks for providing us with hours of insight and entertainment!</p>
2018
2019-01-01T00:00:00Z
https://mikeaparicio.com/posts/2019-01-01-2018/
<p>As I've gotten older, each year seems to just fly by. 2018, on the other hand seemed like the longest year of my life. Some highlights:</p>
<p><strong>I found out that I'm part Chinese.</strong> I did the 23andMe test and was surprised to learn just <a href="https://you.23andme.com/published/reports/21ae3762571d47498d1aeef1fe7b289b/?share_id=190aaa9c91a0440e">how diverse my genetic makeup is</a>. Besides my broad European ancestry, I'm 20% East Asian and Native American. Half being indigenous Peruvian, I'm assuming, and the other half being a mix of East and Southeast Asian. I'm also ~3% Sub-Saharan African.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/CfWNc1TpWJ-300.webp 300w, https://mikeaparicio.com/images/CfWNc1TpWJ-600.webp 600w, https://mikeaparicio.com/images/CfWNc1TpWJ-879.webp 879w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/CfWNc1TpWJ-300.jpeg 300w, https://mikeaparicio.com/images/CfWNc1TpWJ-600.jpeg 600w, https://mikeaparicio.com/images/CfWNc1TpWJ-879.jpeg 879w" sizes="100vw" /><img alt="Roll Safe pointing meme that says Can't Be Racist if You're All the Races" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/CfWNc1TpWJ-300.jpeg" width="879" height="488" /></picture>
</figure>
<p><strong>I got a toilet seat with a bidet for my 43rd birthday.</strong> This was a game changer. I've decided that you know you've made it when the places you spend most of your time sitting have heated seats β your car, your toilet, your man cave (where I usually have an electric blanket draped over my legs). The bidet is the best of all of them though. <a href="https://washlet.totousa.com/product/c100">Take care of your butt</a> and your butt will take care of you.</p>
<p><strong>Peru played in the World Cup!</strong> After a 36-year drought, La Blanquirroja finally returned to the World Cup. They were eliminated in the group stage, but showed the world they could compete and, if nothing else, that <a href="https://www.dreamteamfc.com/c/2018-world-cup/404668/world-cup-russia-2018-peru-fans/">they have the best fans</a>. This was right up there with the Cubs winning the World Series for me.</p>
<p><strong>I did a workshop with Aaron Draplin.</strong> I attended <a href="https://www.instagram.com/p/BkwDqgmBK9e/">Smashing Conference in Toronto</a>, where I got to do a workshop with one of my favorite designers. He talked us through his process and we worked on making logos based on our initials. It was amazing to see him riff on my design and do all sorts of crazy stuff with it.</p>
<p><strong>My stepson started high school.</strong> Transitioning from middle school to high school can be tough, but Joe has handled it really well so far. On top of getting all A's and B's in his honors classes, Joe started on the freshman football team, after having never played organized football before. He's currently on the freshman basketball team. We're incredibly proud of him.</p>
<p><strong>We remodeled our bedroom.</strong> What started as a routine project quickly became a nightmare. When the contractors removed the drywall, they found the exterior wall of our bedroom was rotted from years of the downspout overflowing onto the outside of the house. So we had to replace an entire corner of the top floor of our house. The end result was worth it though. Our bedroom is now a cozy sanctuary.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/s2le6ZBgk0-300.webp 300w, https://mikeaparicio.com/images/s2le6ZBgk0-600.webp 600w, https://mikeaparicio.com/images/s2le6ZBgk0-808.webp 808w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/s2le6ZBgk0-300.jpeg 300w, https://mikeaparicio.com/images/s2le6ZBgk0-600.jpeg 600w, https://mikeaparicio.com/images/s2le6ZBgk0-808.jpeg 808w" sizes="100vw" /><img alt="The bedroom remodel" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/s2le6ZBgk0-300.jpeg" width="808" height="302" /></picture>
<figcaption>
Before and After
</figcaption>
</figure>
<p><strong>I started my EIGHTH year at Groupon.</strong> This is the longest I've ever been at one job. As much as I complain about things, Groupon has been good to me. They give me a lot of autonomy to work on things that interest me, which this year was our design system. The best part about working at Groupon is the people, though. I'm constantly amazed by the talented folks I work with, who are also incredibly down-to-earth and fun to hang out with.</p>
<p><strong>I helped raise $3,815 for Lurie Children's Hospital.</strong> Our fifth year of <a href="https://www.extra-life.org/index.cfm?fuseaction=donordrive.participant&participantID=348194">Extra Life</a> was a massive success. We beat our record by several hundred dollars and, to date, have raised nearly $14,000 in Olivia's honor. I'm constantly humbled by the generosity of people who support our cause.</p>
<p><strong>I celebrated five years of marriage.</strong> It hasn't been an easy five years, but the one constant has been the love and support of my amazing wife, Allison. We've been through things that would have destroyed many people's marriages, but we find strength in each other and grow closer each year.</p>
<p><strong>I had to have my heart zapped.</strong> I almost made it through 2018 without any more drama, but a few nights before New Years, my heart started beating out of my chest and I felt light-headed and short of breath. According to the Internet, I was dying. So I had Allie take me to the ER where they diagnosed me with AFib and performed a cardioversion to get my heartbeat back in rhythm. So that was fun. I seem to be okay now, but I have a follow-up with a cardiologist in a few weeks.</p>
<h2>Things I loved in 2018</h2>
<h3>Movies</h3>
<p>What a great year for movies. There were so many movies that would have easily cracked my Top 10 any other year. This was the hardest time I've had doing my <a href="https://letterboxd.com/peruvianidol/list/favorite-films-of-2018/">Letterboxd list of favorite films of the year</a>. I won't list them all here, but here's a few lesser seen films I really enjoyed:</p>
<p><strong>Minding the Gap</strong> This amazing documentary from filmmaker Bing Liu follows him and his childhood friends from Rockford, Illinois. It's initially set up like a skateboarding documentary but quickly reveals itself to be so much more. I've never seen a documentary whose subjects are so vulnerable, including the filmmaker himself. The skateboarding shots in this movie are some of the most exhilarating scenes of any movie this year.</p>
<p><strong>Apostle</strong> This movie, from the director of The Raid series, blew me away. I love The Raid and The Raid 2, so I was curious how Gareth Evans style would translate to the horror genre. He did not disappoint. Apostle is over-the-top and suspenseful and star Dan Stevens is excellent as the figuratively and literally tortured protagonist.</p>
<p><strong>Private Life</strong> My wife and I really related to this movie about the struggles of a couple in their 40s trying to conceive. There were so many familiar situations, given levity by Paul Giamatti and Kathryn Hahn, who gives one of her best performances. Writer/Director Tamara Jenkins doesn't follow the typical template for this kind of movie. Like real life, there are setups that don't pay off.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/POJdxwm6Xx-300.webp 300w, https://mikeaparicio.com/images/POJdxwm6Xx-600.webp 600w, https://mikeaparicio.com/images/POJdxwm6Xx-850.webp 850w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/POJdxwm6Xx-300.jpeg 300w, https://mikeaparicio.com/images/POJdxwm6Xx-600.jpeg 600w, https://mikeaparicio.com/images/POJdxwm6Xx-850.jpeg 850w" sizes="100vw" /><img alt="Paddington in prison" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/POJdxwm6Xx-300.jpeg" width="850" height="455" /></picture>
<figcaption>
Paddington, the most famous Peruvian movie star
</figcaption>
</figure>
<p><strong>Paddington 2</strong> I had heard nothing but good things about Paddington 2 all year and finally decided to watch it, despite not having seen the first one. Along with the Mister Roger's documentary, Won't You Be My Neighbor, this movie was a delightful relief from the constant deluge of cynicism we're bombarded with, not just in real life but in a lot of our entertainment. So wholesome and charming. I loved it.</p>
<p><strong>The Rider</strong> I was initially turned off by the cast of non-actors, but The Rider is a such a captivating film. Brady Jandreau is outstanding as a young cowboy grappling with an injury suffered in a rodeo. Chloe Zhao captures some amazing long takes that make this feel like a documentary. The Rider didn't crack my top 10, but it's a movie that I still think about often.</p>
<h3>TV</h3>
<p>There were a ton of great TV shows in 2018. We're in a Golden Age of television right now and there's just too many good shows to watch. Here's a few that were especially good:</p>
<p><strong>Dark (Netflix)</strong> Technically this came out in December of 2017, but I spent all of 2018 thinking about it and imploring people to watch it. This German sci-fi show has strands of X-Files, Stranger Things and Twin Peaks in its DNA and has some of the best cinematography and the best soundtrack of any show I've watched in recent years. It's a real mind trip and the finale blew me away and left me thirsting for season 2.</p>
<figure>
<p><img src="https://mikeaparicio.com/images/teddyperkins.gif" alt="Teddy Perkins from Atlanta" /></p>
<figcaption>
Creepiest character of 2018
</figcaption>
</figure>
<p><strong>Atlanta (FX)</strong> Donald Glover somehow managed to top his incredible first season with a collection of even more surreal and absurd stories. Several episodes were devoted entirely to supporting characters and introduced some extremely memorable new ones.</p>
<p><strong>Insecure (HBO)</strong> Issa Rae, the show's co-creator and star, is amazingly talented both on and off-screen. Surrounded by a great ensemble cast, she deftly balances comedy and drama amidst a backdrop of Los Angeles that feels like no other L.A. show or movie.</p>
<p><strong>The Good Place (NBC)</strong> The initial premise of this show doesn't seem like much, but The Good Place keeps finding ways to reinvent itself, surprising its audience at each turn. Another great ensemble show, including one of Ted Danson's best performances. D'Arcy Carden is delightful as Janet, particularly one episode this season where she played all four lead roles.</p>
<p><strong>Barry (HBO)</strong> This dark comedy is exquisitely shot and features Bill Hader as an assassin trying to pivot his career into acting. Henry Winkler is fantastic as his acting teacher and Anthony Carrigan steals every scene he's in and adds much needed levity to the darkness.</p>
<p>Honorable Mention: Terrace House (Netflix), Queer Eye (Netflix), America to Me (Starz), Ozark (Netflix).</p>
<h3>Video Games</h3>
<p>I spend entirely too much time playing video games. There were some big titles this year that I just didn't get into, like God of War and Spider-Man. Mostly because I find myself going back to the same handful of games over and over. Here's a few that really grabbed me:</p>
<p><strong>Destiny 2</strong> Originally released in 2017, Destiny 2 started out strong but sacrificed a lot of what made Destiny 1 great in order to appeal to a broader audience. After an uninspired first DLC, Curse of Osiris, Destiny took a back seat to more interesting games. But its developer, Bungie, incorporated the feedback of its hardcore fans with the next DLC, Warmind, followed shortly by a full expansion, Forsaken. Destiny is now as good as it's ever been and its tight shooter mechanics and addictive gameplay loop has me going back week after week.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/6pXmZm2wWT-300.webp 300w, https://mikeaparicio.com/images/6pXmZm2wWT-600.webp 600w, https://mikeaparicio.com/images/6pXmZm2wWT-960.webp 960w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/6pXmZm2wWT-300.jpeg 300w, https://mikeaparicio.com/images/6pXmZm2wWT-600.jpeg 600w, https://mikeaparicio.com/images/6pXmZm2wWT-960.jpeg 960w" sizes="100vw" /><img alt="Chilling on the range on horseback" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/6pXmZm2wWT-300.jpeg" width="960" height="540" /></picture>
<figcaption>
Sometimes a man just needs to ponder life on the range.
</figcaption>
</figure>
<p><strong>Red Dead Redemption 2</strong> The long awaited follow-up to 2010's Red Dead Redemption is actually a prequel. It follows a similar template as other Rockstar titles like Grand Theft Auto, and suffers from a lot of the same issues. But ultimately this game creates an incredible interactive sandbox to play in and is rich with characters and narrative in ways that most games don't live up to. The story drags in places but the conclusion was extremely satisfying.</p>
<p><strong>Dead Cells</strong> A mash-up of Castlevania, Rogue Legacy and Dark Souls, Dead Cells is a rogue-like action platformer where you find success through trial and error. Along the way you unlock interesting weapons and abilities. I still haven't beaten it, but this is a game I keep going back to.</p>
<p><strong>Guacamelee 2</strong> Another Metroidvania game infused with rich characters, colorful backdrops and humorous references, Guacamelee 2 is a great follow-up to the original. If you enjoy Metroidvania-style games, this is definitely one worth checking out.</p>
<p><strong>Alto's Odyssey</strong> I had a lot of fun with this follow-up to the mobile game, Alto's Adventure. An endless runner-type game, Alto's Odyssey has you sandboarding through gorgeous environments, doing various flips and tricks and avoiding obstacles. It's a great game to pick up during some downtime and just get into a zen state and chill.</p>
<p>Honorable Mention: NBA 2k19, Hitman 2, Into the Breach, Far Cry 5.</p>
<h2>Looking forward to in 2019</h2>
<p><strong>We're having a baby.</strong> Okay, I buried the lede. After four years of trying, we're finally having a baby at the end of January. Given everything that happened with Olivia and everything in between, we decided to keep it on the down low for most of the pregnancy. It's been an anxious few months but we're getting more and more excited with each day that passes.</p>
<p><strong>Trying to make better use of my time.</strong> With a baby on the way and my recent heart diagnosis, I've realized I need to start making some lifestyle changes. Less vegging out, less staying up late, less trying to keep up with my Twitter feed, less caffeine and sugar. More reading, more leaving the house, more exercise, more learning new skills. To do all of that I need to manage my time better. I was <a href="http://bradfrost.com/blog/post/deep-work-update-2/">inspired by Brad Frost</a> to start scheduling my days starting this year. We'll see how that goes!</p>
<p><strong>I'm speaking at my first conference.</strong> I've been doing small talks at Groupon and local meetups over the past few years, but I decided it was finally time to submit a talk to an actual conference. <a href="http://webcon.illinois.edu/index.shtml">University of Illinois' WebCon</a> seemed like a good start, and luckily they accepted my proposal. So this April I'll be doing a talk called Lessons From the Coupon Factory: Design Systems at Scale. I'm looking forward to getting some more speaking experience under my belt and submitting to a few other conferences this year.</p>
<p>If you made it through this entire article, I salute you! Thanks for taking the time and sticking with me. Best of luck to you in the year ahead!</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/NQJNjJFivw-300.webp 300w, https://mikeaparicio.com/images/NQJNjJFivw-600.webp 600w, https://mikeaparicio.com/images/NQJNjJFivw-619.webp 619w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/NQJNjJFivw-300.jpeg 300w, https://mikeaparicio.com/images/NQJNjJFivw-600.jpeg 600w, https://mikeaparicio.com/images/NQJNjJFivw-619.jpeg 619w" sizes="100vw" /><img alt="A photo of Mike's family with Santa and Mrs. Claus" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/NQJNjJFivw-300.jpeg" width="619" height="619" /></picture>
<figcaption>
Happy New Year from Mike, Allie, Joe, Geno, Emily and ?
</figcaption>
</figure>
Should Painters Sculpt?
2018-10-17T00:00:00Z
https://mikeaparicio.com/posts/2018-10-17-should-painters-sculpt/
<p>I've spent the last month stressing over what to write here. Would it be another four years before I wrote another post? Should I write about how obsessed I've been with Destiny lately? My love/hate relationship with NBA 2k? Something about the Bulls? "Oh, I know - HOW ABOUT NOTHING?," my brain responds.</p>
<p>But then this tweet yesterday inspired me.</p>
<blockquote class="twitter-tweet" data-theme="dark"><p lang="en" dir="ltr">I shared some principles behind my process:<br />1. Words, not wireframes<br />2. Skip wireframe, sketch mobile UI<br />3. Shift point of production downstream<br />4. Code commits, not redlines<br />5. Cultivate trust outside documentation<br />6. The product is the common workspace<br /><a href="https://t.co/a5og9Chy1A">https://t.co/a5og9Chy1A</a></p>— Josh Clark (@bigmediumjosh) <a href="https://twitter.com/bigmediumjosh/status/1052256117575815168?ref_src=twsrc%5Etfw">October 16, 2018</a></blockquote>
<p>One of the things that has puzzled me since moving from a one-man web team to a big company with dozens of designers and hundreds of developers is how little overlap there is in skills. I could probably do an hour talk just on this subject alone.</p>
<p>But basically (and I have found this problem is not unique to Groupon) you have design hiring for visual design skills and engineering hiring for computer science skills. Designers have their portfolio rigorously dissected while engineers run a gauntlet of whiteboard interviews and live coding exercises in which they attempt to write a program to make change from a given number or some such bullshit they will never actually have to do on the job. As a result, people whose skills lie somewhere in the middle tend to get weeded out.</p>
<p>Despite HTML and CSS typically being one of the prerequisites for a design OR engineering position, and all the emphasis on "<a href="https://mikeaparicio.com/images/fullstackdeveloper.gif">full-stack developers</a>" (hoo boy, don't even get me started), often times if you get someone who is exceptionally skilled at HTML and CSS, it's by dumb luck. I wish I had a dollar for every candidate I interviewed who, when asked "what is your experience with CSS?" responds simply, "oh, I just use Bootstrap."</p>
<p>And when you're not thoroughly vetting people for certain skills, you end up not having people with those skills to vet other people for those skills and the problem perpetuates itself.</p>
<p><em>Yes, but Mike, what the hell does this have to do with the tweet you mentioned?</em></p>
<p>Huh? What? Oh yeah.</p>
<p>In his article, "<a href="https://bigmedium.com/ideas/only-one-deliverable-matters.html">Only One Deliverable Matters</a>", Josh Clark writes:</p>
<blockquote>
<p>Too many designers get precious about those documentsβI know Iβve been guilty of it. Somewhere along the way, detailed wireframes, high-fidelity comps, and motion prototypes all got enshrined as critical deliverables. Those design artifacts are unimportant. <strong>Only one deliverable matters: the product itself. Everything else gets thrown away when you ship.</strong></p>
</blockquote>
<p>When I started at Groupon seven years ago, we were delivering Photoshop files to engineering with "redlines" indicating that this should be this size and that should be such-and-such color. We've since moved on to exporting Sketch files to Zeplin, but at the end of the day we're still delivering pictures of websites. (Maybe you're using something like InVision and delivering movies of websites!)</p>
<p>I've always equated this to a painter toiling away for hours on a piece before handing it off to a sculptor and saying, "make me a statue of this."</p>
<p>The sculptor looks at the painting and is like, "How big is this supposed to be? What does the back of this thing look like? How am I supposed to sculpt the sky?" before going to <a href="https://www.reddit.com/r/sculpting/">reddit.com/r/sculpting</a> to post a snarky meme about painters.</p>
<p>As a result, the finished product tends to look a bit... off. Maybe it's due to your process or your hiring practices. If you give a picture of a website to 10 different developers you're going to get 10 different websites.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/NWFhcZGWra-300.webp 300w, https://mikeaparicio.com/images/NWFhcZGWra-600.webp 600w, https://mikeaparicio.com/images/NWFhcZGWra-1200.webp 1200w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/NWFhcZGWra-300.jpeg 300w, https://mikeaparicio.com/images/NWFhcZGWra-600.jpeg 600w, https://mikeaparicio.com/images/NWFhcZGWra-1200.jpeg 1200w" sizes="100vw" /><img alt="Photo of Ronaldo and a bust of him that looks horribly disfigured" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/NWFhcZGWra-300.jpeg" width="1200" height="675" /></picture>
<figcaption>
Mmmm... not quite.
</figcaption>
</figure>
<p>The jist of Josh's article is: what a colossal waste of fucking time and resources this is! (Before detailing a process for avoiding such waste.)</p>
<p>This conversation always seems to come down to:</p>
<blockquote class="twitter-tweet" data-conversation="none" data-theme="dark"><p lang="en" dir="ltr">ββββββ<br />ββββββ<br />ββββββ<br />ββββββοΌΌβοΌ<br />ββββββ / SHOULD<br />ββββββγ)<br />ββββββ DESIGNERS<br />ββββββ<br />ββββββ CODE?<br />ββββββ<br />ββββββ<br />ββββββ<br />ββββββ<br />ββββββ</p>— Mike Aparicio (@peruvianidol) <a href="https://twitter.com/peruvianidol/status/1052576483166818304?ref_src=twsrc%5Etfw">October 17, 2018</a></blockquote>
<p><em>Oh no. This whole article was basically the design/dev equivalent of a Rickroll.</em></p>
<p>Sorry. :(</p>
<p>Should a painter sculpt? Not necessarily. But at the very least, they should understand the constraints of the medium they're designing for. Should a general contractor know how to hang drywall? I suppose, if they want to earn more business. Should a podiatrist know what a liver is? Geez, I would hope so.</p>
<p>Anyway, this is all to say that this topic was stewing in my brain all night and I woke up energized. I've been working on a talk about lessons learned from building a design system at Groupon, but I realized that for many people this isn't applicable. They are working on a smaller scale and wonder if they even need a design system. (The answer is yes. Yes you do.)</p>
<p>So I'm going to start a series here about creating a design system for any size team, including a team of one. Look forward to the first part of that series soon!</p>
Driving Your Design System with Tokens
2018-09-07T00:00:00Z
https://mikeaparicio.com/posts/2018-09-07-driving-your-design-system-with-tokens/
<p>Working on a design system at a large company, I've noticed that depending on who you ask, they think the design system is something different. It's like the parable of the blind men and the elephant.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/khLYNB_c5I-300.webp 300w, https://mikeaparicio.com/images/khLYNB_c5I-600.webp 600w, https://mikeaparicio.com/images/khLYNB_c5I-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/khLYNB_c5I-300.jpeg 300w, https://mikeaparicio.com/images/khLYNB_c5I-600.jpeg 600w, https://mikeaparicio.com/images/khLYNB_c5I-800.jpeg 800w" sizes="100vw" /><img alt="Several blind monks feeling up an elephant" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/khLYNB_c5I-300.jpeg" width="800" height="545" /></picture>
<figcaption>
Source: Wikipedia
</figcaption>
</figure>
<p>If you ask a designer, they'll say, "the design system is the UI kit!"</p>
<p>If you ask a developer, they'll say, "the design system is the component library!"</p>
<p>If you ask a third person, they'll say, "we have a design system?!"</p>
<p>All of those are valid answers. Ok, maybe if people aren't aware that you have a design system, you have some work to do.</p>
<p>A design system has a number of parts built for different audiences: a UI kit with Sketch symbols for designers, a React component library and/or a CSS framework for developers, a documentation site for everyone, an icon library, etc. But how do we keep all of those things in sync? Especially when you have a rag tag group of full- and part-time team members of varying disciplines working on the system?</p>
<h2>Design Decisions</h2>
<p>In a large company, where many small teams are responsible for designing and developing individual features across platforms, our design decisions can become muddled pretty easily. We try to achieve consistency by creating tools for designers and developers, like the UI kit and CSS framework, but these are all separate implementations of those decisions.</p>
<p>What ends up happening is that the design tools and the dev tools inevitably fall out of sync and teams are left to implement features independently, and with varying degrees of success. With a focus on delivering new features, these implementations often don't get baked back into the tools for other teams to take advantage of.</p>
<p>To further complicate things, there are likely different frameworks for each platform to maintain or, in some cases, no framework at all. In which case developers might be making things like buttons from scratch every. single. time.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/Vq_cMyCXfQ-300.webp 300w, https://mikeaparicio.com/images/Vq_cMyCXfQ-600.webp 600w, https://mikeaparicio.com/images/Vq_cMyCXfQ-3056.webp 3056w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/Vq_cMyCXfQ-300.jpeg 300w, https://mikeaparicio.com/images/Vq_cMyCXfQ-600.jpeg 600w, https://mikeaparicio.com/images/Vq_cMyCXfQ-3056.jpeg 3056w" sizes="100vw" /><img alt="Illustration of design decisions with arrows pointing to various products and platforms" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/Vq_cMyCXfQ-300.jpeg" width="3056" height="1714" /></picture>
<figcaption>
Our design decisions permeate all of our products separately, leading to inconsistencies.
</figcaption>
</figure>
<h2>Design Tokens</h2>
<p>Design Tokens are a tech-agnostic method of storing design decisions in key/value pairs that can be exported to a different formats based on platform (web, iOS, Android). They give us a shared vocabulary for describing visual properties that translate across platforms. Each platform might use different values to express color but when we say <code>$color-green</code>, we're all talking about the same thing.</p>
<p><em>So, variables basically?</em></p>
<p>Exactly. A lot of developers use variables to store values like their color palette or type scale. Design Tokens are like variables on steroids.</p>
<p>In his article <em><a href="https://medium.com/eightshapes-llc/tokens-in-design-systems-25dd82d58421">Tokens in Design Systems</a></em>, Nathan Curtis separates these variable types into two categories: <strong>options</strong> and <strong>decisions</strong>.</p>
<p><strong>Options</strong> represent all of the distinct values available in the design system. Rather than letting designers and developers choose arbitrary values for things like type size and color, we can limit those options to a logical and manageable number so that we don't end up with 50 different gray values in production.</p>
<figure>
<pre class="language-scss"><code class="language-scss"><span class="token comment">/* GROUPON */</span><br /><span class="token variable">$color-green</span> = #53A318<br /><br /><span class="token comment">/* LIVING SOCIAL */</span><br /><span class="token variable">$color-blue</span> = #0088CC<br /><span class="token variable">$color-purple</span> = #544AA1<br /><span class="token variable">$color-orange</span> = #F0812B</code></pre>
<figcaption>
Options describe the individual values available in the design system.
</figcaption>
</figure>
<p><strong>Decisions</strong> represent the contexts in which things like color, type, and spacing are utilized. At Groupon, which acquired Living Social, we not only have to support different platforms but also different brands across those platforms. So, while Groupon uses the same green color for brand elements like the header background, primary button and pricing text, Living Social uses different colors for all three. We can define these decisions in our design tokens.</p>
<figure>
<pre class="language-scss"><code class="language-scss"><span class="token comment">/* GROUPON */</span><br /><span class="token variable">$color-brand</span> = <span class="token variable">$color-green</span><br /><span class="token variable">$color-button-primary</span> = <span class="token variable">$color-green</span><br /><span class="token variable">$color-price</span> = <span class="token variable">$color-green</span><br /><br /><span class="token comment">/* LIVING SOCIAL */</span><br /><span class="token variable">$color-brand</span> = <span class="token variable">$color-purple</span><br /><span class="token variable">$color-button-primary</span> = <span class="token variable">$color-blue</span><br /><span class="token variable">$color-price</span> = <span class="token variable">$color-orange</span></code></pre>
<figcaption>
Decisions describe the contexts in which options are used.
</figcaption>
</figure>
<p>Notice that the values here refer to other tokens, which would be defined within the <strong>options</strong>.</p>
<h2>Subatomic Design</h2>
<p>In his book, <em><a href="http://atomicdesign.bradfrost.com/">Atomic Design</a></em>, Brad Frost introduced a methodology for breaking design patterns into a logical hierarchy. Atoms, the smallest unit, represent the fundamental building blocks of our design system. In a sense, design tokens are like subatomic particles.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/JhsGek6iZM-300.webp 300w, https://mikeaparicio.com/images/JhsGek6iZM-600.webp 600w, https://mikeaparicio.com/images/JhsGek6iZM-800.webp 800w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/JhsGek6iZM-300.jpeg 300w, https://mikeaparicio.com/images/JhsGek6iZM-600.jpeg 600w, https://mikeaparicio.com/images/JhsGek6iZM-800.jpeg 800w" sizes="100vw" /><img alt="An unapologetic riff on Brad Frost's Atomic Design - Subatomic Design" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/JhsGek6iZM-300.jpeg" width="800" height="198" /></picture>
<figcaption>
Subatomic Design - The 7 Minute Abs of Design Systems (apologies to Brad Frost)
</figcaption>
</figure>
<p>A heading, for example, is made up of a number of property/value pairs: typeface, size, line height, font weight, color, margin, etc. We can apply token values to all of those properties.</p>
<figure>
<pre class="language-scss"><code class="language-scss"><span class="token selector">.header-page-title </span><span class="token punctuation">{</span><br /> <span class="token property">font-family</span><span class="token punctuation">:</span> <span class="token variable">$font-family-heading</span><span class="token punctuation">;</span><br /> <span class="token property">font-size</span><span class="token punctuation">:</span> <span class="token variable">$font-size-heading-large</span><span class="token punctuation">;</span><br /> <span class="token property">line-height</span><span class="token punctuation">:</span> <span class="token variable">$line-height-heading-large</span><span class="token punctuation">;</span><br /> <span class="token property">font-weight</span><span class="token punctuation">:</span> <span class="token variable">$font-weight-heading-large</span><span class="token punctuation">;</span><br /> <span class="token property">color</span><span class="token punctuation">:</span> <span class="token variable">$color-heading</span><span class="token punctuation">;</span><br /> <span class="token property">margin</span><span class="token punctuation">:</span> <span class="token variable">$margin-heading-large</span><span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<figcaption>
Replacing hard-coded values with tokens.
</figcaption>
</figure>
<p>Notice that rather than using options like <code>$color-black</code> or <code>$spacing-medium</code>, we're applying decisions in a context specific to headings. This way, if we ever want to change the font weight of <code>.header-page-title</code> globally, for example, we can do so easily without having to search our entire codebase for every instance of a header and changing <code>$font-weight-bold</code> to <code>$font-weight-light</code>.</p>
<h2>Tokens Across Platforms</h2>
<p>The real power of tokens comes when we use them to apply design decisions across platforms. By storing the token data in YAML, we can easily convert that data to the appropriate format to be consumed by web (preprocessor variables), iOS (JSON), and Android (XML). It might even be possible to power our design tools with tokens.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/jBvDdf_XOw-300.webp 300w, https://mikeaparicio.com/images/jBvDdf_XOw-600.webp 600w, https://mikeaparicio.com/images/jBvDdf_XOw-2560.webp 2560w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/jBvDdf_XOw-300.jpeg 300w, https://mikeaparicio.com/images/jBvDdf_XOw-600.jpeg 600w, https://mikeaparicio.com/images/jBvDdf_XOw-2560.jpeg 2560w" sizes="100vw" /><img alt="An illustration of tokens powering all of our products and platforms" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/jBvDdf_XOw-300.jpeg" width="2560" height="1438" /></picture>
<figcaption>
Tokens can power all of our products and platforms.
</figcaption>
</figure>
<p>Storing our token data in YAML also allows for differences that might be necessary between platforms. Colors, for example, are typically defined in 6-digit hex on web, RGBA on iOS, and 8-digit hex on Android. We can define these separately and then omit the platform segment when the tokens are converted to each platform's format.</p>
<figure>
<pre class="language-scss"><code class="language-scss"><span class="token property">color</span> <span class="token punctuation">:</span><br /> <span class="token property">green</span> <span class="token punctuation">:</span><br /> <span class="token property">web</span> <span class="token punctuation">:</span> &color-green-web <span class="token string">"#53A318"</span><br /> <span class="token property">ios</span> <span class="token punctuation">:</span> &color-green-ios <span class="token string">"0.33,0.64,0.09,1"</span><br /> <span class="token property">and</span> <span class="token punctuation">:</span> &color-green-and <span class="token string">"#FF53A318"</span><br /> <span class="token property">blue</span> <span class="token punctuation">:</span><br /> <span class="token property">web</span> <span class="token punctuation">:</span> &color-blue-web <span class="token string">"#0081E3"</span><br /> <span class="token property">ios</span> <span class="token punctuation">:</span> &color-blue-ios <span class="token string">"0,0.51,0.36,1"</span><br /> <span class="token property">and</span> <span class="token punctuation">:</span> &color-blue-and <span class="token string">"#FF0081E3"</span><br /> <span class="token property">red</span> <span class="token punctuation">:</span><br /> <span class="token property">web</span> <span class="token punctuation">:</span> &color-red-web <span class="token string">"#FC0048"</span><br /> <span class="token property">ios</span> <span class="token punctuation">:</span> &color-red-ios <span class="token string">"0.99,0,0.28,1"</span><br /> <span class="token property">and</span> <span class="token punctuation">:</span> &color-red-and <span class="token string">"#FFFC0048"</span></code></pre>
<figcaption>
Accommodating platform differences in tokens.
</figcaption>
</figure>
<h2>The Single Source of Truth</h2>
<p>Designers and developers are always looking for the mythical "Single Source of Truth" in which all of their decisions are editable in one place and propagate everywhere. We make tools like our Sketch UI kit and CSS frameworks in hopes that they will serve as such but over time they tend to fall short.</p>
<p>Design Tokens are extremely powerful, not to mention resilient. What happens with our UI kit when Sketch is no longer the hot new design tool? Or when our React component library is made obsolete by the next JavaScript framework? (SPOILER ALERT: It will be.) Design Tokens allow us to adapt to new tools without having to re-implement everything from scratch.</p>
<p>When you ask the blind men what the design system is, perhaps they'll all answer "Design Tokens."</p>
Four Years
2018-08-26T00:00:00Z
https://mikeaparicio.com/posts/2018-08-26-four-years/
<p>Hey there. It's been awhile. Almost four years, to be exact.</p>
<p>I've wanted to write you for some time but I couldn't bring myself to do it until now. It felt awkward to just resume writing after so much time away without addressing the elephant in the room.</p>
<h2>Olivia</h2>
<p>Four years ago today, my daughter Olivia was born. It should have been a happy occasion, only she wasn't due until mid-December.</p>
<p>My wife, Allie, woke up in the middle of the night a few nights earlier. She was bleeding. We rushed to the hospital. It turned out that she had a placental abruption. Olivia had been gestating for just under 24 weeks.</p>
<p>At 24 weeks to the day, Olivia was delivered via c-section. She was just 1 lb. 4 oz., but she was alive. She was rushed to the NICU.</p>
<p>The next nine and a half weeks were hell.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/PMJXfCPJTm-300.webp 300w, https://mikeaparicio.com/images/PMJXfCPJTm-600.webp 600w, https://mikeaparicio.com/images/PMJXfCPJTm-750.webp 750w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/PMJXfCPJTm-300.jpeg 300w, https://mikeaparicio.com/images/PMJXfCPJTm-600.jpeg 600w, https://mikeaparicio.com/images/PMJXfCPJTm-750.jpeg 750w" sizes="100vw" /><img alt="Olivia's tiny foot" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/PMJXfCPJTm-300.jpeg" width="750" height="500" /></picture>
</figure>
<p>Olivia struggled with a lot of issues related to her prematurity which required several surgeries. On top of that, we found out my wife and I are carriers for an extremely rare condition known as <a href="https://en.wikipedia.org/wiki/Congenital_amegakaryocytic_thrombocytopenia">Congenital Amegakaryocytic Thrombocytopenia</a> (CAMT), which was passed onto Olivia. This condition resulted in extremely low platelet count and required Olivia to receive regular blood transfusions. It made an already tenuous situation exponentially more complicated.</p>
<p>Ultimately it was too much for Olivia. I held her in my arms as she passed away on October 31, 2014.</p>
<p>The grief was unbearable. It still is. I'm just better at faking being a normal human being now. All of those Second City classes really paid off! It's really hard to care about dumb shit anymore. And after losing a child, just about everything feels like dumb shit. (Looking at you, JavaScript frameworks!)</p>
<h2>Extra Life</h2>
<p><a href="https://twitter.com/sarah_edo">Sarah Drasner</a> recently wrote a very touching article, <a href="https://medium.com/@sarah_edo/mourning-as-a-developer-8adf9969f531">Mourning as a Developer</a>, that really resonated with me. After suffering the loss of two friends, she found solace in her work as a web developer.</p>
<p>For me, it was extremely difficult to focus on work. Instead, I found refuge in video games. I've always enjoyed video games but the compelling gameplay loops and monotonous grind of games like Destiny and XCOM helped keep my mind off of Olivia, even if just for a few hours.</p>
<p>Before Olivia passed away, I signed up for <a href="https://www.extra-life.org/">Extra Life</a>, an annual event where people play video games for 24 hours to raise money for their local children's hospital. I've been doing it every year since.</p>
<p>In four years β thanks to the generosity of family, friends, co-workers, and complete strangers β I've raised close to $9,000 for Lurie Children's Hospital, where Olivia was treated. With the help of my friends Bert and Al, who have joined "Team Olivia," we've raised over $10,000.</p>
<p>I'm really proud to be able to do something that I enjoy while giving back and, in doing so, honoring Olivia's memory.</p>
<h2>What's Next?</h2>
<p>Allie and I have spent the last four years trying to have another child. We've tried PGD, egg donors and other avenues in hopes of avoiding passing on the disorder to our next child. It's been a long road filled with a lot of disappointment, but we're still trying and remain hopeful.</p>
<p>I'll be participating in Extra Life for the fifth year in a row on November 3rd, 2018. If you'd like to donate, you can do so <a href="https://idol.pe/donate">here</a>.</p>
<p>I've redesigned the website in hopes that it will motivate me to write more often. With the shit show that is Twitter (and America in general, currently), a lot of people I follow are getting back into blogging, and it's inspired me to get back into it as well.</p>
<p>You can look forward to reading my thoughts on all sorts of dumb shit soon.</p>
Extra Life for Lurie Children's Hospital
2014-10-23T00:00:00Z
https://mikeaparicio.com/posts/2014-10-23-extra-life-for-lurie-childrens-hospital/
<p>This Saturday, starting at 8:00am Central, I'll be playing video games for 24 hours straight to raise money for <a href="http://www.extra-life.org/">Extra Life</a>. All proceeds will go to <a href="https://www.luriechildrens.org/">Lurie Children's Hospital of Chicago</a>, where my daughter Olivia is being treated. Olivia was born prematurely after just 24 weeks but has received amazing care from the staff of Lurie Children's Hospital. I'm very happy to be able to give something back while doing something I love at the same time.</p>
<p>I'll be streaming live on <a href="http://twitch.tv/peruvianidol">Twitch</a> all day. Come by and say hello, and please consider <a href="http://extra-life.org/participant/peruvianidol">donating</a> if you can. Thanks for your support!</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/dANxGi67QY-300.webp 300w, https://mikeaparicio.com/images/dANxGi67QY-600.webp 600w, https://mikeaparicio.com/images/dANxGi67QY-958.webp 958w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/dANxGi67QY-300.jpeg 300w, https://mikeaparicio.com/images/dANxGi67QY-600.jpeg 600w, https://mikeaparicio.com/images/dANxGi67QY-958.jpeg 958w" sizes="100vw" /><img alt="Extra Life Banner" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/dANxGi67QY-300.jpeg" width="958" height="538" /></picture>
</figure>
CSS at Groupon
2014-08-10T00:00:00Z
https://mikeaparicio.com/posts/2014-08-10-css-at-groupon/
<p>This post was inspired by the recent wave of people sharing info about their CSS: <a href="http://markdotto.com/2014/07/23/githubs-css/">Mark Otto at Github</a>, <a href="http://ianfeather.co.uk/css-at-lonely-planet/">Ian Feather at Lonely Planet</a> and <a href="http://codepen.io/chriscoyier/blog/codepens-css">Chris Coyier at Codepen</a>.</p>
<p>About two years ago I was working on a redesign of Groupon's consumer website (which was later scrapped) when I was asked if I wanted to work on our internal tools team. "You won't have to support Internet Explorer," they said.</p>
<p><strong>* Cue chorus of angels *</strong></p>
<p>As Groupon had been experiencing exponential growth, many of our "internal tools" consisted of a bunch of Google Docs and things scribbled on cocktail napkins. The internal tools team was tasked with streamlining those processes. We had a half dozen or so dev teams working on different tools supported by just two designers. The challenge we faced was how to quickly crank out designs for these tools without having a horrible mishmash of CSS.</p>
<p>At first we debated the merits of using Twitter Bootstrap, which had just started gaining popularity at the time. We also looked at Zurb's Foundation. Eventually we decided that we would roll our own CSS framework in order to keep things light and consistent with our designs. We called it <a href="https://speakerdeck.com/peruvianidol/toolstrap-a-css-framework-for-groupon-internal-tools">Toolstrap</a> (Bootstrap for Internal Tools).</p>
<h2>Style Guide</h2>
<p>We began by looking at a lot of common elements in our design and started abstracting them out into reusable components. We documented these in a style guide that helped us keep track of which components needed to be styled and later served as a handy reference of what was in the framework for developers.</p>
<h2>SMACCS</h2>
<p>Next we decided that <a href="https://smacss.com/">Scalable Modular Architecture for CSS</a> would be a great way to organize our code. Most of the company was already using Sass, and the use of variables and mixins made organizing our code quite simple. Here's a general overview:</p>
<ul>
<li><strong>Base</strong> - In this folder we have <a href="http://necolas.github.io/normalize.css/">normalize.css</a> as well as base styles of all our elements, broken down by global styles (box-sizing, body styles), typography, forms, lists and tables.</li>
<li><strong>Layout</strong> - This included our grid (borrowed liberally from Foundation 2) as well as styles to support several different layouts that our different apps required.</li>
<li><strong>Module</strong> - This included pretty much every variation of elements and groups of elements that were specified by classes. (Think Brad Frost's <a href="http://bradfrostweb.com/blog/post/atomic-web-design/">Atomic Design</a>.) This includes things like buttons, form inputs, lists, navigation, header styles and little custom widgets.</li>
<li><strong>State</strong> - This folder would normally include styles that are triggered by JavaScript but, for the most part, we just put styles here for entire modules that have on/off states, such as accordions, modals and tooltips.</li>
<li><strong>Theme</strong> - Here we have variations on styles for headers, tables and forms, as well as classes to apply color themes to any element.</li>
</ul>
<h2>Toolstrap in action</h2>
<p>Teams embraced Toolstrap pretty quickly as they were able to get a majority of the design for their app from the framework without having to fiddle around in CSS trying to interpret a PSD. They could simply layer on some app-specific overrides to layout their components.</p>
<p>As more teams used Toolstrap, however, we ran into a few issues.</p>
<ol>
<li>
<p>The first version of Toolstrap was heavily dependent on Rails (which most teams were using at the time), JUI, Sass and Compass. Around that time, teams were starting to create apps using various JavaScript frameworks which made using Toolstrap difficult.</p>
</li>
<li>
<p>Versioning of Toolstrap was constantly in flux as we added new modules and removed things that were only being used by a single app. One of the tricky things about maintaining a framework used by multiple apps is determining which styles should be in the framework and which should be included in the app-specific styles.</p>
</li>
<li>
<p>We had a number of image assets included with the framework, including icon sprites, logos and background patterns. This added a lot of bloat to the framework.</p>
</li>
</ol>
<p>To solve these issues, we created Toolstrap 2. Toolstrap 2 included just a single CSS and JS file, rather than all the pre-compiled assets. We decided that we didn't particularly need every project to have access to the individual Sass files. Rather than require JUI, we simply included styles for their markup patterns for things like date pickers. This freed people to use Toolstrap on any project just by including the CSS and JS on each page.</p>
<p>We worked on DRYing up our code and pulling out a lot of things that we included "just in case." Teams were free to add these things to their app-specific styles.</p>
<p>We put all of our icons into an icon font using <a href="https://icomoon.io/">Icomoon</a>, which reduced the overhead of assets and also gave us a lot of flexibility for high-resolution displays. Chris Coyier has a great demo that shows why <a href="http://css-tricks.com/examples/IconFont/">Icon Fonts are Awesome</a>.</p>
<h2>Toolstrap for Consumers</h2>
<p>Eventually the product side of the company got wind of Toolstrap and its success and decided it would be a good idea to implement in their latest redesign efforts. We had already begun creating a style guide for the new design in earnest, known as the Groupon Interface Guidelines. The new framework took on this unfortunate name, shortened to GIG.</p>
<p>Our existing site was a massive Rails app and the CSS was just a huge, huge file with all of the styles for every page on the site, including some that no longer existed. I want to say the CSS weighed in at close to 1 MB.</p>
<h2>A quick word about the dangers of Sass</h2>
<p>While Sass can be a powerful tool in the right hands, in the wrong hands you can end up with selectors like this:</p>
<pre class="language-scss"><code class="language-scss"><span class="token selector">body.getaways-gallery-gig .page_header #filters #categories_filter .pane .categories_container .categories ul li.selectBox-selected a </span><span class="token punctuation">{</span><br /><span class="token property">color</span><span class="token punctuation">:</span> #333<span class="token punctuation">;</span><br /><span class="token punctuation">}</span></code></pre>
<p>Yes, this was an actual selector in production code. Because of the ease of nesting in preprocessors like Sass, inexperienced devs will often nest like crazy without understanding the ramifications on the compiled code. This adds a ton of unnecessary specificity that requires the same selector to override or worse, using !important. (Often times devs will even resort to inline styles! Ewww.)</p>
<h2>Building GIG</h2>
<p>As we moved from Rails to Node.js, one of the biggest challenges in creating GIG was supporting two different designs. We needed to support styles for both the existing design (referred to as OG, or Original Groupon) and the new design (known as Prom Night). Rather than create two separate frameworks, we decided to abstract out common styles between the two designs and then use SMACSS's Themes folder to apply design-specific code scoped to a single body class.</p>
<p>The initial phase of the redesign was simply a re-skinning of the site. All of the markup would would stay the same and only the CSS would change. Later, we would drop support for the old styles and begin iterating on the markup and styles until we got to the finished redesign.</p>
<p>With the common styles abstracted out, our Themes folder looked like this:</p>
<pre class="language-text"><code class="language-text">theme/<br />ββ og/<br />β ββ base/<br />β ββ module/<br />β ββ state/<br />ββ prom-night/<br /> ββ base/<br /> ββ module/<br /> ββ state/</code></pre>
<p>All of the styles were nested under an <strong>og</strong> or <strong>prom-night</strong> class that could be toggled on the body element. This allowed us to A/B test the new design pretty easily and also allowed for a staggered rollout across our international sites as we began the process of getting them all onto a single platform.</p>
<p>There's a great post on our transition from Rails to Node.js on the Groupon Engineering Blog: <a href="https://engineering.groupon.com/2013/misc/i-tier-dismantling-the-monoliths/">I-Tier: Dismantling the Monoliths</a></p>
<h2>Benefits of Custom Frameworks</h2>
<p>There are a bunch of benefits to having your own in-house framework.</p>
<ul>
<li>
<p>While many people complain that sites using frameworks all look the same, in Groupon's case, that's exactly what we're going for. Having Toolstrap and GIG allows our developers to concentrate on how their apps work and not so much on what they look like. Toolstrap's motto is <em>Push Code, Not Pixels</em>. Designers also love our frameworks because they can have consistent design across our products without all of the back and forth that goes on when developers are forced to interpret a PSD.</p>
</li>
<li>
<p>Custom frameworks allow for rapid prototyping. Every quarter or so we have an internal hackfest known as <a href="https://engineering.groupon.com/2013/misc/bottoms-up-innovation-groupon-hosts-geekon-first-internal-tech-conference/">Geekon</a>, where designers and developers have just a few days to put together a fully-realized product. With Toolstrap and GIG, teams are able to get an app up and running quickly that looks like our other internal apps. We can also prototype new products throughout the year and get high-fidelity prototypes in front of users in a very short period of time.</p>
</li>
<li>
<p>With Toolstrap and GIG, it's very easy for developers to move between teams - even from product to internal tools - and not have to spend time learning new styles.</p>
</li>
</ul>
<h2>Many Thanks!</h2>
<p>Groupon's CSS frameworks would not be possible without the efforts of the ton of talented developers we have, as well as the influence of people like <a href="http://bradfrostweb.com/">Brad Frost</a>, <a href="http://chriscoyier.net/">Chris Coyier</a>, <a href="http://snook.ca/">Jonathan Snook</a>, <a href="http://www.lukew.com/">Luke Wroblewski</a>, <a href="http://ethanmarcotte.com/">Ethan Marcotte</a>, <a href="http://keyamoon.com/">Keyamoon</a> and countless others.</p>
Building a Dream Team
2014-07-09T00:00:00Z
https://mikeaparicio.com/posts/2014-07-09-building-a-dream-team/
<p><em>(This post is based on a <a href="https://speakerdeck.com/peruvianiodl/building-a-dream-team">lightning talk</a> I gave at <a href="https://meetup.com/Geekfest">Geekfest</a> last year.)</em></p>
<p>If you work in the tech industry, you're probably familiar with the following words which recruiters use to describe their ideal candidate:</p>
<ul>
<li>Ninja</li>
<li>Rock Star</li>
<li>Wizard</li>
<li>Jedi</li>
<li>Guru</li>
<li>Unicorn</li>
</ul>
<p>And my personal favorite:</p>
<figure>
<p><img src="https://mikeaparicio.com/images/fullstackdeveloper.gif" alt="Dr. Evil doing air quotes with the caption "Full Stack Developer"" /></p>
</figure>
<p><strong>I'll take Mythical Creatures for $800, Alex.</strong></p>
<p>You may consider yourself a full stack developer but let me explain why I have beef with this term.</p>
<p>When we talk about "The Stack," we're talking about the technologies we use to build websites. There's HTML, CSS, and JavaScript. Maybe you're into Ruby on Rails or you live on the cutting edge of JavaScript frameworks or you're keeping it real with PHP. You probably have a MySQL database. And all the stuff beyond my expertise, which I collectively refer to as "server shit." A full stack developer should be experienced and at least competent in most, if not all, of these areas.</p>
<p>We could easily expand the stack to include things like user experience, content strategy, typography, and Photoshopping people's heads onto funny bodies. At this point it becomes more of a spectrum of skills than a stack of technologies. Along this spectrum you have people who can do any number of these things, but they tend to specialize in one particular area. People on one end of the spectrum are labeled as designers and on the other side, developers.</p>
<figure>
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/O3w-5nG5m8-300.webp 300w, https://mikeaparicio.com/images/O3w-5nG5m8-600.webp 600w, https://mikeaparicio.com/images/O3w-5nG5m8-1200.webp 1200w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/O3w-5nG5m8-300.jpeg 300w, https://mikeaparicio.com/images/O3w-5nG5m8-600.jpeg 600w, https://mikeaparicio.com/images/O3w-5nG5m8-1200.jpeg 1200w" sizes="100vw" /><img alt="The stack as a spectrum" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/O3w-5nG5m8-300.jpeg" width="1200" height="673" /></picture>
</figure>
<p>No shit, right? I'm not telling you anything you don't already know. Bear with me.</p>
<p>In basketball, player stats are tracked in a box score. While some most players excel in a few areas, others - <a href="http://en.wikipedia.org/wiki/LeBron_James">LeBron James</a>, for example - are known for "filling up the box score." On any given night they can provide huge numbers in any and all metrics in the box score.</p>
<p>Do you consider yourself the LeBron James of web design/development? Probably not. (I'm closer to the <a href="http://en.wikipedia.org/wiki/Brian_Scalabrine">Brian Scalabrine</a> of web development, myself.)</p>
<p>Yet so many companies pass up perfectly qualified candidates because they want to hire a bunch of LeBrons that can do everything. The fact is, you're lucky to find one LeBron, much less a whole team of them.</p>
<p>Some NBA teams have tried. The 2012-13 Lakers had one of the all-time greatest players, Kobe Bryant, and a versatile big man in Pau Gasol. They had already won a couple of championships together. They added Steve Nash, one of the greatest point guards in NBA history, and Dwight Howard, arguably the best big man in the game today. And just for shits and giggles threw in Metta World Peace, a.k.a. Ron Artest, who, as a Chicago Bull once <a href="https://www.youtube.com/watch?v=NlLOiw0m2LY">applied for a job at Best Buy</a> so he could get the employee discount.</p>
<p>How'd this team do? They barely squeaked into the playoffs on a five-game win streak and were swept in the first round.</p>
<p>Okay, I get it. Maybe you're not a basketball fan. Let's talk superheroes. Think about the Incredible Hulk. How cool would it be to have the Hulk on your team, just smashing shit left and right? What's better than that? I'll tell you: FIVE HULKS. A team of five Hulks is FUCKING AWESOME... if you need shit smashed.</p>
<figure class="ma-float-right">
<picture><source type="image/webp" srcset="https://mikeaparicio.com/images/aqxMx0y_IQ-300.webp 300w, https://mikeaparicio.com/images/aqxMx0y_IQ-600.webp 600w" sizes="100vw" /><source type="image/jpeg" srcset="https://mikeaparicio.com/images/aqxMx0y_IQ-300.jpeg 300w, https://mikeaparicio.com/images/aqxMx0y_IQ-600.jpeg 600w" sizes="100vw" /><img alt="The Avengers" loading="lazy" decoding="async" src="https://mikeaparicio.com/images/aqxMx0y_IQ-300.jpeg" width="600" height="480" /></picture>
</figure>
<p>Sometimes, though, you just need a dude on your team who all he does is shoot stuff with a bow and arrow. But he's REALLY good at it. Throw in a billionaire genius, a super-strong and agile World War II vet, a Norse god with a powerful hammer, a foxy, red-headed ninja, Samuel L. Fucking Jackson and Robin from <em>How I Met Your Mother</em> and you've got a pretty formidable team.</p>
<p>But if you're anything like me, the closest you'll ever get to being a super hero is <a href="https://mikeaparicio.com/images/italian-spiderman.jpg">THIS</a>. And the closest you'll get to being LeBron is <a href="https://mikeaparicio.com/images/lebron2k.jpg">THIS</a>.</p>
<p>Hiring a team is a lot like online dating. You have this ideal person you're looking for but, the truth is, that person is not online looking for dates. They're out at the bar every night getting laid.</p>
<p>And companies looking to hire the LeBron James of web design/development are not the Lakers. At best they're the Cleveland Cavaliers. They may luck into a LeBron once in a generation but ultimately he's going to take his talents to South Beach and win a couple of titles there instead.</p>
<p>So how does one build a Dream Team then?</p>
<p><strong>Hire some hungry, young talent.</strong> They might be a little raw, a little rough around the edges, but if you surround them with good teammates they can turn into something special.</p>
<p><strong>Hire a Hawkeye.</strong> <a href="http://en.wikipedia.org/wiki/Steve_Kerr">Steve Kerr</a> is a five-time NBA champ and pretty much all he did was shoot threes. But he's the all-time leader in career three-point percentage in NBA history! And he worked cheap.</p>
<p><strong>Bring in some savvy veterans to mentor your younger team members.</strong> The Knicks signed 40-year-old <a href="http://en.wikipedia.org/wiki/Jason_Kidd">Jason Kidd</a> a couple of years ago. He didn't have much left in the tank but his experience was invaluable in developing their young guards. Now he's a head coach.</p>
<p><strong>Hire a good manager.</strong> This may be the most important aspect of a great team. Someone who knows how to get the best out of everyone. <a href="http://en.wikipedia.org/wiki/Phil_Jackson">Phil Jackson</a> won 11 championships as a coach. He was known for getting his star players to put aside their egos to work together and got the best out of his role players.</p>
<p>Finally, <strong>take care of your team.</strong> You don't want them to become unhappy and go someplace else to be successful. <a href="http://en.wikipedia.org/wiki/Mark_Cuban">Mark Cuban</a> is famous for providing nothing but the best for his players. His Dallas Mavericks have made the playoffs 13 of the last 14 seasons (including two Finals appearances and one championship) after missing the previous 10 straight playoffs.</p>
<p>Cuban also has some great advice for being a dream teammate:</p>
<blockquote>
<p>Sweat equity is the most valuable equity there is. Know your business and industry better than anyone else in the world. Love what you do or don't do it.</p>
</blockquote>