Chris Padilla/Blog


My passion project! Posts spanning music, art, software, books, and more. Equal parts journal, sketchbook, mixtape, dev diary, and commonplace book.


    Writing Music is Just Problem Solving

    Writing music is actually just problem solving.

    There are folks on both sides of the left and right brain spectrum as far as music making goes. Free form jazz is on the right brain side. Schoenberg's 12 tone school is on the left side.

    Most of it is actually somewhere in the middle, though.

    The ideas may come from inspiration or from influence. It starts with "I want to write a melody in a Medieval Style." But then, the next statement is "Let me figure out how to do that!"

    And it goes on from there:

    • Let me listen to references.
    • Let me score study a few of them.
    • Let me spend 15 minutes sounding bad in a musical mode until I find a melody I like,
    • Let me find an instrument that matches the sound in my head.
    • Let me try adding this other instrument. Woops! That doesn't fit. Let me try another
    • I want to transition key centers to the subdominant. How can I do that AND make my listeners feel a sense of bewilderment and magic as I do that.

    The fun part is it starts pretty broad and loose, but then gets very technical through the project.

    For me, the hardest part of writing is getting started. Blank canvas syndrome. Once a piece is in motion, though, then it's just solving particular musical and emotional challenges along the way.

    From there, the tune is taking shape, you're getting more limitations, those limitations bread further creativity, and eventually you stop because adding any more takes away from the spirit of the piece. Time to go on to the next problem - writing another one.

    In my mind, this doesn't cheapen the spiritual nature of music making or the mystique of writing music. It's both. When stuck trying to pull a melody out of the materials, eventually there's something that comes out of nowhere to fill in the gap. That's still a part of it too.

    I think it's helpful to dispel the belief that it's talent or a gift to do the whole music writing thing, though. Much of it is a lot more on the ground and just working in the dirt than it's given credit, like any creative art.

    (Also worth saying, in my experience, the process of writing music is WILDY SIMILAR to writing software.)


    Software is Measurably Valuable Creation

    Last year I read Chad Fowler's The Passionate Programmer, and I still think a lot about these lines from his ending essay:

    You could have chosen any number of career paths, but this one is exciting. It's creative. It requires deep thinking and rewards you with a sense of being bale to do something that most of the people you meet each day can't imagine being able to do. We may worry about progressing to the next level, making an impact, or gaining respect from our co-workers or our peers in the industry, but if you really stop to think about it, we've got it really good.

    Here's what really sticks with me:

    Software development is both challenging and rewarding. It's creative like an art-form, but (unlike art) it provides concrete, measurable value.

    It rings true. It doesn't feel like music, art, writing, and software are all that separate. They're all simply different mediums for creation. Funnily, in my experience, they all have similar rhythms when it comes to starting a project to completing it. Thankfully, too, when one feels stagnant, it's easy to jump to another one. Stirring a boiling pot, waiting for the other one to simmer.

    The wonderful thing about software is that it is a concrete service. It's difficult to really pin down the value of art. That doesn't dilute art's true importance and value. That might, in fact, be why music and art are wildly valuable. It's an act of awe and wonder, and you can't measure that.

    What a fantastic creative balance, though, that software is a practice that allows you to directly create something to improve the lives of any number of people.

    Early on in my current role, I met with teammates who walked up to me, shook my hand, and said "WOW, the kanban feature you developed makes my life SO MUCH easier! Thank you!"

    I'm convinced that, in a wholly creative life, our practices need both sides. We need that which is directly beneficial to people, and that which entangles with the spirit of discovery and sensitivity. And I'm thankful for software as the form that balances exploration.

    Here's the opening quote on Chad's essay:

    But I say to you that when you work you fulfill a part of earth's furthest dream, assigned to you when that dream was born, and in keeping yourself with labour, you are in truth loving life, and to love life through labour is to be intimate with life's inmost secret. — Kahlil Gibran, The Prophet


    Writing is Efficient Creativity

    I still think regularly about Walt Stanchfield's equation: "Impression minus expression equals depression."

    For me, I've wrestled with what that looks like. All the quirky projects I have going on — art, music, software — generally stem from the idea of taking in what I love and pouring it back out into the world.

    Producing something to share daily is tough, though.

    Writing music is not fast. At least for me. It takes design, sculpting melodies, mucking with synth settings, sometimes practicing an acoustic instrument to get there, and recording multiple takes. Don't get me wrong, it's fun, but it's not a very immediate mode of expression outside of improvising.

    I picked up art partly because I wanted a quicker means at communication. A line can be expressive. Sketches take only a few minutes in a day to get out. But WOOPS! After a few months of rough doodles, I'm hungry to build my craftsmanship and do some serious study. So there are still expressive elements, but the full spectrum is on the other side of some devoted practice. I'm just too much of a beginner here.

    Blogging, though!

    Writing is simply efficient creativity. Essays in any other form take a lot of time: videos take producing and equipment, podcasts take coordinating and editing, speaking takes an audience.

    Writing is a straight shot from imagination to publication. It's also the most flexible medium - you can write technical articles one day, life posts another, highly sensory poetry and non-fiction essays the next day. All of this is augmentable with links, images, sound, and video.

    And, writing is a terrific way to turn the process of all other art forms into creative pieces themselves.

    Software takes a long time to write, too. But sharing a bit about what I learned along the way helps keep my spirit in motion.

    I've been searching for a creative practice that can be shared daily, and maybe writing is it. Writing is a great sustainer while other dishes are still in the oven.

    I'm tempted to say maybe this only applies to me, but the truth is we're all virtuosos of our own way of speaking and communicating. Writing is an expressive medium that we all have access to.

    So if you have something to say — I know you do! — then come hang!


    The Gist on Docker

    "As for me, I am tormented with an everlasting itch for things remote. I love to sail forbidden seas, and land on barbarous coasts." - Herman Melville, Moby Dick

    We're learning about Docker this week at work! 🐳

    Here's what I can tell you so far:

    Why Use it?

    Two big reasons:

    1. Consistency of dependencies (namely, node versions in web development)
    2. Easy onboarding for new devs

    To the first point: Node versioning can be a hassle. Even if your application isn't reliant on a specific version of node, perhaps an NPM package you are using is. Any difference between your environment and your hosts could lead to strange issues.

    To the second: swapping between local versions of node or python can also be tricky. And then say you start working on an app where you need to download a specific version. All doable, but Docker can make this smoother.

    Hosts Handle This Usually

    To run your server on another machine, if you were to do it yourself, you would need:

    1. To install an OS
    2. Install your runtime (Node, Python, etc)
    3. Upload you app directory
    4. Initialize the run command

    Vercel, Netlify, Render, even AWS essentially eliminate all the steps except for the third one. You simply send your files up, and these services will take care of the rest in most cases successfully.

    When you need greater flexibility, or your application is more complicated and fussy with it's versioning, Docker can be the tool to reach for.

    Image? Container?

    A Container is a lighter version of a Virtual Machine.

    A virtual machine is what it sounds like. On a computer, you can simulate a full blown PC by using the hardware on the one you're running it on. Think using Bootcamp to run Windows on a Mac.

    A container is a level lower than that. Containers will share the same OS, but will still have separate, self contained resources and file directories. I can have two different containers running different versions of node.

    An image is the recipe for a specific container's environment. Docker takes an image and creates a container with the given OS, runtime environment, packages, and environment variables. You'll set all this up in a Dockerfile in your application.


    The Haps - March 2023

    Valentines, Galentines, and Palentines! February was an A+ month! The grooves are tracked and I'm in them for code, music, art, and people.

    Blogging & Dev

    I'm getting the hand of this blogging daily thing! Lots of tech journals this month from learning testing in React.

    Continuing on with the Tailwind redesigns at work! It's been coming along nicely. 👌 We'll be learning Docker at work, so I'm reading up on great quotes from Moby Dick. 🐳

    I went to my first meetup in a while! React Dallas was a great hang. There's a really welcoming and smart community out here!

    Music

    I released Spring this month! I'm impatiently waiting for it to actually feel like Spring outside!!

    Spring Cover

    Good things coming with guitar and piano! I'm learning finger style on guitar and am plugging away at reading jazz lead sheets on piano.

    You can see what I've shared so far through the Music tag on my blog

    Drawing

    Two pears in a pod

    I'm getting close to finishing my second ever sketch book! I'm breaking the threshold of only learning from videos to actually learning through the craft. Like practicing an instrument, the training wheels are coming off and I can just start learning through practice. Exciting!

    I'm still doing drawabox. Also going through the brand new Proko Drawing Basics course. Drawabox is so dense an zeroed in on construction that it's great to have a more general, exploratory curriculum with Proko.

    You can see what I've made so far through the Art tag on my blog. I'm also sharing drawings on Instagram.

    Words and Sounds

    📚

    🎧

    Life

    Early this month Miranda and I went to Denver, Colorado for The Gate. IYKYN, we both came back lit up and ready to rock and roll!

    Tourist-wise, we got to see the Meow Wolf out there. We loved the original in Santa Fe when we went a couple of years ago. So crazy cool! Can't wait for the Grapevine location to open this summer!

    We also saw Maggie Rogers. That concert was a blast! Great band, great crowd, great music.

    What's up?

    👋


    Louie Zong's Boss Rush & Sketches

    Louie Zong's album Boss Rush and the CUSTOM BLENDER RENDERED 3D VIDEO is a gem.

    I may have actually had nightmares about the school bus guy grouwing up???

    He's the angriest gamer you've ever heard

    My last bit of plant construction for drawabox!

    Reaching out! 🌱


    Faber — Grand Central Station

    Listen on Youtube

    Big Rhapsody in Blue Vibes with this one. 🌆


    Testing and Implementation Details

    Redux casts it's vote for the methodology behind React Testing Library.

    A key paradigm of React Testing Library is to avoid testing implementation details.

    The reason being your users are namely concerned with the app behaving as they expect.

    In react, that means not necessarily writing tests that your redux store is what you expect it to be. Instead, it's testing that information is rendering on the page correctly.

    I can see the reason why. Implementation details change. Especially in modular systems. We should be able to swap redux out with a means of stage management without having to throw out or refactor our tests. That's twice the refactoring work when all we're concerned about is the app performing as it should be.

    At the end of the day, that's more orthogonal.

    Implementation Details Are Relative

    My example from last time where I'm refactoring my form to elevate a handleSubmit method comes close to being overly concerned with implementation details. As a reminder, here's what that test looked like:

    /**
     * @jest-environment jsdom
     */
    import React from 'react';
    import * as reactRedux from 'react-redux';
    import { render, cleanup, waitFor, fireEvent } from '@testing-library/react';
    import CartItemForm from '../components/CartItemForm';
    
    test('<CartItemForm />', async () => {
        const rendered = render(
        <CartItemForm
          item={chipsAndGuac}
          itemID={'5feb9e4a351036315ff4588a'}
        />
      );
    
        ...
    
      const spiceOptions = await rendered.findAllByTestId('option');
      const firstOption = spiceOptions[0];
    
      fireEvent.click(firstOption);
    
      const addItemButtonElm = await rendered.findByTestId('add-item');
    
      expect(addItemButtonElm.className.includes('selected'));
    
      fireEvent.click(addItemButtonElm);
    
      expect(handleSubmit).toBeCalledTimes(1);
      expect(handleSubmit).toBeCalledWith(formExpectedValue);
    
    }

    I would argue that this is not necessarily too concerned with implementation details, since the result from a form is a fairly important juncture in the flow of this app. AND I'm not really testing redux here. I'm simply verifying that our onSubmit is getting the information I expect.

    However, this integration test is lower on the value scale compared to one where I'm also checking to see if the cart is rendering the correct data afterwards. And that is much closer to what the user is expecting.

    Even so, I'm in the clear - if I swap dispatch for an external api, no big deal. I still want to verify that it's getting passed the information I expect. If we swapped the form for a different layout, that's another component entirely, and we wouldn't be able to avoid reworking tests in that case anyway.

    A Higher Level of Abstraction

    So that's one level of implementation details being disregarded. What about a level higher?

    For this app, there's a higher level of abstraction. When it comes to properly updating an item in the cart, then it's important to pull further away from implementation details.

    Here my logic is in the redux store, but I don't want to verify the values in the store. That's an implementation detail. I want to verify with what's rendering on the user's cart display is correct.

    It's a surprisingly nuanced methodology. I can see why integration testing is a broad portion of the testing spectrum. An appropriate integration test from my last post would not be the same level of abstracted integration test as today's example. And I can see how it's a sweet spot in validating the security of your app. It's the most flexible type of test to give high levels of confidence in different applications and scenarios.

    The Sweet Spot

    I like to interpret that this is why the "integration part of Kent C. Dodd's testing trophy slopes. The higher up an integration is, the more likely that test will stick around as you swap implementation details, and the closer it is to what the user experience. Therefor, the more useful your test is as a tool for building confidence in the stability of your app.

    In my mind, this doesn't negate the benefit of writing tests that are lower on the spectrum. Even unit testing, as a tool for writing modular code, is a pretty sound one.

    But it checks out — integration tests sit in the sweet spot.


    Testing Encourages Refactoring

    I came across hard evidence that testing leads to well designed code this week. Taking the time to test old code is helping me decouple my JavaScript!

    I'm using a NextJS E-commerce site as a playground for practicing writing tests. On the site, I have an item order page for each item on a menu. On the page, you can customize the item, select quantity, and then add them to your cart.

    The component tree structure looks something like this:

    <ItemDisplayPage>
        <CartItemForm>
            <CustomizationDisplay>
            <AddItemToCart>
                <ButtonWithPrice />
    
            ...

    ItemDisplayPage is the page level component, and ButtonWithPrice is the lowest child in this form. Everything else in between handles a spectrum of logic relating to the form.

    The Rookie Mistake

    This app is a 2-year old project, a portfolio piece written before I was full time in software. So there were some odd design choices.

    This is the big one: My onSubmit function was in <ButtonWithPrice/>. Yikes!

      const handleSubmit = (values) => {
        dispatch({
          type: 'ADD_TO_CART',
          payload: {
            ...values,
          },
        });
    
        router.push('/');
      };

    It's doable because, with hooks and global state, I can make that call all the way from the button and it is technically possible.

    That very much tightly couples my form logic with the submit button. The button should really only be concerned with rendering price, adjusting quantity, and then firing the handleSubmit method — NOT declaring it, though.

    Testing Encourages Refactoring

    At the time, it was no big deal. The app worked, tangled as it may have been!

    When it came to testing the code, though, doing so was challenging.

    I wanted to write an integration test the verifies that, on submit and after some interaction, I'm getting the right data saved to my Redux store. I want to do this from CartItemForm since that's a logical container for all of the interactions and form submission.

    Here's a sketch of what that test looked like:

    /**
     * @jest-environment jsdom
     */
    import React from 'react';
    import * as reactRedux from 'react-redux';
    import { render, cleanup, waitFor, fireEvent } from '@testing-library/react';
    import CartItemForm from '../components/CartItemForm';
    
    test('<CartItemForm />', async () => {
        const rendered = render(
        <CartItemForm
          item={chipsAndGuac}
          itemID={'5feb9e4a351036315ff4588a'}
        />
      );
    
        ...
    
      const spiceOptions = await rendered.findAllByTestId('option');
      const firstOption = spiceOptions[0];
    
      fireEvent.click(firstOption);
    
      const addItemButtonElm = await rendered.findByTestId('add-item');
    
      expect(addItemButtonElm.className.includes('selected'));
    
      fireEvent.click(addItemButtonElm);
    
      expect(handleSubmit).toBeCalledTimes(1);
      expect(handleSubmit).toBeCalledWith(formExpectedValue);
    
    }

    The gist:

    1. I'm rendering CartItemForm with React Testing Library
    2. I'm simulating user interaction by selecting a spice level in the form.
    3. I'm clicking the submit button
    4. I'm asserting if handleSubmit has been called and if it has certain values.

    With this test written, here's the problem - how do I mock handleSubmit and read the values? I simply can't with the way my component is structured!! I can't drill down and mock from this level. Even if I rendered my button component, the submit method is still within the component and not easily reachable. It has to be extracted in some way.

    So, ultimately I moved the handleSubmit declaration up to ItemDisplayPage and prop drilled from there.

    That allowed me to mock and pass the mocked handleSubmit method this way:

      const handleSubmit = jest.fn();
    
      const rendered = render(
        <CartItemForm
          item={chipsAndGuac}
          itemID={'5feb9e4a351036315ff4588a'}
          onSubmit={handleSubmit}
        />
      );

    What do I have as a result now?

    • A passing test ✅
    • More flexible, organized code ✅
    • Bonus: I can more confidently refactor later, knowing I have tests in place 💯

    I can see why there are cultures around testing first. WHen using libraries that fall on the spectrum of being opinionated, it guides your code to being more resilient. The upfront cost of setup is paid off in the long run with easily changeable code.


    Testing Organizes Code

    Rebecca Murphey has a fantastic. talk on front end testing. It's all done in JQuery, and the principles still apply really nicely to react applications.

    My favorite takeaways:

    1. Testing allows for a clear explanation of what consumers of your code can expect. Rebekah says this is like documentation, but even better! Tests will actually verify that the code does what it says it will, unlike documentation.
    2. Testing allows you to write methodically. Writing the code is easy once you've written the expectations. This is further validation for testing as a process of clear thinking. Put another way: Measure twice, cut once.
    3. Testing old code illuminates tight coupling. Much of the talk is diving into an example of a long file of entangled responsibilities. Server requests, rendering data, managing state, all in one function. When you sit down to write a test for this, the coupling is quickly illuminated.

    Jest Supports This Systematically

    That last point is one I'm coming up against in my own codebase.

    This site keeps all it's content in markdown. So I have a looong file with methods for grabing that data:

    // api.js
    
    const postsDirectory = join(process.cwd(), '_posts');
    
    export function getPostSlugs() {
      return fs.readdirSync(postsDirectory);
    }
    
    export function getPostBySlug(slug, fields = []) {
      const realSlug = slug.replace(/\.md$/, '');
      const fullPath = join(postsDirectory, `${realSlug}.md`);
      if (!fs.existsSync(fullPath)) return false;
      const fileContents = fs.readFileSync(fullPath, 'utf8');
      const { data, content } = matter(fileContents);
    
      const items = {};
    
      // Ensure only the minimal needed data is exposed
      fields.forEach((field) => {
        if (field === 'slug') {
          items[field] = realSlug;
        }
        if (field === 'content') {
          items[field] = content;
        }
    
        if (typeof data[field] !== 'undefined') {
          items[field] = data[field];
        }
      });
    
      return items;
    }
    
    export function getAllPosts(fields = [], options = {}) {
      const slugs = getPostSlugs();
      let posts = slugs
        .map((slug) => getPostBySlug(slug, fields))
        // Filter false values (.DS_STORE)
        .filter((post) => post)
        // sort posts by date in descending order
        .sort((post1, post2) => (post1.date > post2.date ? -1 : 1));
    
      if (options.filter) {
        posts = posts.filter(options.filter);
      }
    
      if (options.limit) {
        posts = posts.slice(0, options.limit);
      }
    
      return posts;
    }
    
    . . .

    If I wanted to test getAllPosts, this is already difficult on a file-organization level. I can't very well mock the method getPostSlugs because with Jest you can only mock external packages.

    I suppose this, in practice, isn't a terribly tight coupling. They are separate methods. But it has already illuminated an opportunity to break up this file to more closely follow a MVC model of organization. A strange paradigm to take on with the absence of a database here, but taking a step towards it lends to the first point at the top of this post - we get clarity in expectations of how this app is working. A big win already.


    Generating a Sitemap in NextJS

    I wanted to learn how to add search functionality to a NextJS Markdown blog. That's my blog and I'm starting to accumulate a lot of posts here! So I took to Google, and what did I find? Why, I found Julia Tan's post on "How To Add Search Functionality to a NextJS Markdown Blog".

    I've been pretty happy with blogging being a more personal, long form means of keeping a dev journal. Recently, though, blogging has helped me find my people along the way. And that's really exciting!

    When a Google search sent me to a personal site and not a Medium article or Stack Overflow forum, that got me pretty excited. I'm not looking to growth hack my blog or become a domain authority, but I do want to make it easier for folks to find these posts.

    So begins an SEO cleanup!

    The Current Situation

    My site currently checks off the boxes for the bare bone necessities here: I have meta tags for pages and I'm using Semantic HTML for easy parsing.

    I tried Googling a few of my own articles with some disappointing results. "Express React Chris Padilla" at the time brought up my landing page, but not my article on it.

    I went through a few considerations of why this might be:

    1. I don't track this, but I'm confident my blog doesn't get a lot of traffic at the moment. :)
    2. I don't have keyword authority on Express or React, sure. But I have at least more authority with "Chris Padilla" in a tech context, I would think!
    3. I considered my URL structure. I don't keep any subdirectories, but I learned that this doesn't really have a large sway on SEO.

    Sitemaps

    No better source to ask about this than Google themselves. And a bit of looking brought me to sitemaps and why I might need one.

    A Sitemap is largely what it sounds like: It's an XML file that outlines the pages on your site. Bots will use this to ensure all your pages are crawled. Here's mine.

    Here's Google documentation on why you might need one:

    • Your site is large. Generally, on large sites it's more difficult to make sure that every page is linked by at least one other page on the site. As a result, it's more likely Googlebot might not discover some of your new pages.
    • Your site is new and has few external links to it. Googlebot and other web crawlers crawl the web by following links from one page to another. As a result, Googlebot might not discover your pages if no other sites link to them.

    "Large" to Google probably means hundreds or thousands of pages, but my page count is crawling day by day. More important is probably that this is a new site and I'm not breaking the internet with these posts.

    Generating with NextJS

    Next has great documentation on this and even provides code for generating your own sitemap.

    I had to tweak mine just a bit to provide a couple of handy tags:

    • <priority>: on a scale from 0 to 1.0, how important is this page? Landing page is 1.0. My music page is 0.9.
    • <changefreq>: This site is alive! This is how to let bots know the interval it typically updates. My blog page would be daily and my now page would be monthly.

    Here's what those tweaks look like in NextJS's generateSiteMap function:

    function generateSiteMap(slugs) {
      return `<?xml version="1.0" encoding="UTF-8"?>
       <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
         <!--Manual URL's-->
         <url>
           <loc>${BASE_URL}</loc>
           <priority>1</priority>
           <changefreq>daily</changefreq>
         </url>
         ${slugs
           .map((slug) => {
             if (slug === 'blog') {
               return `
                <url>
                  <loc>${`${BASE_URL}/${slug}`}</loc>
                  <priority>0.9</priority>
                  <changefreq>daily</changefreq>
                </url>
              `;
             } else if (slug === 'now' || slug === 'music') {
               return `
                 <url>
                   <loc>${`${BASE_URL}/${slug}`}</loc>
                   <priority>0.9</priority>
                   <changefreq>monthly</changefreq>
                 </url>
               `;
             } else {
               return `
                <url>
                  <loc>${`${BASE_URL}/${slug}`}</loc>
                </url>
              `;
             }
           })
           .join('')}
       </urlset>
     `;
    }

    Getting those values is business as usual for NextJS: write a getServerSideProps method.

    export async function getServerSideProps({ res }) {
      // We make an API call to gather the URLs for our site
      const pages = getAllPages();
      const posts = getAllPosts(['slug']);
      const albums = getAlbums();
      const dynamicSlugs = [...albums, ...posts].map(
        (contentObj) => contentObj.slug
      );
    
      const slugs = [...pages, ...dynamicSlugs];
    
      // We generate the XML sitemap with the posts data
      const sitemap = generateSiteMap(slugs);
    
      res.setHeader('Content-Type', 'text/xml');
      // we send the XML to the browser
      res.write(sitemap);
      res.end();
    
      return {
        props: {},
      };
    }

    Funny to me is that you still have to export a default function. The res.write() and res.end() method above handle sending the XML file. But, I suppose Next still needs to see a React component for this to work happily:

    function SiteMap() {
      // getServerSideProps will do the heavy lifting
    }
    
    export default SiteMap;

    And there you have it! Here's hoping you've reached the end of this article after searching "Generating a Sitemap in NextJS."


    Blog to Find Your People

    Austin Kleon shared Henrik Karlsson's "A blog post is a very long and complex search query to find fascinating people and make them route interesting stuff to your inbox." in one of his latest posts

    A blog post is a search query. You write to find your tribe; you write so they will know what kind of fascinating things they should route to your inbox. If you follow common wisdom, you will cut exactly the things that will help you find these people. It is like the time someone told the composer Morton Feldman he should write for “the man in the street”. Feldman went over and looked out the window, and who did he see? Jackson Pollock.

    ...You will write essays that almost no one likes…. Luckily, almost no one multiplied by the entire population of the internet is plenty if you can only find them.

    Kleon concludes that "This is really a great summary of the best thing that writing and sharing your work can do for you." Just as he outlines in moments through Show Your Work!

    This is what drew me back to sharing online and firing up this blog. After reading Digital Minimalism by Cal Newport, I had taken on a Luddite's mentality to putting things out online. I swore to only doing in person socializing and purely offline means of communication.

    It was great in many ways! Our brains are really wired for the physical connections of a dinner date or playing in a community band.

    But the internet is such an amazing medium for connecting with kindred spirits.

    From the Neopets forums to sending an email after reading someone's blog post, our work connects us. One of the best reasons to practice any art is that it's a form of communication with others in an elevated craft. That is amplified by making that connection with people beyond our local tribe.

    Having a means of genuine connection with a global community. How rad is that?

    This blog hasn't been going long, but I've already made some great friends just by saying hello and keeping up with each other's posts on our blogs.

    Added bonus for blogging in particular - It's insulated from likes, from performance metrics, and it's a glove that fits the hand of the artist, vs cramming them into a box.

    Romanticised? Maybe. But I think it's pretty darn special!


    Chunky Head Construction

    Studies and experiments on Andrew Loomis' Fun With a Pencil! Lots of chonky cheeks. 🙉

    Big round boys

    ⚽️ Start here:

    Faceless round boys

    🙊 End up here:

    Angling these guys from top and bottom view is hilarious


    Fingerstyle Prelude

    Listen on Youtube

    Getting fancy with fingerstyle! 🖐


    Hosting Images for chrisdpadilla dot com

    My site is turning into a lot of images. I haven't really considered the way they're handled on my site very thoroughly until now.

    My current strategy is hosting on an AWS S3 bucket and using the Image component from Next JS. With the component, Next handles the image optimization. So I can upload images as is (usually 2mb big) and Next will dynamically optimize for the resolution requested.

    It's worked great on the pages I'm generating on the server. But I recently found out the component doesn't run on statically generated pages. For me that means all my blog posts aren't having their images compressed.

    I serve up an RSS feed, and that approach won't quite do there either. The next component would be cumbersome while generating the feed.

    Essentially, I need a non-Next solution for taking a moderately high quality image from my host and dynamically serving up a light-weight image.

    My Options

    1. I know Wordpress has plugins for this sort of thing. But it's not really reasonable to migrate my site just for this sort of thing.
    2. TinyPNG is one of the plugins, and they have a CDN and API solution. They'll even save your images to S3 after optimizing. A bit too involved for my taste here, though.
    3. I used Sanity for AC: New Murder. They had a nice library for querying images in the exact dimensions you needed, and this could be done dynamically. Getting warmer, but I'm not in need of a full-blown CDN.
    4. Cloudinary has the same on-the-fly image optimizing through URL that Sanity has, and a very generous free tier.

    So I'm turning to Cloudinary. And so far, so good! I've created a named transform so that all I have to do is add a t_optimize param to the url to get a resized, compressed image. I can get more granular with it from here, but for my needs, it feels like this gets me most of the way there to optimized images.

    https://res.cloudinary.com/cpadilla/image/upload/t_optimize/chrisdpadilla/albums/spring.jpg

    And there we go! There's support to do this dynamically with JavaScript, and I have a way of bringing the images in to RSS without worrying about a heavy load time.