OCTOBER 11, 2019

If you want to add the cs files from one Visual Studio solution (or project) into another, without duplicating the cs files or moving them over, you can simply use the Add > Existing file.. option, making sure that instead of selecting the files and clicking Add (which would copy the files over to your project folder duplicating them) you click on the small arrow and click Add As Link. The files will be linked to your project as a reference to the other project, and editing them will change their code for both Visual Studio projects.

OCTOBER 8, 2019

The short answer is that you can't. But there's a workaround.

Let's say you have a newsletter design as follows, which shows the post image, followed by its title and full content.




The *|RSSITEM:IMAGE|* RSS merge tag will pull in the image and assign to the the created img element the width and height corresponding to the original size of the image. Something like this (which is an example extracted from my Mailchimp campaign using the design template above).

<img class="mc-rss-item-img" src="https://nono.ma/img/u/sketch-170202_cambridge-clary-st.jpg" height="1868" width="2500" style="height: 1868;width: 2500;">

The problem is that we don't want to explicitly specify the height and width values of our image, as its oversized compared to the width of our design, which in my example was 600px plus margins, which was leaving 564px for the width of the image itself.

Here's the workaround: You create the image's img HTML element yourself, formatting it as you want, and use the RSSITEM:ENCLOSURE_URL—which according to Mailchimp "Displays the URL for the attached file [of your post]." In my case, the RSS feed is using the enclosure tag to send the image URL.

// RSS feed item enclosure tag
<enclosure url="https://nono.ma/img/u/sketch-170202_cambridge-clary-st.jpg" type="image/jpeg"/>

Then I can use that URL in my Mailchimp design as follows (also adding the post's title and full content below the image).

<img src="*|RSSITEM:ENCLOSURE_URL|*" style="max-width: 100%">



OCTOBER 8, 2019

It snowed two days ago, the snow melted yesterday, and Cambridge is sunny today. With clear skies, temperatures go low.

I had been learning Go programming all day and needed a break. My first thought was to go for a walk or sketch outside, but I didn't really felt like going outside in such cold weather, so I decided to draw the same house my mom had sketched six months before from my window. I didn't notice the amount of cables until I sketched them.

I wrote those words the morning of February 2, 2017, right before sketching this view from my desk. A year and a half before, in August 2015, I would arrive to our shared student apartment in 8 Clary St, Cambridge, Massachusetts.

My room was a spacious studio originally meant to be our living room, one of the most special places I've lived in that became my home for the three winters to come. I probably spent thousands of hours meditating and starring out of my bow window, talking on the phone and working at my desk—a two-and-a-half-meter-long kitchen top from IKEA, finished in beech, sitting over two black table legs.

Looking out the window, I've seen my girlfriend, family, and friends—including roommates and podcast guests—get home; my bike locked to street signs; random passersby walking along Prospect St; and the white snow cover the streets in winter.

I captured my room and a few other spaces in Cambridge the months preceding my departure in the form of 360-degree virtual reality panoramas that I revisit from time to time using a simple Google cardboard set. I keep surprising myself with the power of these virtual reality scenes—which include sound and imagery—to bring me back to Cambridge. If only for a second, I'm fooled into thinking I'm still there; biking from Clary street to Harvard and then to MIT, commuting to Boston Seaport, or simply hanging out with friends for dinner. Sweet memories.

I'm not sure how many times I looked out that window, but looking at these sketches sparks joy.

OCTOBER 1, 2019

In 2011, I found this blue hat in a thrift store in Raleigh, North Carolina. Looks good! I thought to myself while trying it out in front of a mirror—I bought it for seven dollars.

Even though I remember owning (and wearing) hats when young, I was not a big fan of hats during my teenage years, probably, because I had short hair and I don't like to wear hats when my hair is too short. It wasn't until I started letting my curls grow—and found this blue hat—that I started wearing them.

"Tri State Tank West, Inc. Sacramento, CA," reads the cap. It's a Calhead style #92 made out of cotton and polyester in Taiwan by California Headwear (Calhead), 661 Rio St. Los Angeles, California, 90023.1

I searched the internet for references to California Headwear and their style 92 and found similar hats, also from Calhead, sold as vintage hats on sites like eBay. Air Space America 88, Jack Daniels, Iowa Rose Bowl 1991, Ross for boss 1992, Chip, Dole Hawaii. Then, googling Tri-State Tank West, I found two hats of the same exact design but different color—red and white—on sale on eBay, listed as Vintage Tri State Tank West Sacramento California Baseball Hat Red Snapback Cap. Their price? $41.41 and $51.97.

Ever since I bought it, this has been my hat. I've wore it on sunny and cloudy days, not only while living in Raleigh but on trips around the world, including Australia, London, Spain, Greece, Cambridge, and many, many other places. (I also wore it in this short film recorded in the desert of Almería.)

Now, I have it here with me in San Francisco, California. After eight years, it's getting old. So it might about time to get a new one.

  1. Tri-State Tank West, Inc. seems to be a truck tank company created back in the 1980s. You can buy some of their swag online—including keyrings. California Headwear is the manufacturer that made the hats for them. ↩︎

SEPTEMBER 27, 2019

What does it take for a complex idea to develop? Ingenious ideas are often attributed to an inventive hunch, a sudden spark in someone's mind—think of Newton's apple—yet they commonly grow over the course of several years, if not decades.

Please enjoy this episode with Andrew Witt on the power of ruminating ideas, understanding complex problems, curating signals, geometric simplicity, introspective automation, and finding time for reflection.

Listen to "Andrew Witt — Letting Ideas Grow"

SEPTEMBER 24, 2019

Russ Chauvenet was a chess champion and one of the founders of science fiction fandom. In October 1940, Russ himself coined the term fanzine in one of the issues of his fanzine publication titled Detours.1

A zine is a self-published work of text and images to distribute original or appropriated content. In December 2018, I bought a monochrome, two-sided, A4 laser printer and a long arm stapler to produce A5 zines in-house.2 You can print on regular paper or, as I'm in love with, on recycled 80-grams paper, which makes zines look like a paperback publication with the right typeface and layout.

Thousands of years ago—well before the invention of the printing press—civilizations used stamps and presses to reproduce documents. Today, home printers, copy machines, and publishing software are widely available.1

I print my writing drafts to review and edit away from the screen. The experience is closer to reading a physical book than to that of reading an article online. Gifting a physical booklet is a great way to share my writing instead of sending a digital version to somebody's busy inbox.3

  1. Zine on Wikipedia. ↩︎ ↩︎

  2. I bought the simple and robust Brother HLL2375DW printer and a Rapesco 790 stapler. ↩︎

  3. As a curiosity, in the 1920s, science fiction magazines would publish readers' addresses in a column so readers would be able to exchange letters. ↩︎

SEPTEMBER 17, 2019

I've been living in a small apartment in downtown Málaga for the past seven months. Two people producing one or two bags of trash per week—mainly food packaging and spoiled items—bringing them to a nearby dumpster and starting over again.

In May 15, 2019, two Limasa trucks were collecting trash at La Plaza de la Merced. The small vehicle brooms and sucks the garbage that people mindlessly drop on the floor and accumulates trash from street sweepers as well. While I was sketching, this little truck moved from right to left to release all of its trash into the bigger one, which also collects trash from street containers.

It's become part of our daily lives. Trash cans, street sweepers, and a variety of vehicles keeping the streets clean for us and bringing our waste to landfills. We rarely stop and ask ourselves whether we should produce less trash and how to do it.

Could our individual decisions make a change or do decisions need to be made by the cities and entities who supply us with goods? I'm a bit skeptical of the real impact our individual decisions as consumers have, but that's a story for another day.

SEPTEMBER 11, 2019

As a security mechanism, Windows natively lets you unzip files by right-clicking and choosing Extract All.. Well, you can skip the manual unblocking of the files by using 7-Zip to extract the files instead of Windows’ mechanism.

We want to get rid of a message you might have seen over and over when downloading files from the internet. "This file came from another computer and might be blocked to help protect this computer," next to an Unblock button. If you know about this, it's fine to unblock a couple files, but it's really annoying when you download a zip containing dozens of files which you have to unblock individually, one by one.

Download and install 7-Zip and unzip downloaded plugins with right-click > 7-Zip > Extract here, or any of the other extraction options.

This issue has given me a lot of headaches when installing both Dynamo and Grasshopper plugins, but you might run into this issue in other environments as well. I'm glad there's an alternative to unlocking each file--might it be DLL, gha, gh, dyn, PDF, exe or files in another formats--separately, unzipping a group of files, all unlocked, at once.

SEPTEMBER 10, 2019

By default NPM—the Node Package Manager—uses its own public registry (at https://registry.npmjs.org) to pull down packages when you run npm install or npm update inside of a project.

You can specify different registries at multiple levels or scopes to override these default value (and other configuration settings). Ideally, when working on projects that require a specific registry—due to security or maybe just because some packages are inside of a private repository—you would set NPM to look for packages on that registry inside of the project folder.

Command level (only affects the command itself)

npm install --registry=https://some.registry.url

Project level (these would be the contents of the .npmrc file inside of the project folder)


Global (these would be the contents of the .npmrc file inside of your system user folder)


How to check your configuration is working

Run the npm config list command to see what variables are set. If you run this in a project folder with an .npmrc file you should see its overriding configuration settings in the folder, and the system global settings after that.

If you run the command in any other folder (without an .npmrc file with custom settings) you should see whatever is set in the global .npmrc and then the default configuration values of NPM.

SEPTEMBER 10, 2019

A cheat-sheet for mathematical notation in [JavaScript] code form.

SEPTEMBER 10, 2019

If you squint, people's faces start looking more and more alike, until they're all just blobs.

That's a simple way to abstract a drawing.

As a short-sighted person, this happens to me all the time, objects blur more and more the farther away they are. And I might be fooling myself, but I'm still at the edge of not needing to wear glasses on my day to day. I just use them while driving, watching movies, or attending to a presentation.

Sketches of people wandering around the streets make some of the most attractive pages in my sketchbook—people stare at them, probably completing the missing parts in their minds, as the sketches are made out of rough strokes without much detail.

What's calling people's attention? I believe it's the cheerleader effect, also known as the group attractiveness effect.1 According to the research carried out in 2013 and 2015, the effect is the cognitive bias which makes us think that individuals are more attractive when they are in a group.

I don't think any of those individual sketches of people are perfect or specially attractive on their own but being part of a page seems to make them more attractive. The pattern—not its individual elements—is easier to like.

What do you think?

  1. Apparently, the phrase was coined by Barney Stinson in an episode of How I Met Your Mother first aired in November 2008. (Read on Wikipedia.) ↩︎


Today I've automated the backup of the configuration, database, and static files of all the websites I manage. Two hours and a half that will save me a lot of time in the coming future, and remove stress when weird things happen. The backup—of six websites in three different servers running Laravel—downloads a copy of the database, the .env files, and the static files (a zip with the contents of the public folder) of each site.

I'll probably open source these scripts in the near future.

One new thing I learned was creating bash functions, like this one.

# create a variable with current date, formatted as yymmdd_HHMMSS
DATE_NOW=$(date '+%y%m%d_%H%M%S') 

# function that zips something and removes it
zip_and_remove() { cd $1 && zip "$2.zip" $2 && rm $2 && cd .. }

# function that downloads a file via ssh then calls the previous one
download_zip_remove() { scp $1 $2/$3 && zip_and_remove $2 $3  }

# a function call
download_zip_remove root@ $DESTINATION $(echo $DATE_NOW)_$SITENAME.env


Revit allows you to import PDF and image files from its Ribbon menu. After clicking either button (Import PDF or Import Image) you get the same window, really, just with a different extension pre-selected.

You import a file and place it into a view, and if the file happens to be a PDF file you select a page and a rasterization resolution (in DPI).

Internally, Revit uses the PDFNet library made by PDFTron to manipulate PDF files. One of the operations it seems to use it for is to rasterize the contents of a PDF to be able to display it on a view. This process makes the image data (of the image itself or a rasterized PDF) available inside of Revit. By using the Revit Lookup add-in, I found that the ImageType class offers a GetImage() method which returns a Bitmap object containing that image data.

Remember that, when you pick an existing imported image or PDF, you are selecting what's called an object of the ImageInstance class, which wraps an ImageType object. So we need to get the ImageInstance element, access its ImageType, then get its image data.

Let's see the code.

// This code goes somewhere in your Revit add-in
// Prompt user to pick a Revit Element
Reference pickedObject = UIDoc.Selection.PickObject(Autodesk.Revit.UI.Selection.ObjectType.Element);

// Get Element
Element element = Doc.GetElement(pickedObject.ElementId);

// Get Element Type
ElementId elementTypeId = element.GetTypeId();
ElementType elementType = Doc.GetElement(elementTypeId) as ElementType;

// Do something if object selection exists
if (pickedObject != null)
    // Check if picked element is an ImageInstance
    if (element is ImageInstance)
        // Cast types for ImageInstance and ImageType
        // ImageType Id = ImageInstance Id - 1
        ImageInstance image = element as ImageInstance;
        ImageType imageType = elementType as ImageType;

        // Get image properties
        var filename = image.Name; // eg. FloorPlan.pdf

        // Get imported file path from ImageType
        var filepath = imageType.get_Parameter(BuiltInParameter.RASTER_SYMBOL_FILENAME).AsString();
        var pixelWidth = imageType.get_Parameter(BuiltInParameter.RASTER_SYMBOL_PIXELWIDTH).AsInteger();
        var pixelHeight = imageType.get_Parameter(BuiltInParameter.RASTER_SYMBOL_PIXELHEIGHT).AsInteger();

        // Get image data
        Bitmap bitmap = imageType.GetImage();

        // Save image to disk

Before you go

If you found this useful, you might want to join my newsletter; or take a look at other posts about code, Revit, C#, TypeScript, and React.


If you are inside of a function which uses a type parameter—T—you can do a Console.WriteLine, for instance, to inspect what type is being used on a given function call.

// System.object or other type


Is there a drawing competition? Are you an architecture student? Why are you all sketching around here? Why are you doing this?

People stop by to ask what and why we're sketching, and sometimes to simply watch us doing our thing. They first look at you and your drawing, then they look at what's in front of you, wondering what is so important as to deserve being sketched.

Why are you doing this? It's a relaxing, joyful, and rewarding experience. A meditative moment in which your week finally slows down. There's no need to think about anything else: Just pay attention to what's in front of you and render it in your page.

After deliberating what to draw, the beginning of a sketch—the blank page—can indeed be stressful. Why, then, would you put yourself in such a situation? Well, you start loving the challenge, a challenge that requires your effort and concentration and pushes you to get a tiny bit better every day. Once the drawing is laid out on the page you can continue adding detail and shading and coloring mindlessly, without too much thinking, and feeling a rewarding sense of joy as your sketch gets closer and closer to a finished drawing.

Is there a drawing competition? Not really.

Are you an architecture student? This is a funny one that I'll try to cover in a future post.

Why are you all sketching around here? Frequently, it's just me by myself (or with Mom). But we also meet with the Urban Sketchers group from time to time to sketch a specific place or building altogether.

I'm truthful to the Urban Sketchers manifesto: sketching on location and capturing what I see from direct observation, using my drawings as a story-telling medium.

AUGUST 27, 2019

As soon as I stopped by his butcher stand, Pedro hooked me.

Just one minute away from home, I was wondering around Atarazanas Market on a Monday morning for a quick disconnection from the screen when I discovered Pedro & Isa's modest butcher shop at stall 166–167.

As I stared at their home-made burgers, Pedro offered to prepare whatever burger mix and weight I wanted.

I ended up buying three two-hundred-gram burgers: Chicken with spinach; beef with goose foie; and beef cheek with onion. They tasted awesome. As I handed Pedro 6.50 euros, he mesmerized me with his kind marketing copy: You call us. You choose what, how, when, and how much you want. And I prepare it for you. I do this for restaurants all the time. A fully customized service just one minute away from home.

As every other Monday, the odds were in Pedro's favor. All fish stands close on Mondays, so you either buy fruit, vegetables, or meat. But no fish. And this is probably why I paid attention to his burgers that morning.

AUGUST 6, 2019

On top of being an author and entrepreneur, Scott Young is an ultralearner. After learning MIT's 4-year computer science curriculum in less than twelve months, Scott taught himself four new languages in a year.

In his book Ultralearning—released today—Scott shares the principles and methods that he and other ultralearners employ to quickly master new skills, acquire knowledge, and become good at things that seem impossible to you right now.

Listen to "Scott Young — Ultralearning, How to Master Hard Skills, Outsmart the Competition, and Accelerate Your Career"

JULY 24, 2019

This example uses regular expressions (RegExp) to replace multiple appearances of a substring in a string.

const string = `The car is red. The car is black.`;

const replacedString = string.replace(/car|is/g, "·····");

// returns The ····· ····· red. The ····· ····· black.

Before you go

If you found this useful, you might want to join my newsletter; or take a look at other posts about code, TypeScript, and React.

JULY 24, 2019

Here is an example of nested Promise.all() calls. We are using the Fetch API to load a given path or URL, then requesting the arrayBuffer() of each of the responses we get back. This is a trivial problem if we do it all asynchronously, but we want to do something with the output buffers when we have them all available, and not one by one.

Specifically, this code tries to (1) fetch an array of images; (2) get their array buffers; (3) then obtain their base64 representation. In essence, map an array of images (by providing their paths or URLs) to their corresponding base64 string.

While this technique works in both TypeScript and JavaScript, the code is only shown in TypeScript.

Approach 1: Verbose

const images = [/* Array of image URLs (or local path if running in Electron) */]

Promise.all(images.map((url) => fetch(url))).then((responses: any) => {

    return Promise.all(responses.map((res: Response) => res.arrayBuffer())).then((buffers) => {
        return buffers;

}).then((buffers: any) => {

    return Promise.all(buffers.map((buffer: ArrayBuffer) => {
        return this.arrayBufferToBase64(buffer);

}).then((imagesAsBase64: any) => {

    // Do something with the base64 strings


Approach 2: Simplified

const layerImages = [/* Array of image URLs (or local path if running in Electron) */]

Promise.all(layerImages.map((url) => fetch(url))).then((responses: any) => {

    return Promise.all(responses.map((res: Response) => res.arrayBuffer())).then((buffers) => {
        return buffers.map((buffer) => this.arrayBufferToBase64(buffer));

}).then((imagesAsBase64: any) => {

    // Do something with the base64 strings


Array Buffer to base64

// source: stackoverflow.com
private arrayBufferToBase64(buffer: any) {
    let binary = "";
    const bytes = [].slice.call(new Uint8Array(buffer));
    bytes.forEach((b: any) => binary += String.fromCharCode(b));
    // Inside of a web tab
    return window.btoa(binary);

Before you go

If you found this useful, you might want to join my newsletter; or take a look at other posts about code, TypeScript, and React.

JULY 19, 2019

Technologist and artist Cristóbal Valenzuela co-founded Runway with a simple idea in mind: putting machine learning in the hands of creators as an intuitive and simple visual interface.

We are on the verge of a new creative revolution. [Machine intelligence] is producing radical changes in the way digital content is made, understood, and processed, unfastening previously unimagined ways of creating.

Enjoy this conversation on how to power your creative work with artificial intelligence, and Cristóbal's take on simplicity, life, work, and creativity.

Listen to "Cristobal Valenzuela — Machine Learning for Creators"

JULY 10, 2019

It's convenient to deploy a single Laravel application and then point multiple domains to it and have different configurations (and databases) for each individual domain. This means that you can reuse your code and only deploy once if all of the websites share the same resources, and then just specify a custom .env environment file to configure each domain entry point.

The first thing you need to do is to add one .env per domain. (Leave your .env file as a default, which would be used as a fallback for domains where you haven't explicitly created a custom .env file.) For the domains you want to have their custom config, add an .env file attaching the domain name to the end of its filename, like .env.nono.ma, for instance.

Then add the following code to your bootstrap/app.php right before returning the $app.

// bootstrap/app.php

// ...

| Load domain-specific .env file if it exists

if(isset($_SERVER['HTTP_HOST']) && !empty($_SERVER['HTTP_HOST'])){
    $domain = $_SERVER['HTTP_HOST'];

if ($domain) {
    $dotenv = \Dotenv\Dotenv::create(base_path(), '.env.'.$domain);
    try {
    } catch (\Dotenv\Exception\InvalidPathException $e) {
        // No custom .env file found for this domain

// ...

return $app;

I've tested this code with Laravel 5.8 and it works like a charm.

JULY 9, 2019

Important Looking Pirates on rendering Westworld:

For all the character work on Westworld, we used Arnold. It’s perfect for preserving detail in skin shading and also handles hair/fur very efficiently. For shading, we quite often work with Anders Langlands, alShader and also use shaders written here at ILP. Besides Arnold, we also used V-Ray for the train station sequence.

Bobo Skipper (VFX Supervisor of Important Looking Pirates):

We started our shot production for Westworld in early February 2016. The size of the team varied depending on what episode we were on. At times we were about five people and other times around 15. In total, we delivered around 65 shots.

We were so excited when Jay Worth (VFX Supervisor) approached us. The show looked promising, and there were a lot of cool shots planned. Our goal is always to deliver the best possible quality, and for all the VFX we did on "Westworld" the most important thing was that shots helped drive the story. I think the first season turned out to be incredible and I’m proud of our contribution to the show.

In general, the challenge was to deliver high-quality shots for all our sequences. A few of the extra tricky ones included creating a young version of Anthony Hopkins, a big terraformer digging up dirt and rock and the sequence of the robot boy opening up the face.

Read the full article on Autodesk AREA.

JUNE 30, 2019

Over the last months, I've been questioning why the streets of my hometown are flooded with electric scooters, at the same time that I keep asking myself if I should continue using social media and how.

In this essay, I briefly explain the way Amish communities decide whether to adopt a given piece of technology, and, hopefully, convince you that our modern communities—and ourselves as individuals—can learn from why and how the Amish do it.

Read "Would The Amish Ride Electric Scooters?"

JUNE 26, 2019

—Wake up.
—Oh God, another day? Boy, this hurts.

Simplicity might well be the art of hiding the messiness involved in our creative processes. (Drafts and versions; cutting and pasting; design tools; projects, clients, and deadlines.) Even when new technologies facilitate our arts and crafts, traditional methods may still work better than anything made today.

Enjoy this conversation with a maximalist artist living a simple life doing what makes him (and others) smile.

Turns everything off and goes outside.

Listen to "Pier Gustafson — Drawing Fast, Thinking Slow"

JUNE 12, 2019

Simplicity is an emerging trend; a luxury not everyone can afford.

For the last 10,000 years, human biology has barely changed — yet our lives feel more complex, accelerated, and stressful than ever before.

What are we trying to slow down from?

🎙 Listen to "Panagiotis Michalatos — Slow Down From What?"

JUNE 6, 2019

Hi Friends— 👋🏻

I'm excited to be preparing a newsletter to share my sketches with you on a weekly basis. Each week, subscribers will receive a sketch paired with a short essay. The drive of this project is to sketch and write daily, and to have a medium to share my drawings independent from social media. 👨🏻‍🎨

Curious about the format? Here's a sample email.

If you feel this is your kind of thing, here's how to join.

JUNE 5, 2019

Now it’s incredibly simple to start building a native Mac app from your current iPad app. Your apps share the same project and source code, so you can efficiently convert your iPad app’s desktop-class features, and add more just for Mac.

Apple seems to (finally) have started blurring the edges between what it means to be an iPadOS and a macOS app.

If your iPad app would make an excellent Mac app, now is the perfect time to streamline your code base and bring your app to life on Mac. The beta version of Xcode 11 is all you need. Begin by selecting the “Mac” checkbox in the project settings of your existing iPad app to create a native Mac app that you can enhance further. Your Mac and iPad apps share the same project and source code, making it easy to change your code in one place.

Want to see older publications? Visit the archive.

Listen to my Podcast.