This is the digital confluence of a lot of things I do: comics, writing, coding, theory, and arts education. Make yourself comfortable and dig in wherever you like. It’s nice to have you here.

Recent Posts

  • Dog For Hire: Process

    Here’s some insight in the process of creating one of these digital collage comics:

    Content

    These were the pieces that I chopped up for this. I looked at a lot of other things but these wanted to coalesce together in my mind. I allow this stage of the process to be open. I save the images to my desktop and then drag them into the canvas once I’ve laid in a grid.

    I use the Icon Archive’s classic pixel art icons as a source of inspiration. It’s like opening up a magazine to a random page and cutting out what I find. Their archive structure makes this useful. Sometimes I find a flower I like and then pop into the collection that flower comes from to see what other icon’s the creator of that icon might have made.

    Form

    I usually start these comics solely with a desire to make something. Sometimes I have a direction in mind. I usually find myself using that as a place to start but veer away from that idea or sentiment fairly quickly. I tend to follow my intuition of what makes the pieces come together. Here’s a look at some of the early cut and pasting and rearranging looked like.

    The first step was the laying out of an underlying grid. I don’t always do this, but it was something I wanted to work on in this case. I’ve been really interested in underlying grids determining higher order structure relationships. Tight, but invisible. (I look forward to making 15 panel grid pages in the future. That grid is a brutally beautiful thing).

    As you can see, in this piece I was especially committed to the overall structure, particularly the inlaid 9 panel grids within panels 2 and 3. I thought it to be an interesting formal constraint and I found that there was a fertile tension in the layout.

    Color

    To achieve the coloring technique that I’ve used as the unifying element for this series, I use Photoshop’s Save For Web feature. It’s usually used to compress files with fine control of format and compression artifacts. In my usual way, I looked at this tool that was built with a certain use case: optimal compression with controlled lossy-ness, and thought tried to think of it in another way. What would it yield if the goal was to intentionally change the image significantly?

    Save for Web Dialog Box from Photoshop showing a compressed version of this post's comic

    I started following this train of thought a couple years ago. I’ve found that it creates a really neat back and forth in the process, akin to screen printing, where the output based on the input started to effect the decisions I would make in the input. I’ve sought to become in tune, intuitively, with the variables involved in the color decision and dithering algorithm.

    Some high level take-aways: Gradients dither really nicely, for example. Garish colors in an original image, assuming they have solid contrast, yield coherent new images. Organic mark making techniques yield surprising textures. Pixel art’s sharp edges yield a satisfying textural contrast to the complext dithering that happens, etc.

    In short, this process creates richly textured digital images that I think of as screen printed collages. It’s a good space to step into when I want to communicate something but don’t know exactly what.

    Trial and error, constraint and composition, chaos and accident.

  • Weather-Or-Not: Web App Process

    Animation of the web app in use

    Earlier this summer my buddy Missy Moreno and I decided to make inroads in learning how to work with React and APIs. We decided to make a cheerful weather web app that had some kind of suggestion system based on the weather forecast at a given location. That was the genesis of Weather-Or-Not. Here’s a link to the Github repository where we keep the code.

    Having just recently learned how to write successful code in ReactJS, we dove in and got to work. We had plenty of messy false starts before we landed on a good component structure that allowed for us to do what we wanted. My intended focus was on what learning how to make API calls correctly and successfully using components in ReactJS.

    Not having ever used an API on my own, I thought it would be good to start with some guard rails. We used this tutorial from RapidAPI. It didn’t connect to the endpoints that we needed it to, but that was ok, we needed to figure out how this all worked!

    After we got that working we had a basic web-app with inroads of our desired core functionality. We took a step back and discussed what we needed to do differently to get where we wanted to go. Notably, we wanted to get the weather conditions for the next 5 days, not just the current weather. This required using a different API endpoint which required latitude and longitude. So, we doctored up our code to hit the appropriate API endpoints and we were in business.

    At that point, we were manually entering Pittsburgh’s latitude and longitude to test. No good! Naturally that’s not a reasonable way to have user’s enter their location. Turns out we needed to connect to another API to help us transform city names into latitude and longitude coordinates!

    Mapbox was the ticket. We used their forward geocoding feature of the API. At this point we had the intended usage for the application’s user interface.

    Because Javascript is a collection of asynchronous processes, it was necessary to chain the calls in such a way where you never call the Openweather API until you’ve gotten a successful response from the Mapbox API. As you’ll see below the two fetches are linked by a callback that you can see in line 29.

    Figuring this out was its own kind of puzzle. I had a lot of fun figuring out how to make this work. This post on how to use the fetch() method to make multiple API calls with vanilla JavaScript was immensely helpful.

    Here’s a look at the function that makes this work!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    
    function getWeather(e){
        e.preventDefault();
        console.log("CITY UPON BUTTON PRESS: ", city);
        // Clear state in preparation for new data
        setError(false);
    
        console.log("in getWeather")
        setResponseObj({});
        setLoading(true);
        setSafe(false);
    
        var post;
    
        // Call the mapbox API
        fetch(`https://api.mapbox.com/geocoding/v5/mapbox.places/${city}.json?access_token=MAPBOXACCESSTOKEN`).then(function (response) {
            if (response.ok) {
                setLoading(false);
                return response.json();
            } else {
                return Promise.reject(response);
            }
        }).then(function (mapBoxData) {
    
            // Store the post data to a variable
            
            // responseObj = data;
    
            // Call the openweatherAPI
            return fetch(`https://api.openweathermap.org/data/2.5/onecall?lat=${mapBoxData.features[0].center[1]}&lon=${mapBoxData.features[0].center[0]}&exclude=minutely,hourly&units=imperial&appid=MAPBOXAPIID`);
    
        }).then(function (response) {
            if (response.ok) {
                return response.json();
            } else {
                return Promise.reject(response);
            }
        }).then(function (weatherData) {
            console.log("userData is: ", weatherData);
            responseObj = weatherData;
            setResponseObj(weatherData);
    
            setSafe(true);
            console.log("STORED AT RESPONSE OBJ AT THIS MOMENT: ", JSON.stringify(responseObj));
    
        }).catch(function (error) {
            console.warn(error);
        });
        
        return; 
    }
    

    We passed the OpenWeather response object over to the conditions component, which contains the strip components.

    <Conditions
    // this component holds our strips.
    responseObj={responseObj}
    error={error} //new
    loading={loading} //new
    safe={safe}
    />
    

    Each strip was its own component that was passed a copy of responseObj so that it could pull out what it needed from the JSON blob. The strips were able to be handle the data according to the pertaining day via the day variable. The whichStrip variable controlled how the CSS rendered each strip’s color.

    <Strip whichStrip="StripOne" responseObj={props.responseObj} safe={props.safe} loading={props.loading} day={0}/> 
    <Strip whichStrip="StripTwo" responseObj={props.responseObj} safe={props.safe} loading={props.loading} day={1}/> 
    <Strip whichStrip="StripThree" responseObj={props.responseObj} safe={props.safe} loading={props.loading} day={2}/> 
    <Strip whichStrip="StripFour" responseObj={props.responseObj} safe={props.safe} loading={props.loading} day={3}/> 
    <Strip whichStrip="StripFive" responseObj={props.responseObj} safe={props.safe} loading={props.loading} day={4}/> 
    

    Each strip is constructed as follows. You can see the whichStrip prop that is passed into this component dictates what class is used to style the strip.

    <div > 
        <container>
            <section className={props.whichStrip}>
            <p>{props.safe ?  "Lo: " + JSON.stringify(props.responseObj.daily[props.day].temp.min) + "°F" : ""}</p>
            <p>{props.safe ? "Hi: " + JSON.stringify(props.responseObj.daily[props.day].temp.max) + "°F"  : ""}</p>
            <p>{props.safe ?  "Main Description:" + JSON.stringify(props.responseObj.daily[props.day].weather[0].main) : ""}</p>
            <p>{props.safe ?  "Sub Description: " + JSON.stringify(props.responseObj.daily[props.day].weather[0].description) : ""}</p>
            <div>{props.safe ? <img src={"http://openweathermap.org/img/wn/"+ iconId + "@2x.png"}></img> : ""}</div>
            </section>
        </container>
    </div>
    

    It’s not the cleanest or the most clever code, but it gets the job done and I want to show my work here! It’s a little clunky and could work far more efficiently. But it works! And that’s what counts for me and Missy in our journey of knowledge. Missy has been having lots of fun playing with the styling, as you can see in the GIF above. It’s wacky and I love it.

    Missy has a big vision of what she wants this web app to be in the future. Based on the weather the user gets all kinds of different suggestions to help them have a cheery day.

    ☁️Whether or not the weather is “good”, there’s lots you can do to have a good day. ☁️

    The idea is to create a table of weather conditions that dictated different outputs. For example if it is sunny but the high temperature is less than 35°, it makes sense to suggest going outside as it’s likely going to be a cool and crisp day. Likewise, say it is above 80° and OpenWeather says the weather can be described as “heavy rain”, it’s going to be a muggy day where you’ll likely be cooped up inside. Board games with cool drinks are likely a good suggestion.

    Idea: Build a table of activity suggestions that are offered to the user for suggestions as to what they might think to do in the upcoming days. The idea would be to have a collection of rainy weather activities that are randomly selected. ⛅

    This is something that Missy and I need to sit down to do. Another thing we were thinking of was connecting a recipe API that would be called and passed different variables based on the weather conditions. Fish tacos recipes when it’s thundering, mimosas when it’s hailing, etc…

    As you can see the weather can trigger a lot of different responses. Rather than lose ourselves in the sprawling options I’m going to let this project rest right now and will return to it with Missy when we’re ready to see it through!

    In the future, I’d like to return to when I have more ReactJS experience under my belt so that we can restructure this to be optimized. I’m going to take a pause from working on this and am going to work on a new, similar web app that for the moment I’m calling: WHAT SHOULD I PLANT. This web app aims to be a minimal, clean design that allows a user to get help deciding what to plant at any given moment in the year in North America. I’ll be connecting with the Trefle API to do this.

    The goal for this will be to create a streamlined web app that offers a useful digest of information to gardeners to make informed planting decisions. I picture this could be useful to more casual gardeners that don’t necessarily plan out a whole growing season from the beginning.

    Weather-Or-Not taught me that things can get hairy, fast! I will be building this new web app primarily as a text based interfact, no CSS. Once I get that output in a form that works I can build out a simple HTML + CSS design with components.

    🌱Let’s see how that goes.🌱

  • As Serious As Your Life

    4 panel comic that reflects on the vanity of needless busyness,

    Death is around the corner. How we come to terms with, that is the business of our living.

    Don’t work so hard. You’ll likely regret it.

  • Willful Blindness

    4 panel comic that references Toni Morrison's 1993 conversation with Charlie Rose urging people to think of anti-racist work as the responsibility not of Black Americans but that of White Americans.

    History is not the past, history is the present. We carry our history with us. To think otherwise is criminal. -James Baldwin

    Nothing fancy here. Just a straighforward public service announcement.

    Whiteness is a dangerous, violent concept. It isn’t about skin color. It’s not even about race. I mean, it is, and it isn’t. Fundamentally it’s the symbol of those appearances and lineages used to implement a willful blindness used to justify white supremacy. Whiteness mutates as the needs of the shape of the hegemony of whiteness shifts. It’s a deft chameleon. It is about using moral rhetoric to defend exploitation, racism, mass murder, reigns of terror and the crimes of empire. It is necessary to justify the sins needed to satisfy our ancestors’ greed and our comfort.

    This is the history of whiteness. Reckon with it and see yourself as you truly are.

    Then, build a better world.

    For context, I’m white and latinx. I’m a first generation immigrant to the U.S.A. from Venezuela and of Spanish descent. This is my history.

    Further Reading/Watching:

  • S-N-A-K-E-S

    Front and Back Cover of "Snakes" First Spread of "Snakes" Second Spread of "Snakes" Third Spread of "Snakes"

    This is a zine I made when Simon Reinhardt was visiting Pittsburgh in April of 2017 for PIX, the Pittsburgh Independent Comics Expo. It was a confusing time, so naturally, this is a confusing zine.

    It was made from a collection of drawings that I was making with a chunky, Sharpie Flip Chart marker while out and about on index cards. This was done at the peak of working for Frank Santoro so his predilection for Matisse-like mark-making and notecard technique was rubbing off on me. It was also the beginning of my burn-out from working with Frank.

    I had just started working at the Greater Pittsburgh Arts Council, was running the then 3-times monthly comics salons, was still doing a radio-show on WRCT-Pittsburgh, and the daily news blogging on Comics Workbook was going full-steam. I was coordinating workshops at PIX that year with Frank and Sally Ingraham and it was just too much. I was really hungry for experience and opportunities for growth at the time so I was afraid of saying no to things, but it broke my back.

    Flip Chart Marker

    In the face of the daily exhaustion, I found the Flip Chart Marker drawings immensely helpful. The lines went down with immediate impact. In the little time that I had to draw on the bus or waiting between jobs I could draw lines that felt like someone else was drawing them. (I don’t particularly recommend these markers other than for ephemeral drawing - These markers aren’t made for archival use so the drawings fade quickly. And if you spill water on them, the pigments composing the colors spread out real wild-like.)

    This zine comes from trying to make a special, strange object with comics-energy from the pieces of my ongoing notecard drawings. Simon and I stayed up late to make these zines and had them ready for the Expo. He was doodling some snakes and I asked him if I could photocopy them and include them in the zine. It creates a silly, bizarre tension between the drawings of people around town. It also takes me back to a moment of late night creative friendship with Simon. I love it.

    It was exciting and fun to have this strange little zine to people. Looking back on it, I’d say this was the first zine that I’m truly proud of. It speaks to a certain aesthetic mystery that I’ve tried to pursue over the past 3 years.

subscribe via RSS