Tuesday, June 24, 2014

Simplifying the Terms of Service

At the GDISF study group last night, one of the attendees was working on the Terms of Service for a new site, and she wanted to give the users a way to see the layman-friendly version of the terms. She was inspired by the "Simply Put" right hand side of the Pinterest site, and was experimenting with other ways to present that.

Pinterest:

I'd never seen that sort of thing before, and I think it's pretty neat, so I asked on Twitter for more examples. Here are a few they shared:

500px:

CodePen.io:

Aviary:


Related to this, there's the Terms of Service; Didn't Read initiative that comes up with layman-friendly version of the top TOSes, and there's a list of related efforts to simplify terms and identify ambigious terms from CommonTerms.

How do you make your Terms of Service layman-friendly? Tell me in the comments!

Thursday, February 27, 2014

The Long Lunch Table

For the last two years, I've had the pleasure of working for companies that are still small enough to fit in a room; small enough so that everyone can squeeze at the same lunch table. Even at Khan Academy, where we now have almost 50 people in the office, we have a long table made up of many tables, squished together so as to appear a continuous structure. I never really thought about that until today, when we were talking about plans for our new office.

You see, our small company is getting bigger, and we're moving into a larger space. We have to decide which of the traditions and configurations to bring over from our current space, and which to leave behind as a thing-we-did-when-we-were-smaller. One of those is the team lunch. Our office admin announced to all of us that they're working hard to make sure that we can continue to all eat lunch together. A devil's advocate amongst us responded with "Why? Why do we need to eat lunch at the same time and same table if we can only hear a 4 person radius around us?" He had a good point, yet he also provoked a visible gut reaction in many. But, why? What reasons did we come up with?

We kerfuffled for a bit, trying to justify our insanity on holding onto our irrational needs, until my colleague spoke up. He told the story of lunch at his last company, which was a few times larger. They had a long lunch period, with many small lunch tables in a big cafeteria, and employees were expected to lunch at different times, to distribute the lines over time. Employees would walk in, look around at the lunch tables, not see anyone they knew - or not see anyone they felt confident in table-crashing - and go back to their desks. Eventually, many of them defaulted to eating lunch at their desks. Lunch had gone from being a social affair to being a daily reminder of loneliness.

In fact, when he recalled this, I remembered feeling the same way at Google. Sure, I would know people scattered around the tables in the cafeteria, but it took guts to feel like I could impose myself on any given table. There were days that I couldn't muster up enough of those guts; and those were the saddest.

And now, finally, I realize the simple brilliance of the long lunch table and the single lunch period. When you get your food, you don't have to gather the confidence to approach a table - you just look at the long table, pick the next logical available seat, and sit there. That's what everybody does, and there's no expectation that you have to ask to do that, because, what else would you do?

Maybe the long lunch table is why I look forward so much to lunch every day at Khan Academy. It's certainly not that I dislike my work, but I adore our lunches: I don't have to stress about where to sit, and I know that wherever I sit, I'll be surrounded by some subset of my smart and funny colleagues.

Here's to hoping that we can keep our lunch table long for as long as possible.

Thursday, January 30, 2014

Improving front page performance: removing images, 5 ways

We regularly hold Fix-Its at Khan Academy, where we take a day to work on the little things that pile up, the bugs and tweaks and optimizations we don't find the time to do otherwise. On Tuesday, we had a Fix-It dedicated entirely to performance, and we made a Trello board of performance improvement ideas, many of them around speeding up our server-side calls.

I decided to tackle the frontend, starting with the very first experience a user has on Khan Academy: the logged out landing page. My colleague told me there were some images that could be delay loaded on it, a technique that I'm familiar with, so I logged out, opened up the Chrome Dev Tools Network panel, and checked out the HTTP requests (particularly the pre-DOMContentLoaded ones). Sure enough, lots of image requests!

Here's a screenshot of the page, with the various images circled in red:



Some of those images are "above the fold", meaning they're visible without scrolling, while others are "below the fold", requiring varying degrees of scrolling to see. This is an important distinction to make, because most users do not scroll on our landing page - most will go straight to signup, which is what we want to happen, and have optimized for in numerous A/B tests. Depending on their position on the page, I used different techniques to deal with each image. Let's go through them, shall we?



TinyPNG

For many of the techniques below, I first put the images through TinyPNG to optimize their size, and often achieved 50%-75% compression, without discernible loss in image quality. Plus, I made a Panda happy!


Top Logo: CSS Data URI

HTTP Requests saved: 1

The top logo is displayed on every Khan Academy webpage, so it will need to get downloaded by ever user in some form. Since we're already sending down a CSS file on every page, and the logo is a fairly small file (2KB, after compression), my colleague suggested just inlining it as data URI in the CSS file.

Thanks to the magic of all of our conversations happening in HipChat, I then found out that my colleague Craig Silverstein actually made it so that our CSS build process will automatically Data URI an image that's used as a background-image, as long as it's sufficiently small size and only included in one CSS package or if it has a /* data-uri */ comment next to it. If I hadn't had that option, I would have used one of the online converters - but I'm happy I get to keep our CSS files clean and readable!


Login icons: Sprites FontAwesome

HTTP Requests saved: 2

CSS sprites are a now classic technique for saving HTTP requests for the commonly used little images on your site, condensing them all into one image and using background-image/background-position magic. That seemed like the obvious approach at first for the remaining above-the-fold images on the page, the login icons and the purple leaves background. I optimized the images, uploaded them to this online CSS Sprite generator, and set their new CSS rules, happily turning 3 HTTP requests into 1.

However, my colleague then informed me that we actually had FontAwesome icons (in our custom build!) that looked nearly the same as the Google and Facebook login icons, and he'd been meaning to change those over. We already send down FontAwesome with every page, because we use their icons so heavily, so it made sense to give up images entirely and just use the FontAwesome classes.


Featured Images: Delay Load

HTTP Requests saved: 4

We display three images related to featured content just below the fold, which we don't want to sprite because we change them up a fair bit, but we also don't want to load for all the non-scrolling users out there. So I implemented this delay-loading technique for the images, which basically entails adding a scroll handler, checking if the desired DOM elements are within view or within some threshold of being in view, and swapping out their background-image or src if so, based on data attribute values.

Here's the generalized delay loading code that I wrote as a simple jQuery plugin:

Here's example HTML for one of the images:

<div data-delayed-bgimage="https://www.kastatic.org/images/featured-actions/pollock.jpg">
</div>

And here's the JS that calls the delay loading plugin for those images:

var maybeLoadMedia = function(nearThreshold) {
    $("#homepage [data-delayed-bgimage]").each(function() {
        $(this).delayLoad(nearThreshold);
    });
};

// On scroll, use very large threshold. Most people don't scroll homepage,
// but if they do, we want them to see everything.
$(window).on("scroll.load-media", _.throttle(function() {
    maybeLoadMedia(600);
}, 100));

// Start with no threshold, items must be visible
maybeLoadMedia(0);

Youtube Video: Delay Load

HTTP Requests saved: 1+

Way below the fold, we embed an iframe of Sal's TED talk. It's a great talk, but once again, most users won't make it this far. We use the same technique as for the images, with one difference: for img tags, we start them off with an empty src attribute. However, that's not a valid value for src for the iframe, so we start the iframe off with src="about:blank". Ben Vinegar, an iframe wrangling expert from Disqus, suggests it's even better to completely create the iframe from scratch, but since the src swapping worked, I went the simpler route this time.

Here's what the HTML looked like:

<iframe width="560" height="315" frameborder="0" allowfullscreen
  data-delayed-src="//www.youtube.com/embed/gM95HHI4gLk" src="about:blank">
</iframe>

And the JS was pretty much the same:

var maybeLoadMedia = function(nearThreshold) {
    $("#homepage .youtube-video iframe").each(function() {
        $(this).delayLoad(nearThreshold);
    });
};

$(window).on("scroll.load-media", _.throttle(function() {
    maybeLoadMedia(600);
}, 100));
maybeLoadMedia(0);

Social Icons: Delay Load

HTTP Requests saved: 0 (all were async tags)

We also display a host of social icons next to the video, and we have to load in the relevant JS APIs for each of those, often via dynamically appending a script tag. We set the async attribute on all of those, so they were not affecting our DOMContentLoaded time, but hey, might as well delay load them! No sense in making users do HTTP requests for things they won't need.

var maybeLoadSocialMedia = function(nearThreshold) {
    if ($("#homepage #social-actions").inView(nearThreshold)) {
        _.defer(function() {
            Homepage.initSocialButtons();
        });
        $(window).off("scroll.load-social-media");
    }
};

$(window).on("scroll.load-social-media", _.throttle(function() {
    maybeLoadSocialMedia(1000);
}, 100));

Subscribe icon: FontAwesome

HTTP Requests saved: 1

I started off by delay loading the RSS subscribe icon, but it felt like overkill and I realized there was a much easier approach: just use the FontAwesome subscribe icon, and color it orange. Ta-da, nearly the same!

It was easy to do with this HTML:

<span class="icon-rss-sign"></span>

...and this CSS

.icon-rss-sign {
  color: orange;
  text-decoration: none;
  margin-right: 5px;
  font-size: 18px;
}

Invisible image: Delete!

HTTP Requests saved: 1

After I'd optimized all the images I could see, there was still an HTTP request for an image that I couldn't ever see: our loading gif. I spent a while trying to track down what code was loading it, to see if it was validly being used at some point during the page rendering process. I finally discovered that it was in a CSS rule for an element that was visible on the page - but its visibility was set to hidden. Apparently, browsers (or at least Chrome) will download background-image's for hidden elements. Luckily, I then discovered that it was "dead" CSS - the rule that would toggle its visibility was never getting triggered. We'd stopped using the loading image without removing the associated CSS rules, and that was costing an extra HTTP request. I happily and promptly deleted it, whee.



The Exciting Results!

If you've been keeping score, my changes removed at least 10 HTTP requests, if not more (like additional ones triggered from the Youtube iframe). I recorded load times across 5 page loads in Chrome Dev Tools both before and after the changes, and here are the results:

# of Requests DOMContentLoaded (average) load (average Time between them (average)
BEFORE 65 3.02 5.66 2.64
AFTER 28 1.86 2.00 0.14
% REDUCED 57% 39% 65% 95%

The full spreadsheet is here, and I've also downloaded the HARs from all the loads.

There is still much we can improve - there's a lot of latency and variability in the initial download of the HTML page itself, plus we're passing down several CSS, JS, and font files. But still, it's impressive what we could do in a single day, with just the images. Thanks to those techniques, the page makes it to the DOMContentLoaded event in nearly half the time, and to the load event in less than half the time.

Got any other techniques to share, or tips for how you improve your site's performance? Tell us in the comments!

Saturday, January 25, 2014

Networking at events: It should be easy, not scary

I was at an event the other night and the MC said, "I hope you like networking, because that's what we're here for!" My immediate thought was "Uhhhhhh, no. Networking is the most frightening thing I could ever imagine."

See, when I think about "networking," I picture a room full of people that have to come up with excuses to talk to each other, come up with excuses to stop talking to each other when the conversation has peaked, and keep doing this for hours on end. I can't decide which aspect of that is the worst, because it's all the worst. There are good parts in the middle, when you've discovered your commonality with your current conversational target and you figure out how you can both benefit from learning about each other, but those good parts are sandwiched by anxiety-inducing awkward social situations.

Fortunately, I'm not the only one who finds it hard to approach large numbers of random strangers, and I've been happy to come across multiple forms of more structured networking at recent events. I wanted to highlight a few of them here in this post, to put out ideas for the event organizers out there, and to hopefully find out about other approaches in the comments.

Introductions

I went to an EdSurge Womens Night last fall, and when I walked into the room full of people that I didn't know, much of them in the thick of conversations, I had a shyness attack. I immediately found a corner that wasn't visible from the rest of the room, and busied myself with my phone. And yes, I may have tweet-ranted my feelings a bit, as well. Once I get shy like that, I find it increasingly hard to recover, to muster up the courage to impose myself on someone - so I was ready to call it a failed night and go home.

But then the organizer shushed everyone, gave a little spiel about the event purpose and sponsors, and then encouraged us to give little spiels. She wanted us to let everyone know what we were there for - like if we were looking to hire, looking for a job, looking for partners. She didn't make everyone do it (which would have taken a while) but was encouraging enough that about a third of us took the mic for thirty seconds. I was one of those that gave a spiel, because I knew that I'm the kind of person that needs other people to approach me, especially in the shy state I was in then. After that, we all went back to mingling, but now we all knew a lot more about people that were there and had real reasons to approach each other. I was then busy the entire rest of the night, speaking with a variety of people who were interested in hearing more about what I was up to.

This will not work for every event, due to the time it takes -- but if the event is small enough, a simple round of introductions can do wonders for improving networking at events, for lowering the barrier to approach. There's still the problem of the social awkwardness of leaving a conversation, though, which is where the next strategies come in.

Speed Networking, Pre-Matched

Early this year, I attended an NSF conference for ~300 computer science education researchers. I'm new to the more academic circles, after being so heavy in the "industry" circles for so long, so I knew only a handful of the researchers. It was great getting to catch up with them, but I also wanted to meet a few new folks.

Thankfully, the conference organizers really wanted this gathering to be heavy on connecting and conversing with each other, starting with an unconference style approach to picking session topics and carving out time for 5 attendee-led discussion sessions.

On the first day, they announced a special session right after lunch: speed networking. Before the conference, we had all filled out our particular research interests on the registration website. They ran those through an algorithm to pick pairs of similar attendees, and printed a list of 8 numbers on the back of our name tag, each number corresponding to a pair. When we arrived at the room for the session, we found 150 pairs of chairs with numbers on them, and we sat in the chair with our first number printed on it. For the next hour, we rotated every 8 minutes and met someone completely new each time. It was a great way to meet people I wouldn't have otherwise met, and I found that 8 minutes was enough time to have enough of a conversation to figure out if we should continue talking later (or just to learn something new and move on).

There are a few logistical issues with this sort of session, since not everyone who signs up will end up attending and since the organizers have to pre-calculate the pairs. I had actually signed up too late, after they'd printed the badges, but I just grabbed the badge of someone who seemed similar to me but didn't make it to the conference, and I was happy with my pairs. And in the case that nobody sat across from me, I'd just triple up with people near me. So as it turned out, the logistical issues were quite surmountable, and I think a speed networking session like that would be a fun addition to many conferences.

Speed Networking, Randomized

Just this week, I attended a networking event put on by Berkeley Women in Science. I came as one of the "professional"s, expecting to meet many non-professional students. I was a bit reluctant when they first asked me to attend, because I heard the title "networking" and thought, "oh no, what if they expect *me* to approach people, because I'm so professional?" I expressed my doubts that I would be able to do that effectively and only decided to go when they reassured me that they would be facilitating networking via introductions and other means.

The event started with the MC introducing each of the professionals by name and title, and then we started a speed networking session of sorts. We were instructed to find someone that we hadn't met yet, that was the opposite of us (i.e. I found students because I was a professional). Then they gave us a question that the left partner would answer for 2 minutes and then another question that the right partner would answer. The questions would ask about how we got into STEM, the stereotypes we encountered, ideas for countering them. This went on for about four rounds, and then we went into free networking.

This was an interesting approach because they gave us the questions, removing the pressure of coming up with conversation starters. There were some drawbacks as well, however -- 1) since we found our pairs randomly, we were less likely to meet the most relevant people (I ended up chatting with many microbiologists and no Computer Science majors, which was interesting but non-optimal from a recruiting angle), 2) we didn't have any time for introductions, so we ended up trying to do that quickly or tying it into our answers, and 3) the MCs had to keep shushing everyone to move on to the next question, because people had more to say than they could cover in 2 minutes. I think this could work well with modifications, like having a 2 minute introduction time, and it'd work well at an event where everyone is relevant to each other's interests.

Thursday, October 17, 2013

Digital Learning Apps in Guatemala

In between the talks and workshops that I gave at FIT this week, I also got the chance to talk to many people that are involved in digital and online learning in Guatemala, and was surprised to find out the many ways they're experimenting in the space. I want to highlight two projects here:

Telescopio

This is Galileo University's take on the MOOC format, and is led by GES director Rocael Hernandez. They developed the web app in house, culling together open source projects and APIs into a platform that supports lectures, quizzes, discussions, and peer assessments. They started it off with an iPhone courseand based off the Stanford iPhone course curriculum, and now have 6 engineering courses on it, with 2-5,000 spanish speaking students enrolled in each. They've experimented with various aspects of the platform, like using the Google Docs API to track changes to a document, and have published a few papers in the space: MOOC in Latin America, Implementation of Online course with Accessibility features, MOOCs Concept and Design using Cloud-based Tools.

Cerebrex

This project was initiated by their Education Innovation director Ali Lemus, and is an experiment in finding a new way to teach math and reasoning to young kids. Cerebrex is a game made for Android, iOS, and the web that presents challenges in a Maya-themed setting, translated into the Mayan language of the user (there are something like 30 spoken Maya languages in Guatemala). They trialed it in several classrooms, and saw great results with increased intelligence measurements after the test. Ali told me the story of one student that was young for their grade and bullied for that, but once that student was at the top of the game leaderboard, their classmates suddenly respected them. That's an anecdote, of course, but its promising, especially in a country where students have low confidence about their place in the world to start with (or so I'm told). Ali shared his slides about Cerebrex here.

It's easy to think that it's only Silicon Valley where innovation happens, but really, whenever I visit another country or talk to a foreigner, I find out about the amazing projects that they're working on in the education space, and realize that of course, we're not the only ones. It sounds obvious, typing that now, but it's nice to venture outside and get a reminder of this every so often.

I look forward to seeing what Guatemala does in the education space in the future!

Tuesday, October 15, 2013

1 Day in Antigua, Guatemala: Where to Go, What to Eat

At the end of my trip to Guatemala to speak and teach at the FIT conference, our gracious hosts took us on a day trip to Antigua. Antigua was the second capital of Guatemala, 12-by-12 blocks of colonial architecture and Baroque style cathedrals and churches. After it suffered from an earthquake in the 1700s and many of its structures went to pieces, the capital moved to Guatemala City, where it is now. Antigua is a popular destination for tourists, who can walk amongst the ruined cathedrals and enjoy local food. If you ever get the chance to visit it, here's what I recommend.

Where to go

  • 2013-10-12 at 10.32.53 El Tenedor del Cerro: This little collection of museums and restaurants sits atop a hill, where you can see three of the volcanoes that surround Antigua (2 active ones!). As you walk around and enjoy the mosaic murals and sculptures, parrots from their sanctuary will happily land on your shoulder and tweet away.
  • Cerro de la cruz: Before venturing into Antigua, drive up for a view from the cross. You'll get another vista of the volcanoes (a straight on view of "Agua", if there are no clouds) and a birds-eye view of Antigua. You can also see the first capital of Guatemala from there, if you squint and look for the white church near the base of the volcano.
  • 2013-10-12 at 12.54.36 Las Ruinas: You can wander around giant blocks of cathedral, now the home for beautiful sprouting flowers, and wonder how magnificent they once were, back when the cathedral actually had a roof. Or, if you're like me, you can count the number of times an enamored visitor has proclaimed their love by etching it into the walls, and wonder how many of them actually stayed together.
  • Sereno: A restaurant that doubles as a popular spot for wedding ceremonies, thanks to a rock-studded cave that looks beautiful inside when lit up by tiny white lights.
  • 2013-10-12 at 15.36.10 Hotel Museo Casa Santo Domingo: Another popular spot for weddings, home to an open air cathedral surrounded by ruins. They cover the fountains and grounds with hundreds of candles each night, and if it's a wedding night, *thousands* of candles, which I was lucky enough to witness. The grounds is also home to rather noisy parrots and a chocolate shop.

What to eat:

  • Dulces tipicos: Translated literally, they're the "typical sweets", and they're candies and pastries that are part of the Guatemalan tradition. You will need to pace yourself to try all twenty-something of them, or pick and choose - I tried the sweet coconut bar (a bit too sweet for me), the coconut macaroon (yum, just right), and a macaron-like almond cookie (also yum).
  • 2013-10-12 at 13.13.53Chocolate: Guatemala is home to many chocolate and coffee farms, so you'll find multiple local chocolate shops while walking around Antigua. In fact, you may want to skip eating normals meals and just stick to sampling chocolates. You can try different exotic mix-ins at ChocoLala, like chocolates with rum, ginger, or papaya, or go for more classic chocolate at Guatemala Chocolates, or even go for a chocolate-making class at ChocoMuseo.
  • Steak: You can eat steak the Guatemalan way at Casa Santo Domingo - with guacamole (no tomatoes!), frijoles volteados (bean puree), salsa, and platanos. You'll have to enjoy it with a red wine from Chile, not Guatemala, because it's too hot for them to make local wine, but hey, the Chile wine is highly enjoyable.
  • Ron Zacapa: The native rum of Guatemala, you can drink this straight (if you're into that) or mixed with Sprite and ice. Once you do, you'll likely find yourself buying a liter to bring home for your friends to try. Or you'll just find yourself drunk.

Disfruta-te de Guate!

*I wrote this after reading United Airlines "Hemispheres" during take-off, so, uh, if this sounds too much like an airplane magazine article, blame the fact that I can't use electronic devices on airplanes during take-off.

Monday, October 14, 2013

Shyness Hacks for Conferences

A few years ago, I gave an ignite talk at Google I/O about the ways I'm shy and the many ways I've found to work around my shyness. I recently saw a post on overcoming shyness at conferences on HN, and realized I never formally wrote up my own tips.

Before going into my shyness hacks for conferences, let me clarify what I mean when I say that "I'm shy". For me, it means that I'm afraid of approaching and talking to people, especially when its me and a group of strangers. Ultimately, it's because I'm afraid of rejection. As long as I don't approach people, then I don't have to worry that they will ignore me or turn me away. Sometimes I try to just be a hermit and not worry about my fears, but I soon realize I crave human interaction, and always will. If I'm going to go through the effort to go to a conference, then I don't want to waste that opportunity for interaction.

Given that, here are my shyness hacks for conferences:

Be a Speaker

This is my primary hack. I will almost never attend a conference if I'm not a speaker, because I know that if I'm just there as an attendee, I will spend my time getting shyer and shyer until eventually I'm just reading my book in a corner in the bathroom.

After I deliver a talk to a group of people, there will be a whole room of people afterwards who know who I am and even better, who know what conversation topics they can approach me with. Speaking isn't easy- I still get sick to my stomach just before I talk- but for me, its worth it. When I moved to Sydney and didn't know anyone, I gave two talks at their BarCamp my first weekend there, and that's how I met 90% of my Aussie friends. If you're nervous about speaking in front of a big audience, start small - give a lightning talk or lead a BOF session - that's still a group of people that now know who you are!

Whenever I get the choice of when to speak in an event, I always ask for an early slot - - early in the week if it's a multi-day conference or before lunch if it's one day. I want to make sure that people know who I am as soon as possible so that I can spend the rest of the time hopefully getting approached by them with their thoughts on my talk.

Talk to Speakers

Okay, let's say you really don't want to be a speaker, or you didn't have a speaking opportunity at this conference. Now that you've seen that many speakers (okay, at least one of us) become speakers because they want to be approached, an obvious hack is to talk to the speakers.

I will typically keep a running notepad with the questions that come to my mind during a talk, and then I will often ask one during the formal Q&A, so that the speaker's seen my interest, and save the rest for attacking them after with my curiosity. Most of the time, the speaker is more than happy to answer questions, and loves that somebody is interested enough to ask.

Go to Workshops

Traditional presentations are not very conducive to social interactions. It's a bunch of people, watching a speaker, and the only opportunities to talk to each other are before and after. A workshop, however, is inherently more interactive: there's many a time at which you'll be working on an exercise, and that's a time at which you can talk to the people near you about what you're working on. If you want to be very popular, then try to be the one that pays a lot of attention and can help out everyone else. Otherwise, don't be afraid to ask for help, too. (Just not *too* much).

Be a Conversation Piece

This is a hack that works anywhere in life - parties, cafes, dinners. If I make it so that some aspect of my physical presence provokes conversation ideas, then people will have an obvious and immediate excuse to talk to me.

That's typically in the form of a t-shirt, like a geeky one, an awesome band, or some ironic one from Threadless, but it can also be in the form of a crazy hat or accessory, like my often brightly colored hair or super cute animal socks. I actually don't wear geek t-shirts to work anymore, but I've saved up a spectrum of them so I have appropriate ones to wear at each conference I go to.

Hand out Free Shit

This is the hack that I used as a kid. I was shy around my classmates, so I would bring crazy candy to school in a Santa-like bag and offer it to everyone around me. The word would get around fast, and pretty soon, everyone would be approaching me, even the "cool" kids.

This isn't something I've done frequently myself at conferences, but I've seen others do it. Lug around a bag of cool stickers or shirts, and pretty soon, because we all have grade school sticker-mongers deep inside us, you'll have random strangers approaching you for them.


I'll update this as I think of more. Feel free to share your own hacks in the comments!

.