Month: April 2020

Staying Connected And Learning From Each Other

Staying Connected And Learning From Each Other

Staying Connected And Learning From Each Other

Iris Lješnjanin

Digital space obviously has its challenges, but it also provides incredible opportunities for us to connect and learn in ways we just wouldn’t be able to do otherwise. The situation with COVID-19 has challenged us to consider ways in which we could offer a similar SmashingConf experience and access to experts just as in an in-person workshop — without needing to leave your desk.

With insightful takeaways, exercises, access to slides, recordings and friendly Q&As, it has been such an incredible experience already! We’ve had literally people from all over the world collaborating together on group exercises — something we’d never be able to achieve with an in-person event.

Topple the Cat running an online workshop with six other cool cats
We’re looking forward to connecting with Brad Frost, Joe Leech, Miriam Suzanne and many others. Try spotting them, but don’t get too distratced by the Mouse!

And we’re just getting started! We already have a schedule of online workshops ready for you so you can start marking your calendars and join us anytime you like. What better way is there to boost your skills online and learn practical, actionable insights from experts in the industry — live!

Name Topic Date Time
Brad Frost Creating and Maintaining Successful Design Systems April 22–May 6 09:00–11:30 AM PDT
Joe Leech Psychology For UX and Product Design April 27–May 5 09:00–11:30 AM PDT
Miriam Suzanne Resilient Web Systems with CSS & Sass May 7–22 09:00–11:30 AM PDT
Vitaly Friedman Smart Interface Design Patterns, 2020 Edition May 12–26 09:00–11:30 AM PDT
Rachel Andrew The CSS Layout Masterclass June 11–12 01:00–03:30 AM PDT
Marcy Sutton Front-End Accessibility Masterclass June 16–30 09:00–11:30 AM PDT

Do you like what you see, but are worried about getting some time off from work? Well, you surely didn’t think we would leave your hanging? We know how difficult it can sometimes be, and so we’ve prepared a neat lil’ Convince-Your-Boss template to help you out. Good luck!

Ready For The Next Smashing Book?

Topple the Cat presenting the book cover of the upcoming Click! bookThat’s right! Paul Boag’s Click! Encourage Clicks Without Shady Tricks is currently in its final production stage and the pre-release starts on May 12. This practical guide has 11 chapters full of advice that can help you start improving your conversion rate in just a matter of simple steps. You can subscribe for a pre-order discount and be one of the first to get your hands on the book. Stay tuned!

Live UX Review With The Author

Next week, we’ll be hosting a Smashing TV webinar with Paul Boag who’ll be reviewing your websites and sharing some techniques you can use to improve conversion rates — without having to resort to any shady tricks. Tell me more →

Topple the Cat presenting The Ethical Design Handbook book coverAs for the previous book, printed copies of The Ethical Design Handbook have made their way around the world, and we got to see some happy responses and thoughtful reviews. If you’d also like a copy, you can download a free PDF excerpt (5 MB) to get a first impression of the book — we’re sure you won’t be disappointed!

Also, in case you missed it, there is a Smashing Podcast episode featuring two of the authors of the book: Trine Falbe and Martin Michael Frederiksen. They discuss what it means for a design to be ethical, and how we can make improvements in our own projects.

Drew has also interviewed Laura Kalbag, Eduardo Bouças, Stéphanie Walter, and many more. You can subscribe and tune in anytime with any of your favorite apps!

We publish a new article every day on various topics that are current in the web industry. Here are some that our readers seemed to enjoy the most and have recommended further:

  • Best Practices With React Hooks
    by Adeneye David Abiodun
    This article covers the rules of React Hooks and how to effectively start using them in your projects. Please note that in order to follow this article in detail, you will need to know how to use React Hooks.
  • Inspired Design Decisions With Herb Lubalin
    by Andy Clarke
    How can we combine elements to develop powerful headers and calls to action? How do we use pre-formatted HTML text, and the text element in SVG for precise control over type? How can we optimise SVGs and make SVG text accessible? In this article, we’ll explore just that.
  • Baking Structured Data Into The Design Process
    by Frederick O’Brien
    Retrofitting search engine optimization only gets you so far. As metadata gets smarter, it’s more important than ever to build it into the design process from the start.
  • How To Make Life Easier When Using Git
    by Shane Hudson
    You don’t need to know your trees from your dangling blobs. If you use Git every day and feel like it’s a juggling act, then here are some tricks and tips to help make your life a bit easier.

Best Picks From Our Newsletter

We’ll be honest: Every second week, we struggle with keeping the Smashing Newsletter issues at a moderate length — there are just so many talented folks out there working on brilliant projects! Kudos to everyone involved!

Interested in sponsoring? Feel free to check out our partnership options and get in touch with the team anytime — they’ll be sure to get back to you right away.

Tips For Leading A Remote Team

Leading a remote design team can feel a bit daunting, especially if it’s your first time. Luckily, other people out there have found themselves in the same situation before and developed strategies to keep the team productive and effective, no matter where everyone might be located. Mark Boulton is one of them.

Screenshot from the article

In light of recent events when many teams need to switch to remote work, Mark summarized some simple but useful approaches that have helped him leading remote teams for years. From continuing your team’s rituals to dealing with expectations on availability and coaching people through the ups and downs that working remotely brings along, Mark’s tips aren’t hard to adopt but they can make a real difference. (cm)

Getting To Grips With CSS Viewport Units

CSS Viewport units provide us with a way to size things in a fluid and dynamic way, without the need for JavaScript. If you haven’t gotten around to dive deeper into the topic yet, Ahmad Shadeed wrote a useful guide to CSS Viewport units.

CSS Viewport Units

Starting with a general overview of the viewport units vw, vh, vmin, and vmax, the guide covers how viewport units differ from percentages and explores practical use cases for viewport units and how to implement them in your projects. Just the push you might have needed to make the switch. (cm)

A Better File Uploader For The Web

Building a better file uploader for the web. That was the idea behind the JavaScript image uploader Uppload. Created by Anand Chowdhary, the image uploader is open-source and can be used with any file uploading backend. And with more than 30 plugins, it’s highly customizable, too.


Users can drag and drop their files to upload them or import from a camera, URL, or social media and a several other services (there’s even an option to take and upload a screenshot just by entering a URL). During the uploading process, users can apply effects to the images and adjust filters like brightness, contrast, and saturation. If that’s overkill for your project, you can select only what you need and treeshake the rest, of course. Uppload supports browsers down to IE10. Handy! (cm)

Open-Source Flip Counter Plugin

Do you want to count down to an event, visualize a fundraising campaign, or show a clock or sales counter? Then Rik Schennink’s Flip Counter might be for you. The plugin is open-source, mobile-friendly, easy to set up, and it gets by without any dependencies.

Flip Counter

Apart from its ease of use and flexibility, Flip shines with the beautifully smooth animation that is used to flip the numbers on the cards. Depending on your use case, there are several presets that you can use as a starting point to build your flip counter. The visual style can be customized with CSS. A lovely little detail. (cm)

How To Write Good Email Code

Maybe you’ve been in that situation before where you had to code an HTML email but struggled with email code best practices. To help you master the challenge, Mark Robbins set up a library for good email code. You can simply copy and paste the code and use it in your emails or you can learn more about the theory behind it.

Good Email Code

Priority lies in making sure the code is semantic, functional, accessible, and meeting user expectations, as Mark points out. Consistency between email clients and pixel perfect design are important, too, but always secondary. One for the bookmarks. (cm)

A Complete Solution For Tooltips, Popovers, And Dropdowns

If you’re looking for a quick and easy solution for tooltips, popovers, dropdowns, and menus, you might want to take a look at Tippy.js. The library provides the logic and styling involved in all types of elements that pop out from the flow of your document and get overlaid on top of the UI.


Tippy.js is optimized to prevent flipping and overflow, it’s WAI-Aria compliant, works in all modern browsers, and, so the promise, it even delivers high performance on low-end devices. You can style the elements with custom CSS and TypeScript is supported out of the box, too. Handy! (cm)

Open-Source Tool To Make Animated Product Mockups

What do you do when you’re missing a tool for a specific purpose? You build it yourself. That’s what Alyssa X did when she was looking for a tool to make animated GIFs and videos to showcase a product. Her take on the subject: Animockup.


With Animockup, you can showcase your product in action within a device mockup. Just drag some screen footage into the browser-based tool, and Animockup automatically places it into your desired mockup. You can add text, images, and adjust the styling, and choose from a selection of presets to optimize your mockup for sharing on Twitter, Dribble, Instagram and the like. A useful little helper. (cm)

Create CSS Color Gradients With Ease

Hand-picking colors to make a color gradient requires design experience and a good understanding of color harmony. If you need a gradient for a background or for UI elements but don’t feel confident enough to tackle the task yourself (or if you’re in a hurry), the color gradient generator which the folks at My Brand New Logo have created has got your back.

Color gradient generator

Powered by color gradient algorithms, the generator creates well-balanced gradients based on a color you select. There are four different styles of gradients that go from subtle to a mother-of-pearl effect and an intense, deep color gradient. You can adjust the gradient with sliders and, once you’re happy with the result, copy-paste the generated CSS code to use it in your project. Nice! (cm)

Collaborative Diagrams

Pen and paper are often hard to beat when you want to visualize an idea with a quick diagram. If you’re looking for a digital alternative that is just as straightforward and easy to use as your analog tools, you might want to check out Excalidraw.


Excalidraw is a virtual whiteboard that you can draw on. You can choose from a set of shapes, connect them with arrows or lines, add text, and color. There are some other styling options, too, but the tool is kept rather simple so that you can focus on what’s really important: visualizing your idea. A great feature that comes in especially handy now that a lot of teams work remotely: You can share a live-collaboration session with your team members or your clients. Export and save options are included, too, of course. (cm)

Mastering BEM Naming Conventions

BEM makes your code scalable and reusable, prevents it from becoming messy, and facilitates teamwork. However, even experienced CSS developers struggle with the naming conventions sometimes. To prevent you from getting lost in the BEM cosmos, the folks at 9elements put together the BEM Cheat Sheet with naming suggestions for some of the most common web components: breadcrumb navigation, buttons, cards, lists, tabs, form checkboxes, sidebars, and more.

BEM Cheatsheet

If you want to dive in even deeper into the BEM methodology, Luke Whitehouse shares tips to tackle an ever-present issue in BEM: grandchildren, i.e. elements that are tied to another element, rather than to the block itself. Luke explores three different approaches to master the challenge: flattening the grandchildren and treating them as if they have no relation with their parent element, by creating new blocks, and by extending the BEM naming convention. A good read. (cm)

A Preserve For Classic Games

Do you feel nostalgic when you think of the video games you played back in the 80s and 90s? Well, why not take a little trip back to those days when games were just as much fun without the fancy effects they shine with today?


ClassicReload preserves more than 6,000 old retro games and abandoned OD/interfaces that you can play right in your browser. You can search for your favorite or browse the games by name, year, genre, and platform to discover something new. No matter if it’s The Oregon Trail, Prince of Persia, or Dangerous Dave you’ve been longing for for so long, if you’ve got a sweet spot for games, the site will keep you entertained for quite a while. (cm)

Managing HTML DOM And jQuery Alternatives

How do you manage HTML DOM with vanilla JavaScript only? Phuoc Nguyen collected 100 native DOM scripting snippets along with explanations on how to use them. The snippets are labeled by difficulty and range from basic (e.g. detecting if an element is focused) to more intermediate tasks like exporting a table to CSV and, finally, advanced use cases like creating a range slider.

How to manage HTML DOM with vanilla JavaScript only

Speaking of going vanilla: If you’re using jQuery in your projects, it might be a good idea to check if you actually need the additional dependency or if a few lines of utility code could do the trick. “You might not need jQuery” lists useful alternative code snippets that help you forgo jQuery. (cm)

Overly Descriptive Color Palettes

Have you ever considered combining snail-paced soft pink with unsealed mahogany and lousy watermelon as a color scheme for your next project? Well, what might sound a bit weird at first, is the concept behind, a color inspiration site with “overly descriptive color palettes”, as its creator Adam Fuhrer describes it.

Created as a fun way to discover interesting color combinations, the palettes are hand-selected from the Twitter bot @colorschemez. The feed randomly generates color combinations and matches each color with an adjective from a list of over 20,000 words. Hiding behind the unusual names are of course real hex color values that you can use right away — #FDB0C0, #4A0100, and #FD4659 in the case of snail-paced soft pink and its fellas, for example. A fun take on color. (cm)

Flexible Repeating SVG Masks

Sometimes it’s a small idea, a little detail in a project that you tinker with and that you can’t let go off until you come up with a tailor-made solution to make it happen. Nothing that seems like a big deal at first glance, but that requires you to think outside the box. In Tyler Gaw’s case, this little detail was a flexible header with a little squiggle at the bottom instead of a straight line. The twist: to make the component future-proof, Tyler wanted to use a seamless, horizontal repeating pattern that he could color with CSS in any color he liked.

Flexible Repeating SVG Masks

To get the job done, Tyler settled on flexible repeating SVG masks. SVG provides the shape, CSS handles the color, and mask-image does the heavy lifting by hiding anything in the underlying div that doesn’t intersect with the shape. A clever approach that can be used as the base for some fun experiments. (cm)

As a token of appreciation, Vitaly Friedman released his very own “Smart Interface Design Checklists”, a PDF deck with 150+ questions to ask when designing and building anything from hamburgers to carousels and tables. Subscribe to the newsletter below and get it in your inbox right away!

Smashing Editorial (cm, vf, ra, il)

Smashing Podcast Episode 14 With Rachel Andrew: How Can I Run Online Workshops?

Smashing Podcast Episode 14 With Rachel Andrew: How Can I Run Online Workshops?

Smashing Podcast Episode 14 With Rachel Andrew: How Can I Run Online Workshops?

Drew McLellan

Photo of Rachel AndrewIn this episode of the Smashing Podcast, we’re talking about running online workshops. How can a traditional event adapt when participants can’t attend in person? Drew McLellan talks to Rachel Andrew to find out.

Show Notes

This episode of the Smashing Podcast is dedicated to the memory of Christopher Schmitt, who sadly passed away last week. A familiar name to many of us over the years as an active contributor to both the Web Standards and Accessibility communities, Christopher, along with his partner Ari, was also a pioneer in conducting online workshops and conferences, which is the subject of this podcast.

Christopher was a skilled web practitioner, a generous educator, and a wonderful person to spend time with. His contributions to our industry were numerous and valued, and he will be missed by us all.

If you have memories of Christopher you’d like to share publicly, you can do so via this community site.

Weekly Update


Drew McLellan: She is editor-in-chief of Smashing Magazine as well as being a web developer, writer and public speaker. She’s the founder of web development consultancy,, responsible for products such as Perch CMS and the slide sharing and public speaking portfolio platform, Notist. She’s a member of the CSS Working Group, and many will know her for her prolific writing and teaching on modern CSS layout techniques, such as CSS grid.

Drew: So we know she’s an expert in CSS and in teaching, but did you know she’s a recognized authority on carving turnip lanterns? My Smashing friends, please welcome Rachel Andrew. Hi Rachel, how are you?

Rachel Andrew: I’m smashing.

Drew: So I could talk to you all day about any number of interesting CSS topics, but you write and you speak so much about these sort of subjects, that there’s a plentiful supply of resources that people can reference. And not least of which being things like your Grid By Example site or you CSS Layout Workshop video course. And of course, there’s plenty right here on Smashing Magazine. But what I wanted to talk to you today was something that was almost a byproduct of your expertise, isn’t it? That you have to end up getting up on stage and communicating what you know with other people. You do an awful lot of speaking at conferences and teaching in person workshops, don’t you?

Rachel: Yes. Yeah, I do. I have to done for about, I don’t know, the last six or seven years. And the last few years I’ve spent about half of the year on the road speaking and yeah, doing workshops. In particular for Smashing Magazine, did a bunch of workshops every year For Smashing. So that’s the something I’ve been doing quite a lot of.

Drew: So what does the shape of your year usually look like with conferences and workshops?

Rachel: Ah pretty much, I’m springing out in particularly. I’m generally just on the road quite often for three or four weeks at a time, go for one thing to the other. I try and link these things up, so I’m not sort of constantly flying back and forth over the Atlantic corridor for you. But yeah, so spending a lot of time either on stage talking to people about CSS or in workshops, and then going to see this working group meetings and sitting with a bunch of other people who really, really likes CSS and talking about CSS. So that’s mainly what I’ve been doing, and in between that actually trying to… Well, spending a lot of time writing these talks and workshops while I’m not giving them. And then then getting back on the road again. So that’s been life for, yeah, several years

Drew: As we speak, we’re in the thick of the Coronavirus pandemic. So this year isn’t really shaping up like a typical year for you or for any of us. So what’s the situation with your conference season looking like at the moment?

Rachel: Yeah, empty. It’s really bizarre looking at my calendar and not having it full of flights and hotel bookings. I’ve spent quite a lot of time in the last few weeks getting flights refunded and getting vouchers to use because I had all of my spring travel booked. I’ve been organized. So it’s been really strange then remove all those things from the calendar and be looking at not going anywhere. It’s very, very unusual for me. So yeah, it’s been quite a shock because it’s not happened for so long. And every year after, I’m not going to do so much travel this year. And of course, the diary fills up and off you go. So for this to happen and to happen so dramatically, and in a way that I don’t actually know when it’s going to start again. I’m looking at things in, say two months time, and thinking, well, will I be able to do those?

Rachel: I don’t personally have any health issues that… if it is okay to travel, I probably feel okay to travel. But I don’t know if it’s going to be okay to travel. I don’t know if it’s going to be sensible to travel because you might go somewhere and then them cause a lockdown and you get stuck there or get stuck in quarantine. So it’s very, very strange to not have this quite rigid plan, which is what I’ve had for the last few years where everything has been planned around me getting on a plane and going to speak somewhere.

Drew: So lots of conferences, probably in conferences and workshops, have been either canceled or postponed. I’m including the rescheduling of our own Smashingconf events and the workshops that go alongside that. Now hopefully, we can look forward to rescheduled Smashingconfs later in the year, but the workshops are also going online, is that right?

Rachel: That’s right, yeah. We’ve very, very quickly… Once we realized we were going to have to postpone San Francisco, we have… See we have workshops, both myself and Vitaly run workshops at Smashingconf, and they were sold out in San Francisco, both of our workshops. And obviously, we have lots of other people who come and run workshops for us, people who we’ve worked with for a long time. And they were finding that all their workshops… And for those of us who do workshops they’re actually a key part of our income. Public speaking, you don’t earn a lot of money typically going and public speaking. Most people aren’t paid a lot, not when you consider the amount of time it takes to write talks and so on. Workshops tend to be quite a nice way for people who are good at teaching this stuff to earn some money.

Rachel: And so they represent people’s income. And so, not only did myself and Vitaly had lost our workshops early this year. We also realized that a lot of our Smashing speakers also, were reliance on those workshops. And so we thought, well, why not just take them online? And very, very quickly, really, within days of that happening, we decided that me and Vitaly would be the first to stick our heads over the parapet, given it’s us. And we could figure out how to do it. And we also have very different workshops. Vitaly is much more collaborative. He has group activities and things. I teach classroom style. So between us we thought, well we kind of covering all the bases. So that was really… We thought, let’s just do it, let’s see if it works. So we advertise them, we figured out how long did each take. And then we sat down and said, well what does an online workshop really look like? What is this?

Drew: I think from a technical perspective, as web developers, we immediately think, how on earth are we going to deliver something like that? There must be lots of different platforms that you looked at. What were the different things you looked at and what Smashing eventually come with?

Rachel: So we’ve had a look at all sorts of things, and we’re still kind of in the process of doing that. We’re using Zoom at the moment, and the reason we’re using Zoom is accessibility. It was the most accessible of the platforms. Obviously, we don’t want to cut people out because of the platform we’ve chosen. And I think the platforms are getting better and people are… I think that a lot of platforms have had people come to them and say, yeah, you look great, but you know, we need you to be accessible. And so, so Zoom is the easiest for people to use at the moment. And so, that’s why we’ve ended up using them.

Rachel: I don’t know whether we will do forever, but that’s what we’re using at the moment, and it’s worked pretty well as a way to do this stuff. And it gives us the flexibility we need. We’re able to do breakout sessions for Vitaly’s workshop and things. And yeah, so platform-wise, it seems to work. We didn’t really have any major issues across the days. And say we’ve run my workshop and Vitaly’s workshop now… Are the two that we’ve actually done, and then we didn’t really have any technical problems as it were. So that was really helpful. Yeah, because it’s always a bit of a worry thinking everyone’s silent in all these different locations, and this has got the work.

Drew: As you say, you’ve run two workshops so far, and there’s an awful lot more scheduled to come up in the future.

Rachel: Yeah, we’ve got a whole bunch of them. So the upcoming stuff, I’m just having a look at the list, we’ve got Brad Frost doing his Design Systems. We’ve got Psychology for UX with Joe Leech, Advanced CSS and Sass with Miriam Suzanne. Vitaly’s doing his Smart Interface Design Patterns again. I’m doing my CSS Layouts Masterclass again in June, and we’ve got a Front-End Accessibility Masterclass with Marty Sutton. So those are the ones lined up until June now.

Drew: That’s quite a big undertaking, isn’t it? All those different instructors as they were, with different styles of teaching and different requirements from the platform.

Rachel: Yeah, I think so. That’s why we started with Vitaly and I because we have this different way of teaching We thought that would be a good start. We could iron out some of the things, and then we’re going to then write up the stuff that we figured out. To hand that over to other instructors. Because we were very keen that they didn’t just become… we didn’t want it to be a second-rate experience. It wasn’t like, Oh well, you can’t come and see us in San Francisco, and so this’ll do. We actually wanted to see, how can we make an online workshop a really cool thing. Because actually, there’s a whole bunch of people who, even if we could all travel around the world… there’s a whole bunch of people who can’t.

Rachel: There’s plenty of people who, they don’t have the budget to fly places, or they’ve got family, or they just don’t like doing that sort of travel, or they’re concerned about spending a lot of time on airplanes. And I think actually, this is something that, that can work very well as a thing, and we’ve been forced into it to some degree. And we’ve had to figure out how to do it, but it’s certainly not a lesser thing. It’s a different thing and we’re figuring out how to make that happen. But it doesn’t have to be a second best from an in person.

Drew: So what does the experience of attending an online workshop feel like for a participant, where obviously it’s can be very different from the in-person experience?

Rachel: I think we looked at what people really say they get from coming to an in-person workshop. And a lot of that isn’t really just the teaching because all of that stuff, you can get lots of ways. You can read things on Smashing Magazine, you can watch video tutorials. Here there’s lots of ways to get this information. Both Vitaly and I are incredibly prolific in all this output that we do in sharing. But actually, what people tend to put on their feedback forms and stuff, from in-person workshops is, they got their questions answered. They were able to spend time talking to the person leading the workshop or with each other as well, with the other attendees, and have questions answered. That kind of interactivity was important. And so that was the thing we wanted to bring.

Rachel: And so, during the workshop there’s a few ways we’re doing that. There is a chat in Zoom itself, so people can chat while the workshop’s going on. So they do that and they introduce each other over and talk about where they are and what time it is because we’ve got people from all over the world. So that’s going on. Both of us had Google Docs open, which anyone could edit. And we tend to do that actually at Smashingconf, anyway, have these collaborative docs that people… people do amazing things. They completely live blog the entire event and put all the resources and so on. So we had those, and it was really interesting to see the attendees, which they would put the questions in there.

Rachel: And they would so much help each other out. Someone would write a question that I hadn’t got to, and someone else would have answered it, and people were clarifying things, and putting links to code pins in. And so, that was really interesting, that there was this collaboration going on while I was teaching. This sort of with other people. And I inadvertently had the same experience, people were helping each other out in terms of making comments and so on. So I think that that was the thing that it did feel like an interaction. It didn’t feel… so I’ve done a lot of presenting online where you just feel like you shout at your computer for an hour and then go away, and you’ve got no idea if anyone enjoyed it. It’s like, all right, there we go. I’ll go and I’ll drink now. But this actually felt like I was with people as an instructor, and the feedback… people were saying, it felt very intimate and that they were talking to me rather than just having something presented at them. Yeah, so that was interesting.

Drew: I guess as you say, the danger of running a workshop online is that it just becomes impersonal and the experience becomes more of a passive one for attendees. Is there anything that you can do in the way that you structure the content that you’re actually teaching?

Rachel: Yes.

Drew: Or the way that you conduct it to encourage people to interact and to participate with the tools that have been provided?

Rachel: Yeah, and I think Vitaly does a lot more of that because he has more… some of our other instructors are going to have more group activities. I teach in person, very much classroom style. My courses are pretty much a brain dump of here’s the stuff I know about CSS, here it is with lots of examples. And I have people coding with me all day, when we do them, but I’m not so much a group activities thing. It’s hard to do a group activity on Here’s the Basics of Grid Layout. So I’ve just found that teaching classroom style works quite well. Whereas I know that Vitaly actually had people breaking off into groups and doing activities, and actually meeting up with some of these people from all over the world who are participating. And so, that’s really quite fun because I think people do get a lot from that, from just the meeting of the people who do their job. Particularly, if you were mostly on your own, to actually get chance to do an activity with other people is quite a nice thing too.

Drew: Is there anything special that’s been done to give the online events something of the feel of the brand, in the same way that you would in an in-person event? I know attending a Smashing event, it always feels like a Smashing event. There’s something of the brand that’s communicated in the way that everything’s done. Is there anything that can be done online to help communicate that same feel?

Rachel: I think it’s difficult, but I think part of it is the attitude that generally smashing has. We’re very friendly and try and be as approachable and sort of informal as it were. So people feel like they’re coming to something which is going to be fun and entertaining. Things like Vitaly was online before my workshop playing a load of music and so on, just because that’s the sort of thing we do at Smashing. We like to entertain people and have some fun. So I think, yeah… I think trying to bring some of that fun that we do have at the live events as much as you can with a virtual thing. I think that’s what we’re trying to do. We’re trying to make it feel like a Smashing thing as much as we can.

Drew: Of course, you mentioned that there are many people who can’t or aren’t willing to travel to in-person events anyway. There must be a lot of advantages, even for those who would normally attend an in-person event. There’s got to be advantages to actually attending a workshop from the comfort of your own desk with your own set up around you.

Rachel: I think definitely. I think that is something a few people mentioned, that it was just nice to be… have the whole set up. Because if you’re a developer working at home, you’ve probably got two screens, and you’ve got your comfortable keyboard and your chair. And certainly for my software workshop where people are coding the whole time, to actually be able to have the presentation on one screen and have your code in front of you. And not be working on a tiny laptop, squashed in with a load of other people, and on an uncomfortable chair for the day. There’s a lot of benefits to that. So I think there are some quite nice things. You obviously, don’t get all the sides. If you don’t get to go off with your new friends and have a drink and have a chat about it all. And there’s things that you do lose by doing this virtually, but there is an awful lot to be said for it as an experience.

Drew: One thing that I’ve seen done quite a lot in the past with online events, is to try and create a bit of a sense of community by having local hubs, even though it’s a distributed global event. Obviously, that’s not something that we can even do at the moment because everybody’s confined to their own home, more or less. Is there anything else that can be done to create that sense of community, do you think? Is there anything that’s Smashing has thought about to try?

Rachel: Yeah. I think it’d be interesting to see where this plays out and whether this becomes a temporary thing, or whether that’s something that we can just carry on doing. I think that… and it would be interesting to see how we can link people up. We also have the Slack channels, so people chat in there. And I think really it’s just trying to… and we know a lot of friendships are made and also work relationships are made, people get new jobs and so on, from coming along to things like a Smashingconf. It’d be nice to try and encourage that sort of… that it’s not just where we do this and then go away afterwards, but that we can carry on the conversations and so on. That people are making and there’s something very nice to be said as well about… we have people from all over the world in my workshop. And that’s pretty cool that all those people were able to get together and spend some time learning.

Rachel: So yeah, I think that there’s all sorts of possibilities for this. We obviously, kicked it all off in a bit of a rush like, let’s just do it and see what happens. But I say, Vitaly and myself, we sold out. There was a lot of interest, and the other tickets are selling really well. So there’s obviously a need for this, and whether it is just now or whether it’s going to be something that we carry on doing, see what people think.

Drew: Being delivered digitally, there’s the fact that a workshop can actually be recorded and then replayed by participants later to go back over everything they’ve missed. Is that something that Smashing is taking advantage of?

Rachel: Yep. Everyone gets copy of the recording, and also we’ve been asked to add to that. At the moment, we haven’t got live captions going during the workshops. That’s something we’re hoping to fix. We’re hoping to actually be able to get the captions in real time. At the moment we’re not doing that, but we are getting them transcribed after the event. So when they get the video, they also have a transcript of the stuff, which is great. It might help, particularly if people are struggling with accents, so what have you. So that’s quite good. And then say, we’d like to look at getting them captioned as well, actually as they go out, with a live captioner, which would then be something that we don’t do in person. Not saying that we can easily do, and with workshops that we’re running live, but actually we can do online. So that would be, I think, a really helpful thing, and hopefully it would open it up to more people.

Drew: You mentioned as a presenter, things are quite different in the way that you actually present and you teach, where you’re just basically shouting it at a computer, hoping that there’s somebody there. I guess it’s quite different because you’re having to take care of all your own technology, your own setup, everything to make sure that you’re in a position ready to present online. How does that differ to how things would go normally if you were going to an event?

Rachel: In some ways it’s easier because I’m quite used to doing stuff online. I think it might be harder if you’re not well set up for recording stuff, I do quite a lot of video and things. So I’m reasonably well set up. But also, we’ve got our crew, we’ve got people online. I think that’s actually really important, is that if you’re presenting, the last thing you want to have to do is deal with someone who can’t get into Zoom or can’t hear the sound or can’t… just having some problem. So we have other members of the team, just like we do in person, have members of the team to help out if someone’s having trouble getting on the wifi or whatever it is. With the online workshops, we have people online to keep an eye on the chat and make sure that people aren’t struggling. And also to alert the presenter, if suddenly they drop offline or something… their sound’s gone weird or whatever it is.

Rachel: We’ve actually had no real technical issues like that, but there’s always that thought when you’re presenting online like, can people hear me? Am I just like talking to my screen and nothing’s happening out there? So having the team online with… or their contact details to be able to get hold of me, if suddenly I dropped off that. It makes you feel a lot more safe and that it’s okay.

Drew: Is there anything that you’ve changed about your setup in your home office to make online presenting easier? What does your set up look like there?

Rachel: Yeah, it’s getting ridiculous to be honest. It is just an excuse to buy things. So for the workshops, I’m coding, so I’m sitting down. When I’m doing more like presentations, I realized that it is just weird to present sitting down. And I don’t feel like I can actually do it very well. So I’ve got a standing desk, and so everything I have in… I’ve got some lighting and bits and pieces, but because I have things bolted to my desk. If I wanted to present standing up, I can just make the desk go up and everything goes with it and then I can present from my feet. And I did an online presentation for the BBC recently that was meant to be an offline in-person thing and got changed. And it felt so much better, being able to move around.

Rachel: And so, I’ve got my camera set up, so I can move about a bit, and I don’t feel like I’m just tied to the spot. And so, that sort of thing, I think, is really useful, being able to feel natural when you’re presenting and not just that you’re slumped in your chair and talking to a camera. And decent lighting I think is really important. I seem to spend an awful lot of time in Zoom calls now. And just people being well-lit is incredibly helpful. And I think, when you presenting or doing a workshop, people want to be able to see your face and your expressions and things, and having some decent lighting will help with that.

Drew: I’ve seen photos from, I think it was Val Head who posted her setup where she had a great big screen, and I think a couple of different computers and maybe an iPad or something as well. What does your technology set up look like there?

Rachel: So I’ve got two too, I’ve got my laptop and then my screen and because… so there’s the chat and things going on, which I don’t tend to take Q&A during, while I’m talking. I tend to deal with it at the end. But I can see the chat, and so I can see if… Sometimes I’ll pick up that someone’s got a very specific issue that I can just deal with at the time, and I might do that. So I’ve got that going on just in the peripheral vision. Because I’m coding, I’ve got the main stuff I’m doing and the screen it’s being output to the attendees is my main screen.

Rachel: I turn all my notes in when I do in person workshops as well. I turn all my notes into an e-pub, so I can have that on my iPad, which is handy because I can jump back and forth with the indexing and so on. So I have all the notes and the stuff to help me remember what I want to do next. But pretty much, and mossy of it’s run as I do in-person workshops. I work with a bunch of examples, basically that we work through, and I explained different things. And then, the attendees can take those examples away to help them remember what they did. So I pretty much do the same thing online. I think what I do probably moves online the easiest because teaching classroom style is quite an easy thing to move online. So you see, I’ve not changed too much. It’s just really making… getting comfortable with the setup so I don’t have to worry about that while I’m working.

Drew: Are there any bits of technology that you have in place that you think a really useful and really recommended for anyone who’s looking to do something similar?

Rachel: I think the lighting and decent mics and decent headsets and mics, so you’re not leaking sound over your ears. That sort of stuff is, I think, important. I like the headset mic rather than a mic on a stand because I’m writing code. I find that if I have a mic on a stand, I move away from it, back and forth all the time because I’m doing things. So having the headset mic means I haven’t got to get around a microphone that’s in front of my face. So that’s what I tend to use and that works quite well for me. So that was my main thing. I think, yeah, having a decent… You don’t have to spend a fortune, but having a good mic and headphones and some lighting, I think makes all the difference.

Drew: They often say, don’t they, that audio quality is more important than video quality when it comes to these things.

Rachel: Yeah. It’s just painful to listen to if you’ve got bad crackly audio.

Drew: So what have you learned so far in this journey? You say that you and Vitaly were the Guinea pigs for the approach. Is there anything key that you weren’t expecting that you’ve learned along the way?

Rachel: I think I’m surprised how intimate it felt and how connected it felt with the people who were attending. I hadn’t expected that at all. I’d expected it to be quite impersonal, and that we’d try very hard to make it feel personal but it would still be that kind of, Oh I’m presenting online now, I’m going away. I think having a good set amount of time for questions… I had half an hour for questions at the end of both of my days, and we used them. And I then went back to the Google doc and answered some stuff in there afterwards. So I think that really helped because people were able to ask their specific questions. I think the approach was splitting them up into multiple days. When we do these things in person, they are full day workshops. And we just figured that a full day for people to sit with a very long time to concentrate.

Rachel: And also it meant that we could put them into a time zone that worked for more people. Because if you’re not going to find a full day, if you’re saying well actually, it’s two or three hours, then more people in different time zones can attend that. So this workshop was my evening. So then it was like 9:00 AM on the West coast of the States, which meant the people on the East coast, the States and also people in the UK and stuff could attend. The next one I’m doing is going to be UK morning, which means that people in Asia and so on and in Australia, it’s not too far out of their day to be able to attend. So that kind of thing works quite well, spacing them up over multiple days. And I think it is easier for people because it’s a long time, a full day listening to someone on a screen. I think you’re probably going to start to zone out no matter how interesting they are.

Drew: And people have other responsibilities in their jobs, don’t they? The number of times that you see people at a in-person conference and they have to leave at the lunch break because they’re needed in the office, because there’s things that have to be done. Life doesn’t stop just because you’ve got a day’s worth of training planned.

Rachel: Yeah, and I think here, and in the current situation as well. A lot of people are working from home and are having to do childcare or home educate their kids. So particularly in the current environment, I think asking both presenters and attendees to be able to block out two and a half, three hours is probably a lot easier for people than be able to block out a full day. Because if you’ve got young children at home, even if you’ve got a partner there, you’re basically saying, you’ve got to be all locked out of this room for nine hours today. That’s a lot. So I think actually, having those shorter sessions is, for a lot of reasons, is probably a good thing.

Drew: If other event organizers are thinking about doing the same with their events, they’re looking at their schedule ahead, seeing all their in person events being canceled, and thinking they’d really need to do something to keep everything ticking over. What should they be taking into consideration before embarking on moving their events online?

Rachel: I think to realize that it’s doable and that people are interested and will pay for this sort of thing. I think getting the tech in place and testing it is important. Having a team to back people up is really important, even if they don’t need to do very much, they’re just sitting there watching the output. It makes you feel a lot more confident as a presenter, knowing that that’s happening. So that I would say is, is important. And really just thinking about the ways in which you can make this seem not like a second class way of learning. It’s a different way of learning, but it doesn’t need to be a lesser way. And rather than being apologetic and saying, Oh, we’re really sorry we can’t do an event, but we’re going to do this. Say, No, hey, this is going to be a really great way for us all to get together and learn something and spend some time with other people, not just in our own four walls.

Rachel: And it’s just a different thing. And I think this is quite an exciting thing that we’re learning how to do. And it’s made us all at Smashing feel so much happier because it could have been quite depressing, losing the conferences. It’s when we were all… we were a little team and we love spending time together as well. We were all so excited to be going to San Francisco and seeing each other and doing the conference. But instead of feeling like we’ve lost that, we actually feel like we’re doing a really great thing and sharing knowledge with our Smashing community. And it’s been really nice. I think it feels like we’re moving forward.

Drew: So the Smashing online workshops are running throughout April, May, and June. And you mentioned some of the great speakers who are lined up for those. And listeners can find out about those and the rescheduled Smashingconfs that are coming to a city near you. Again, So I’ve been learning about online workshops. What have you been learning about lately?

Rachel: I’ve actually been learning the mandolin. I keep meaning to learn the mandolin, and it’s been like, well I’m stuck in the house, so might as well. So I’ve been doing that. That’s been good. I’m terrible. Absolute terrible. But it’s something nice to be doing. I’ve always been learning about gardening because I had a mud pit outside and I thought I might try and turn it into some sort of garden. So that’s what I’ve been doing to get away from the computer a little bit, so I’m not just sat here staring at this all day.

Drew: If you, the listener, would like to hear more from Rachel, you can follow her on Twitter, where she’s at Rachel Andrew. And find all of her writing, speaking, online training, and excellent CSS layout news email newsletter linked from my site at RachelAndrew.coderUK.

Drew: Thanks for joining us today, Rachel. Do you have any parting words?

Rachel: Just to say that, keep on enjoying learning stuff while we’re in this weird situation, but also don’t stress if you’re feeling like you really can’t do anything today because it is weird. Well, none of us were expecting this sort of thing to be happening, and it’s okay to feel not great and not want to learn and not be productive for a while too.

Smashing Editorial (il)

Creating Personal Customer Experiences With Context Marketing

context marketing

By Brooke Sellas

Creating personal customer experiences is nothing new. But adding context marketing to those experiences is key when it comes to modern marketing and solving customer pain points.

In this episode of the Marketing Companion Podcast, I’m still holding down the fort while Mark Schaefer recovers from COVID-19.

I was so fortunate to be joined by the brilliant Mathew Sweezey of Salesforce. We talk about his new book, The Context Marketing Revolution: How to Motivate Buyers in the Age of Infinite Media, and how context is exactly what helps marketers and business owners cut through the noise and provide seamless, highly personalized customer experiences.


Mathew is Principal of Marketing Insights for, author, podcast host, multiple award-winning marketers, pioneer of the marketing automation space, and regarded as one of the top minds on the future of Marketing (he’s even written a delightful article here on the {grow} blog).

On this episode, Mathew and I take a deep dive into the five context elements, and how you can apply them to create personalized customer experiences:

  • How do brands *really* cut through the noise of infinite media?
  • Creating customer experiences means understanding the five context elements of context: 1) availability 2) permission 3) personal 4) authentic 5) purposeful
  • Mat also gives several examples of brands doing it right, like his own company’s Salesforce Trailblazer Program and how people are vying to become a ‘Ranger’
  • And finally, how can brands ditch the campaign and focus on the customer journey?

Creating customer experiences can be daunting, but with Mat’s vast research and examples, it feels like anyone can do it.

And while I’ve loved having amazing guests on the podcast with me, I’m happy to report that Mark is on the mend and should be back co-hosting with me soon!

Click on this link to listen to Episode 188

Other ways to enjoy our podcast

Please support our extraordinary sponsors. Our content is free because of their generosity.

Many thanks to our friend Scott Monty for the awesome show intro. Be sure to check out his amazing newsletter The Full Monty and his new podcast available here:

Tim Washer is contributing creative direction to the show and he’s has worked for Conan O’Brien, John Oliver, among others. He helps corporations build more creative cultures.

It’s hard to ignore — millions of business professionals are active on LinkedIn. They have twice the buying power of a normal web user. If you’re in business, you need to be exploring advertising on LinkedIn. Brooke and I have both had tremendous success with this marketing platform and to help you get started, LinkedIn is offering Marketing Companion listeners $100 in free ad credit. That can go a LONG WAY! Take advantage of this opportunity today by visiting

The post Creating Personal Customer Experiences With Context Marketing appeared first on Schaefer Marketing Solutions: We Help Businesses {grow}.

Django Highlights: Models, Admin, And Harnessing The Relational Database (Part 3)

Django Highlights: Models, Admin, And Harnessing The Relational Database (Part 3)

Django Highlights: Models, Admin, And Harnessing The Relational Database (Part 3)

Philip Kiely

Before we get started, I want to note that Django’s built-in administrative capabilities, even after customization, are not meant for end-users. The admin panel exists as a developer, operator, and administrator tool for creating and maintaining software. It is not intended to be used to give end-users moderation capabilities or any other administrator abilities over the platform you develop.

This article is based on a hypothesis in two parts:

  1. The Django admin panel is so intuitive that you basically already know how to use it.
  2. The Django admin panel is so powerful that we can use it as a tool for learning about representing data in a relational database using a Django model.

I offer these ideas with the caveat that we will still need to write some configuration code to activate the admin panel’s more powerful abilities, and we will still need to use Django’s models-based ORM (object-relational mapping) to specify the representation of data in our system.

Recommended Reading

“Django Highlights” is a series introducing important concepts of web development in Django. You might want to read up on providing secure user authentication flows and follow alongside a demonstration on using Django templating to write complex pages.

Setting Up

We’re going to be working with a sample project in this article. The project models some data that a library would store about its books and patrons. The example should be fairly applicable to many types of systems that manage users and/or inventory. Here’s a sneak peek of what the data looks like:

Data Model. (Large preview)

Please complete the following steps to get the example code running on your local machine.

1. Installing Packages

With Python 3.6 or higher installed, create a directory and virtual environment. Then, install the following packages:

pip install django django-grappelli

Django is the web framework that we’re working with in this article. (django-grappelli is an admin panel theme that we’ll briefly cover.)

2. Getting The Project

With the previous packages installed, download the example code from GitHub. Run:

git clone
cd library_records/library

3. Creating a Superuser

Using the following commands, set up your database and create a superuser. The command-line interface will walk you through the process of creating a superuser. Your superuser account will be how you access the admin panel in a moment, so be sure to remember the password you set. Use:

python migrate
python createsuperuser

4. Loading the Data

For our exploration, I created a dataset called a fixture that you can load into the database (more on how to create a fixture at the end of the article). Use the fixture to populate your database before exploring it in the admin panel. Run:

python loaddata ../fixture.json

5. Running The Example Project

Finally, you’re ready to run the example code. To run the server, use the following command:

python runserver

Open your browser to to view the project. Note that you are automatically redirected to the admin panel at /admin/. I accomplished that with the following configuration in library/

from django.contrib import admin
from django.urls import path
from records import views urlpatterns = [ path('admin/',, path('', views.index),

combined with the following simple redirect in records/

from django.http import HttpResponseRedirect def index(request): return HttpResponseRedirect('/admin/')

Using The Admin Panel

We’ve made it! When you load your page, you should see something like the following:

Django Admin Panel Main Page. (Large preview)

This view is accomplished with the following boilerplate code in records/

from django.contrib import admin
from .models import Book, Patron, Copy

This view should give you an initial understanding of the data that the system stores. I’ll remove some of the mystery: Groups and Users are defined by Django and store information and permissions for accounts on the system. You can read more about the User model in an earlier article in this series. Books, Copys, and Patrons are tables in the database that we created when running migrations and populated by loading the fixture. Note that Django naively pluralizes model names by appending an “s,” even in cases like “copys” where it is incorrect spelling.

Data Model. (Large preview)

In our project, a Book is a record with a title, author, publication date, and ISBN (International Standard Book Number). The library maintains a Copy of each Book, or possibly multiple. Each Copy can be checked out by a Patron, or could currently be checked in. A Patron is an extension of the User that records their address and date of birth.

Create, Read, Update, Destroy

One standard capability of the admin panel is adding instances of each model. Click on “books” to get to the model’s page, and click the “Add Book” button in the upper-right corner. Doing so will pull up a form, which you can fill out and save to create a book.

Create a Book (Large preview)

Creating a Patron reveals another built-in capability of the admin’s create form: you can create the connected model directly from the same form. The screenshot below shows the pop-up that is triggered by the green plus sign to the right of the User drop-down. Thus, you can create both models on the same admin page.

Create a Patron. (Large preview)

You can create a COPY via the same mechanism.

For each record, you can click the row to edit it using the same form. You can also delete records using an admin action.

Admin Actions

While the built-in capabilities of the admin panel are widely useful, you can create your own tools using admin actions. We’ll create two: one for creating copies of books and one for checking in books that have been returned to the library.

To create a Copy of a Book, go to the URL /admin/records/book/ and use the “Action” dropdown menu to select “Add a copy of book(s)” and then use the checkboxes on the left-hand column of the table to select which book or books to add a copy of to the inventory.

Create Copy Action. (Large preview)

Creating this relies on a model method we’ll cover later. We can call it as an admin action by creating a ModelAdmin class for the Profile model as follows in records/

from django.contrib import admin
from .models import Book, Patron, Copy class BookAdmin(admin.ModelAdmin): list_display = ("title", "author", "published") actions = ["make_copys"] def make_copys(self, request, queryset): for q in queryset: q.make_copy() self.message_user(request, "copy(s) created") make_copys.short_description = "Add a copy of book(s)", BookAdmin)

The list_display property denotes which fields are used to represent the model in the model’s overview page. The actions property lists admin actions. Our admin action is defined as a function within BookAdmin and takes three arguments: the admin object itself, the request (the actual HTTP request sent by the client), and the queryset (the list of objects whose boxes were checked). We perform the same action on each item in the queryset, then notify the user that the actions have been completed. Every admin action requires a short description so that it can be properly identified in the drop-down menu. Finally, we now add BookAdmin when registering the model.

Writing admin actions for setting properties in bulk is pretty repetitive. Here’s the code for checking in a Copy, note its near equivalence to the previous action.

from django.contrib import admin
from .models import Book, Patron, Copy class CopyAdmin(admin.ModelAdmin): actions = ["check_in_copys"] def check_in_copys(self, request, queryset): for q in queryset: q.check_in() self.message_user(request, "copy(s) checked in") check_in_copys.short_description = "Check in copy(s)", CopyAdmin)

Admin Theme

By default, Django provides fairly simple styles for the admin panel. You can create your own theme or use a third-party theme to give the admin panel a new look. One popular open-source theme is grappelli, which we installed earlier in the article. You can check out the documentation for its full capabilities.

Installing the theme is pretty straightforward, it only requires two lines. First, add grappelli to INSTALLED_APPS as follows in library/

INSTALLED_APPS = [ 'grappelli', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'records',

Then, adjust library/

from django.contrib import admin
from django.urls import path, include
from records import views urlpatterns = [ path('grappelli/', include('grappelli.urls')), path('admin/',, path('', views.index),

With those changes in place, the admin panel should look like the following:

Admin Panel with Theme. (Large preview)

There are a number of other themes out there, and again you can develop your own. I’ll be sticking with the default look for the rest of this article.

Understanding Models

Now that you’re comfortable with the admin panel and using it to navigate the data, let’s take a look at the models that define our database structure. Each model represents one table in a relational database.

A relational database stores data in one or more tables. Each of these tables has a specified column structure, including a primary key (a unique identifier for each element) and one or more columns of values, which are of various types like strings, integers, and dates. Each object stored in the database is represented as a single row. The “relational” part of the name comes from what is arguably the technology’s most important feature: creating relationships between tables. An object (row) can have a one-to-one, one-to-many (foreign key), or many-to-many mapping to rows in other tables. We’ll discuss this further in the examples.

Django, by default, uses SQLite3 for development. SQLite3 is a simple relational database engine and your database is automatically created as db.sqlite3 the first time you run python migrate. We’ll continue with SQLite3 for this article, but it is not suitable for production use, primarily because overwrites are possible with concurrent users. In production, or when writing a system that you one day intend to deploy, use PostgreSQL or MySQL.

Django uses models to interface with the database. Using part of Django’s ORM, the records/ file includes multiple models, which allows for specifying fields, properties, and methods for each object. When creating models, we strive for a “Fat Model” architecture, within reason. That means that as much of the data validation, parsing, processing, business logic, exception handling, edge case resolution, and similar tasks as possible should be handled in the specification of the model itself. Under the hood, Django models are very complex, featureful objects with widely useful default behavior. This makes the “Fat Model” architecture easy to achieve even without writing a substantial amount of code.

Let’s walk through the three models in our sample application. We can’t cover everything, as this is supposed to be an introductory article, not the Django framework’s complete documentation, but I’ll highlight the most important choices I made in constructing these simple models.

The Book class is the most straightforward of the models. Here it is from records/

from django.db import models class Book(models.Model): title = models.CharField(max_length=300) author = models.CharField(max_length=150) published = models.DateField() isbn = models.IntegerField(unique=True) def __str__(self): return self.title + " by " + def make_copy(self): Copy.objects.create(book=self)

All CharField fields require a specified max_length attribute. The conventional length is 150 characters, which I doubled for title in case of very long titles. Of course, there still is an arbitrary limit, which could be exceeded. For unbounded text length, use a TextField. The published field is a DateField. The time the book was published doesn’t matter, but if it did I would use a DateTimeField. Finally, the ISBN is an integer (ISBNs are 10 or 13 digits and thus all fit within the integer’s max value) and we use unique=True as no two books can have the same ISBN, which is then enforced at the database level.

All objects have a method __str__(self) that defines their string representation. We override the default implementation provided by the models.Model class and instead represent books as “title by author” in all places where the model would be represented as a string. Recall that previously we used list_display in Book’s admin object to determine what fields would be shown in the admin panel’s list. If that list_display is not present, the admin list instead shows the string representation of the model, as it does for both Patron and Copy.

Finally, we have a method on Book that we called in its admin action that we wrote earlier. This function creates a Copy that is related to a given instance of a Book in the database.

Moving on to Patron, this model introduces the concept of a one-to-one relationship, in this case with the built-in User model. Check it out from records/

from django.db import models
from django.contrib.auth.models import User class Patron(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) address = models.CharField(max_length=150) dob = models.DateField() def __str__(self): return self.user.username

The user field is not exactly a bijective function. There CAN be a User instance without an associated Patron instance. However, a User CAN NOT be associated with more than one Patron instance, and a Patron cannot exist without exactly one relation to a user. This is enforced at the database level, and is guaranteed by the on_delete=models.CASCADE specification: if a User instance is deleted, an associated Profile will be deleted.

The other fields and __str__(self) function we’ve seen before. It’s worth noting that you can reach through a one-to-one relation to get attributes, in this case user.username, in a model’s functions.

To expand on the usefulness of database relations, let’s turn our attention to Copy from records/

from django.db import models class Copy(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) out_to = models.ForeignKey(Patron, blank=True, null=True, on_delete=models.SET_NULL) def __str__(self): has_copy = "checked in" if self.out_to: has_copy = self.out_to.user.username return + " -> " + has_copy def check_out(self, p): self.out_to = p def check_in(self): self.out_to = None

Again, we’ve seen most of this before, so let’s focus on the new stuff: models.ForeignKey. A Copy must be of a single Book, but the library may have multiple Copys of each Book. A Book can exist in the database without the library having a Copy in its catalog, but a Copy cannot exist without an underlying Book.

This complex relationship is expressed with the following line:

book = models.ForeignKey(Book, on_delete=models.CASCADE)

The deletion behavior is the same as Patron’s in reference to User.

The relationship between a Copy and a Patron is slightly different. A Copy may be checked out to up to one Patrons, but each Patron can check out as many Copys as the library lets them. However, this is not a permanent relationship, the Copy is sometimes not checked out. Patrons and Copys exist independently from one another in the database; deleting an instance of one should not delete any instance of the other.

This relationship is still a use case for the foreign key, but with different arguments:

out_to = models.ForeignKey(Patron, blank=True, null=True, on_delete=models.SET_NULL)

Here, having blank=True allows for forms to accept None as the value for the relation and null=True allows for the column for the Patron relation in Copy’s table in the database accept null as a value. The delete behavior, which would be triggered on a Copy if a Patron instance was deleted while they had that Copy checked out, is to sever the relation while leaving the Copy intact by setting the Patron field to null.

The same field type, models.ForeignKey, can express very different relationships between objects. The one relation that I could not cleanly fit in the example is a many-to-many field, which is like a one-to-one field, except that, as suggested by its name, each instance can be related to many other instances and every other and each of those can be related back to many others, like how a book could have multiple authors, each of whom have written multiple books.


You might be wondering how the database knows what is expressed in the model. In my experience, migrations are one of those things that are pretty straightforward until they aren’t, and then they eat your face. Here’s how to keep your mug intact, for beginners: learn about migrations and how to interact with them, but try to avoid making manual edits to the migration files. If you already know what you’re doing, skip this section and keep up what works for you.

Either way, check out the official documentation for a complete treatment of the subject.

Migrations translate changes in a model to changes in database schema. You don’t have to write them yourself, Django creates them with the python makemigrations command. You should run this command when you create a new model or edit the fields of an existing model, but there is no need to do so when creating or editing model methods. It’s important to note that migrations exist as a chain, each one references the previous one so that it can make error-free edits to the database schema. Thus, if you’re collaborating on a project, it’s important to keep a single consistent migration history in version control. When there are unapplied migrations, run python migrate to apply them before running the server.

The example project is distributed with a single migration, records/migrations/ Again, this is automatically generated code that you shouldn’t have to edit, so I won’t copy it in here, but if you want to get a sense of what’s going on behind the scenes go ahead and take a look at it.


Unlike migrations, fixtures are not a common aspect of Django development. I use them to distribute sample data with articles, and have never used them otherwise. However, because we used one earlier, I feel compelled to introduce the topic.

For once, the official documentation is a little slim on the topic. Overall, what you should know is that fixtures are a way of importing and exporting data from your database in a variety of formats, including JSON, which is what I use. This feature mostly exists to help with things like automated testing, and is not a backup system or way to edit data in a live database. Furthermore, fixtures are not updated with migrations, and if you try to apply a fixture to a database with an incompatible schema it will fail.

To generate a fixture for the entire database, run:

python dumpdata --format json > fixture.json

To load a fixture, run:

python loaddata fixture.json


Writing models in Django is a huge topic, and using the admin panel is another. In 3,000 words, I’ve only managed to introduce each. Hopefully, using the admin panel has given you a better interface to explore how models work and relate to each other, leaving you with the confidence to experiment and develop your own relational representations of data.

If you’re looking for an easy place to start, try adding a Librarian model that inherits from User like Profile does. For more of a challenge, try implementing a checkout history for each Copy and/or Patron (there are several ways of accomplishing this one).

Django Highlights is a series introducing important concepts of web development in Django. Each article is written as a stand-alone guide to a facet of Django development intended to help front-end developers and designers reach a deeper understanding of “the other half” of the codebase. These articles are mostly constructed to help you gain an understanding of theory and convention, but contain some code samples which are written in Django 3.0.

Further Reading

You may be interested in the following articles and documentation.

Smashing Editorial (dm, yk, il)

Tesla to reduce price of standard range Model 3 in China

Tesla said it will reduce the price of its standard range Model 3 vehicle in China to meet the government’s new eligibility requirements for subsidies.

This marks the second time this year that the automaker has reduced the price. Several months ago, the base version of China-made Model 3 was lowered by 9%.

Tesla has to cut the price of the vehicle to continue to qualify for government rebates on electric vehicles. The Chinese government instituted new regulations that require prices below 300,000 yuan for electric vehicles to qualify for subsidies.

The base price of the standard range Model 3 made in China is 323,800 yuan, or $45,754 before subsidies.

The price reduction will go into effect tomorrow in China, Tesla CEO Elon Musk said in a earnings call Wednesday. Musk, who didn’t provide a specific figure, said he is confident the vehicle will deliver a gross margin despite the reduction in price.

Tesla chief financial officer Zachary Kirkhorn added that the cost of vehicles produced at its Shanghai factory in the first quarter is already lower than the cost to produce the Model 3 in the United States. That margin should improve as the company improves its local supply chain in China. Tesla still ships some parts from the U.S. to build cars at its Shanghai factory.

5 Ways to Adapt Your LinkedIn Ads During COVID-19

By now, everyone knows that we’re facing challenging times with the COVID-19 pandemic as well as the resulting downtown in the economy. For online advertisers, this means working with new search habits, new performance benchmarks, and, in some cases, new budget restrictions.

LinkedIn advertising during COVID-19 example

Your advertising campaigns don’t necessarily have to stop, but they need to adapt. That includes LinkedIn. If you’re keeping LinkedIn Ads campaigns running during COVID-19 but need some help making them meaningful, here are five strategies I suggest:

  1. Stop focusing only on sales
  2. Build audiences cautiously
  3. Leverage LinkedIn retargeting
  4. Continue full-funnel marketing
  5. Communicate with your customers

1. Stop focusing only on sales

The biggest benefit of advertising on LinkedIn is the business targeting available. Advertisers leverage this to make valuable sales pitches to the proper parties in a given company, industry or location.

But during the COVID-19 pandemic, all bets are off.

people working at home

Too many people are in unusual work environments and simply aren’t as receptive to your hard sales pitch as they were before. The best approach now is to shift into a helpful and/or educational role. Rather than trying to get someone to set up a sales call, offer them useful content or access to a resource that could help them out.  I’ve had clients do this by writing new content, putting on webinars, town halls, and more to help support their customers during this time of need.

The downfall is that you might not see immediate returns from these efforts, if you see returns at all. Many people will take the free help and never end up working with your company. But there are many other people out there who will remember that you were there when they needed help. They’ll see you as a source of knowledge and when they’re ready to upgrade their business, they’ll not only be aware of your brand but have a positive association.

The best way to keep in touch with these users is to build as many audiences as you can for retargeting later on. Unfortunately, that comes with its own challenges, which I’ll go into now.

2. Build audiences cautiously

Audience building can still be a great strategy even during these strange times, but know there will be some challenges to overcome here, as well.

First, with many people now working from home, there are potentially many more (or at least different) devices in their work day.

Let’s consider my mom as an example. She works on a computer in her office but is now working from home. She’s still using a computer, but it’s a brand new one her company bought to give to remote employees so they could feel like the systems were secure.

This means a couple of things for audiences based on cookies:

  • The audiences my mom was in from her work computer will no longer target her since she’s not using that machine.  
  • The new audiences she’s finding her way into may not be helpful in a few weeks once she goes back to the office and resumes work on the original machine. 

This change in behavior won’t last forever, but it’s also not going to go away overnight. Think about how you’re leveraging audiences and adjust as needed.

That could include any of the following:

  • Create audiences with shorter/longer cookie windows on platforms other than LinkedIn to accommodate and speak to users based on how they’re interacting with your site.
  • Ask employees to share their IP so you won’t accidentally include them in your audiences or analytics.
  • Leverage gating tactics and ask for an email address before giving access to resources to help build a custom audience you can upload to platforms. (More on this later.)

There are still plenty of ways audiences can be useful, and we’ll get to those next, but be aware that they might not be as fool proof as before. 

3. Leverage LinkedIn retargeting

This might sound a bit silly and obvious, but if you follow my work at all you know I typically don’t like to run retargeting ads on LinkedIn. If anything, I try to steer you away from them.

The platform already has the highest CPCs, so why pay those twice when you can prospect on LinkedIn and then retarget on other cheaper platforms like Facebook and Google?

Well, this is likely the time to put that strategy on hold. Or at least, augment it with some LinkedIn retargeting.

For the same reasons I list above about audience issues and creation, it might be hard to retarget users accurately across those platforms. If you’re continuing the full-funnel marketing (which I recommend—more on this next), then it makes sense to keep it all in every channel so you have the best coverage and best chances of not missing anyone. Create your audiences in all platforms, but also LinkedIn, and retarget to the best of your abilities across all channels. Once everyone gets back to work, it might make sense to limit LinkedIn retargeting again, but for now, I think it’s a viable strategy.

4. Continue full-funnel marketing

In times like these, it’s easy to assume that all B2B buying functions are stopped, but that’s not always the case. Some companies are seeing businesses go through the buying stage more quickly than usual.

LinkedIn advertising during COVID-19 for brand awareness example

We need to move away from the hard selling in advertising campaigns, but we should continue to nurture them as we have before. The particular nurture cadences and touchpoints may need to be adjusted, but don’t abandon the nurture cycle completely.

Companies are still willing to buy during COVID-19, it just might look a little different than usual.

Continue having sales teams follow up and utilize retargeting campaigns to impact their buying decisions. With LinkedIn, that could mean any of the following as a follow up touch point:

LinkedIn lead gen ads

Test using lead generation ads as a follow up conversion action. This could be for a sales call, for another content touch point, or even as simple as a newsletter sign up. The goal here is to keep the users engaged with your brand with as little friction as possible so that when users are able to take the next step, they’ll be ready for it.

Sponsored InMail

The theory here is the same as for lead gen ads, but InMail should be reserved for a particularly special offer.

LinkedIn Sponsored InMail

Many users feel InMail is a bit of an invasion of privacy into their Inbox, so be sure the offer you’re making is worth the intrusion. What can you offer that the user won’t see anywhere else? Deep discount? Free onboarding? As long as it’s a valuable and unique offer, this could be worth a shot.

LinkedIn video ads

If we want a slightly softer touch, video ads can be a great way to get back in front of a target audience and get your message across in a controllable way. If you have video assets available, this could be a good time to leverage them as a soft touchpoint in your audience’s LinkedIn feed to, again, help you stay top of mind.

5. Communicate with your customers

No matter what, throughout each stage of the buyer funnel, make sure you’re communicating proper expectations to your customers. What can they expect from you in terms of follow up, if any.

In ad copy, make sure you’re positioning yourself in such a way you can follow up on.

Update your website copy to make it clear what your availability is.

marketing copywriting during COVID-19

If you don’t have dev resources, check out this new tool from Google Optimize that lets you add a banner to your site.

Many other things are uncertain at the moment. Make sure that your customers aren’t unsure about your company and how you can help.

Review and adjust your LinkedIn advertising during COVID-19

As I mentioned earlier, LinkedIn campaigns need only adapt to continue to be useful during COVID-19. Think about how you’re positioning your brand. Don’t focus only on sales, but don’t abandon them altogether, either. Be helpful and educational, capture audiences where you can, and leverage your touchpoints on all channels.

Marketing opportunities in the biggest disruption of our time

marketing opportunities

If there’s a silver lining to being a marketer in a sales-driven organization in the middle of this crisis, it’s this: There are marketing opportunities to build the commercial engine you’ve always dreamed about.

In my marketing career, I’ve heard “no” a lot … especially from sales.

Can marketing target this segment? No.

These leads need follow-up, can we build a better process? No.

This would make us more efficient and increase conversion. Could you collect this data point? Let’s have a meeting … followed by blah, blah, blah, no.

Change takes guts and when you’re dealing with sales in a normal, stable period there’s natural resistance because of how sales is incentivized. For practitioners of marketing strategy, there are few business irritations that rank as high as having to market at a continuous status quo.

In her book Big Magic: Creative Living Beyond Fear, Elizabeth Gilbert said if you’re aware of the ideas knocking on your door and, they can turn into something extraordinary. Wait too long and the idea will move to the next person. I think the same thing happens with marketing opportunities.

On the surface, the coronavirus crisis doesn’t feel like an opportunity.

This is a time of disorientation, apprehension, and uncertainty for nearly every business. Shifting our mindset from a place of dread and worry to one of curiosity and intrigue can soothe that fear and accelerate innovation. Here’s what we need to remember:

Cause > Fear

When you have a cause or purpose, you’ll naturally move forward because there’s no time to sit and debate fear. At my company, the mission is to connect healthcare providers and communities to transform lives. That’s a big ask. The coronavirus crisis makes it colossal.

Every one of us has a choice – be diminished by fear or absorbed in mission. Whether it’s a company or personal mission, by tackling one new tactic each day, you’ll achieve more than you once believed possible.

Early in the pandemic, a friend with an event company (one of the largest in the nation) pivoted to become a field hospital and testing site company. I placed a few calls, asked for a partnership and they said yes. Turns out this event company was starting a coalition banding 100 event companies to fight the pandemic. By being brave enough to call and ask, we became the first and only staffing company listed as a coalition partner. My focus on mission rather than fear continues to guide me to new opportunities.

Stop asking permission

The coronavirus crisis can enable you to dismiss your title and normal swim lane. This is an environment that is all-hands-on-deck, jump-in, act … and ask for permission later. As a result, it’s brought greater company awareness to marketing’s capability and earned us more voice at the table.

Case in point — several years ago, my team sought permission to take over more of the email efforts led by sales. We spoke ad nauseum about their unsubscribe rates, lost revenue, lost opportunity, and our ability to optimize results if given the chance. They wouldn’t listen to us.

When COVID-19 hit, marketing stopped asking permission and began sending. Our email communication has been far more effective, leading other teams to solicit our help to reach healthcare providers for critical positions.

My job is to find physicians and advanced practitioners who serve critically ill patients (a very difficult assignment right now!).

Despite the hurdles, we generated hundreds of new leads in a matter of 24 hours and earned the trust of healthcare workers who shared contact information they would have typically kept close to the glove.

By moving forward without waiting to be asked or asking to proceed, we had a greater impact on our organization and created marketing opportunities that will transcend the crisis.

Chaos leads to innovation

The COVID crisis introduces ambiguity and new constraints, which can feel paralyzing. However, re-framed, it’s a window to incredible creativity. The old rules don’t exist, we don’t know how the market will respond, so build from your gut. If you have a nagging idea, a hunch, something you’ve longed for, give it a try now.

During this period of chaos, we’ve re-imagined our campaign attribution model to better understand our direct relationship to ROI. Until now, our organization has run the last touch attribution model. You never want to overwrite a paid source with email as a source, so it’s been nearly impossible to quantify the financial value of marketing’s campaigns, which hurts optimization efforts.

With marketing’s initiatives taking greater visibility, we started logging every response we received, funneling them into a spreadsheet to track leads surfaced by marketing. Now we know what we can generate through email automation. The figure brings credibility to our efforts and provides a baseline of success to build on.

There’s an innovation you know will elevate your business. Now’s the time to build a small-scale pilot to prove your concept.

Humanity wins

As Mark Schaefer wrote, “The most human company wins.”


It can feel awkward to sell something in a national crisis. Instead of feeling invasive or needy, think about how your product or service genuinely helps others. That will reveal bold opportunities that could have lasting consequences.

From sunglasses to shoes, every product can create an emotional lift for the buyer. Nothing is strictly functional. If you sell sunglasses, you could be helping a runner find a pair that doesn’t fall down the bridge of their nose or someone struggling with depression during this time increase sunlight and serotonin.

In this crisis, my team has helped remind providers why they were called to medicine, which can get lost in the documentation and bureaucracy of normal practice.

For our sales teams, we’ve helped create safety by identifying leads when the normal practices failed. And for families across the country, we are doing our part to bring hope so that someday soon we can all walk outside and hug a good friend.

What I learned from working in this crisis isn’t necessarily unique, but I’ve been forced to understand core principals that I took for granted when everything was normal.

If you’re ready to reframe disruption as marketing opportunities, you’ll see a world of possibility.

Alycia Kaufmann is Division Vice President of Marketing for Jackson & Coker, one of the largest physician and advanced practitioner staffing firms in the nation. During COVID, she’s picked up indoor tennis and water bottle bowling with her family. You can connect with Alycia on LinkedIn and Twitter.

The post Marketing opportunities in the biggest disruption of our time appeared first on Schaefer Marketing Solutions: We Help Businesses {grow}.

Thuan Pham, who fled Vietnam as a child and became Uber’s CTO in 2013, is leaving the company

Thuan Pham, hired as Uber’s chief technology officer by former CEO Travis Kalanick back in 2013, is leaving the company in three weeks, the ride-share giant revealed today in an SEC filing that came out as a piece in The Information reported that massive layoffs at Uber are being proposed to preserve some of the company’s dwindling capital reserves.

The outlet suggests the discussed cuts could impact upwards of 20 percent of Uber’s 27,000 employees, roughly 800 of whom could theoretically come from Pham’s engineering team, which currently comprises 3,800 people.

Said an Uber spokesman to The Information’s Amir Efrati: “As you would expect, the company is looking at every possible scenario to ensure we get to the other side of this crisis in a stronger position than ever.”

Uber has been hard hit as much of the country and world remains at home, awaiting a vaccine for — or at least more testing around — COVID-19. Last Thursday, Uber said it expects an impairment charge of up to $2.2 billion in the first quarter due to the outbreak and for revenue to nosedive by $17 million to $22 million in the quarter. (The company will report its first quarter results next Thursday.)

Pham has meanwhile become the longest-serving top executive at Uber, outlasting not just Kalanick, who was forced to resign as CEO back in 2018, but also the members of Kalanick’s so-called “A team” of trusted advisors. Included in this circle: Ryan Graves, who was one of Uber’s first employees a board member of the company until last May; Uber’s former head of product, Daniel Graf, who has since started his own company; Eric Alexander, who was Uber’s president of business in Asia and was fired in 2017 over his handling of a rape investigation in India; and Emil Michael, Uber’s controversial former SVP of business who left the company in 2017, though it remains unknown if he resigned or was fired.

Pham — who was recruited by Kalanick from VMWare, where he’d spent the previous eight years — stood to make more than $200 million from Uber’s IPO last year, according to Business Insider. At the time, he owned 5.4 million shares.

It’s a true American success story. At age 12, Pham escaped Vietnam with his mother and brother in a fishing boat that was reportedly carrying dozens of other refugees. After first spending 10 months at camp in Indonesia that he has described as having no sanitation and offering only a carp over their heads, his family later arrived in Maryland and Pham, an excellent student, wound up studying at MIT.

Pham would go on to nab a master’s degree in electrical engineering before being drawn to job in Silicon Valley, where his first job was at Hewlett Packard. He said after three years, he “got bored” and joined Silicon Graphics, whose cofounder, Jim Clark, would later cofound Netscape with a young Marc Andreessen.

Pham spoke at a startup event in February, roughly one month before the Bay Area instituted its shelter-in-place rules. You can check out the talk below.

Goal Talk Podcast Episode 12: The Dos & Don’ts of Effective Ad Copy

On each episode of this season of the Goal Talk podcast, I interview a marketing or management expert to bring small business owners and marketers the information they need to successfully grow their businesses.

Last week, Mark Irvine and I sat down for a very special episode of the Goal Talk Podcast, where we dove into marketing during COVID-19. From search trend changes to specific data we’re seeing in multiple industries in response to social distancing effects of the coronavirus pandemic, we break down the essential information marketers should know, as well as resources marketers can use to make effective decisions for their businesses. If you haven’t heard that episode, we definitely recommend giving it a listen! Find it here.

This week’s topic: The ins and outs of ad copy

Let’s get right to it: Ad copy is arguably the most important aspect of your search marketing campaigns. Often the most visible component of an ad, the copy is the hook, line, and sinker to reel in your target audience. While many other aspects we discuss are also very important in the success of your campaigns, ad copy is how people will experience your company and how you will encourage those clicks.

Goal Talk podcast season 1 episode 12 artwork.


In this episode, I interview Customer Success Program Manager Jeff Stevens on how to effectively write ad copy that inspires clicks for any industry.

Throughout the episode, we discuss:

  • How to approach writing compelling ad copy.
  • How to meet Google’s set of conditions for a high quality score.
  • How to organize your headlines and descriptions.
  • Different formats and extensions to utilize.
  • How to use keywords for relevancy and extensions.
  • And more!

An important note about the episode: This interview with Jeff was recorded before we’ve felt the majority of the effects of the coronavirus pandemic. These insights are mainly focused on tactics available within the traditional marketing landscape, so some options will not be available to you or your business at the moment. Regardless, these insights to writing ad copy will benefit you in adjusting existing copy and for writing new ads.

You can find this week’s episode on Apple Podcasts and Spotify, as well as your favorite podcast app. Also, don’t forget to watch new episodes on our YouTube channel, follow the podcast’s Twitter account for episode releases, ask the hosts questions, and join in on the conversation.

About the podcast

The Goal Talk podcast is all about giving small business owners and marketers the information they need to succeed. From advertising tactics that help you personalize your message for your customers to management styles that will help your employees perform at their full potential and feel satisfied in their role, we’re sharing valuable takeaways to help you and your business flourish by interviewing the experts and sharing their insights. Listen here.

Best Practices With React Hooks

Best Practices With React Hooks

Best Practices With React Hooks

Adeneye David Abiodun

React Hooks are a new addition in React 16.8 that let you use state and other React features without writing a class component. In other words, Hooks are functions that let you “hook into” React state and lifecycle features from function components. (They do not work inside class components.)

React provides a few built-in Hooks like useState. You can also create your own Hooks to reuse stateful behavior between different components. The example below shows a counter whose state is managed using the useState() hook. Each time you click on the button, we make use of setCount() to update the value of count by 1.

See the Pen [React Hook example with Counter]( by Adeneye Abiodun David.

See the Pen React Hook example with Counter by Adeneye Abiodun David.

This example renders a counter with a value of 0. When you click the button, it increments the value by 1. The initial value of the component is defined using useState.

const [count, setCount] = useState(0)

As you can see, we set that to be 0. Then we use the onClick() method to call setCount when we want to increment the value.

<button onClick={() => setCount(count + 1)}> Click me

Before the release of React Hooks, this example would have used more lines of code, as we’d have had to make use of a class component.

Rules Of React Hooks

Before we dive deep into the best practices, we need to understand the rules of React Hooks which are also some of the fundamental concepts of the practices presented in this article.

React Hooks are JavaScript functions, but you need to follow two rules when using them.

  1. Call Hooks at the top level;
  2. Only call Hooks from React components.

Note: These two rules were introduced in React Hooks, as opposed to being part of JavaScript itself.

Let’s look at these rules in more detail.

Call Hooks At The Top Level

Don’t call Hooks inside loops, conditions, or nested functions. Always use Hooks at the top level of your React function. By following this rule, you ensure that Hooks are called in the same order each time a component renders. That’s what allows React to correctly preserve the state of Hooks between multiple useState and useEffect calls.

Let’s make a Form component which will have two states:

  • accountName
  • accountDetail

These states will have default values, we’ll make use of the useEffect hook to persist the state to either the local storage of our browser or to the title of our document.

Now, this component will be maybe to successfully manage its state if it remains the same between multiple calls of useState and useEffect.

function Form() { // 1. Use the accountName state variable const [accountName, setAccountName] = useState('David'); // 2. Use an effect for persisting the form useEffect(function persistForm() { localStorage.setItem('formData', accountName); }); // 3. Use the accountDetail state variable const [accountDetail, setAccountDetail] = useState('Active'); // 4. Use an effect for updating the title useEffect(function updateStatus() { document.title = accountName + ' ' + accountDetail; }); // ...

If the order of our Hooks changes (which can be possible when they are called in loops or conditionals), React will have a hard time figuring out how to preserve the state of our component.

// ------------
useState('David') // 1. Initialize the accountName state variable with 'David'
useEffect(persistForm) // 2. Add an effect for persisting the form
useState('Active') // 3. Initialize the accountdetail state variable with 'Active'
useEffect(updateStatus) // 4. Add an effect for updating the status // -------------
// Second render
// -------------
useState('David') // 1. Read the accountName state variable (argument is ignored)
useEffect(persistForm) // 2. Replace the effect for persisting the form
useState('Active') // 3. Read the accountDetail state variable (argument is ignored)
useEffect(updateStatus) // 4. Replace the effect for updating the status // ...

That’s the order React follows to call our hooks. Since the order remains the same, it will be able to preserve the state of our component. But what happens if we put a Hook call inside a condition?

// 🔴 We're breaking the first rule by using a Hook in a condition if (accountName !== '') { useEffect(function persistForm() { localStorage.setItem('formData', accountName); }); }

The accountName !== '' condition is true on the first render, so we run this Hook. However, on the next render the user might clear the form, making the condition false. Now that we skip this Hook during rendering, the order of the Hook calls becomes different:

useState('David') // 1. Read the accountName state variable (argument is ignored)
// useEffect(persistForm) // 🔴 This Hook was skipped!
useState('Active') // 🔴 2 (but was 3). Fail to read the accountDetails state variable
useEffect(updateStatus) // 🔴 3 (but was 4). Fail to replace the effect

React wouldn’t know what to return for the second useState Hook call. React expected that the second Hook call in this component corresponds to the persistForm effect, just like during the previous render — but it doesn’t anymore. From that point on, every next Hook call after the one we skipped would also shift by one — leading to bugs.

This is why Hooks must be called on the top level of our components. If we want to run an effect conditionally, we can put that condition inside our Hook.

Note: Check out the React Hook docs to read more on this topic.

Only Call Hooks From React Components

Don’t call Hooks from regular JavaScript functions. Instead, you can call Hooks from React function components. Let’s take look at the difference between JavaScript function and React component below:

JavaScript Function
import { useState } = "react"; function toCelsius(fahrenheit) { const [name, setName] = useState("David"); return (5/9) * (fahrenheit-32);
document.getElementById("demo").innerHTML = toCelsius;

Here we import the useState hook from the React package, and then declared our function. But this is invalid as it is not a React component.

React Function

import React, { useState} from "react";
import ReactDOM from "react-dom"; function Account(props) { const [name, setName] = useState("David"); return <p>Hello, {name}! The price is <b>{}</b> and the total amount is <b>{props.amount}</b></p>
ReactDom.render( <Account total={20} amount={5000} />, document.getElementById('root')

Even though the body of both looks similar, the latter becomes a component when we import React into the file. This is what makes it possible for us to use things like JSX and React hooks inside.

If you happened to import your preferred hook without importing React (which makes it a regular function), you will not be able to make use of the Hook you’ve imported as the Hook is accessible only in React component.

Call Hooks From Custom Hooks

A custom Hook is a JavaScript function whose name starts with use and that may call other Hooks. For example, useUserName is used below a custom Hook that calls the useState and useEffect hooks. It fetches data from an API, loops through the data, and calls setIsPresent() if the specific username it received is present in the API data.

export default function useUserName(userName) { const [isPresent, setIsPresent] = useState(false); useEffect(() => { const data = MockedApi.fetchData(); data.then((res) => { res.forEach((e) => { if ( === userName) { setIsPresent(true); } }); }); }); return isPresent;

We can then go on to reuse the functionality of this hook in other places where we need such in our application. In such places, except when needed, we don’t have to call useState or useEffect anymore.

By following this rule, you ensure that all stateful logic in a component is clearly visible from its source code.

ESLint Plugin

ESLint plugin called eslint-plugin-react-hooks enforces the rules above. This comes in handy in enforcing the rules when working on a project. I suggest you make use of this plugin when working on your project, especially when working with others. You can add this plugin to your project if you’d like to try it:

// Your ESLint configuration
{ "plugins": [ // ... "react-hooks" ], "rules": { // ... "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies }

This plugin is included by default in Create React App. So you don’t need to add it if you bootstrap your React applications using Create-React-App.

Thinking In Hooks

Let’s take a brief look at class components and functional components (with Hooks), before diving into the few Hooks best practices.

The simplest way to define a component in React is to write a JavaScript function that returns a React element:

function Welcome(props) { return <h1>Hello, {}</h1>;

The Welcome component accepts props which is an object that contains data and returns a React element. We can then import and render this component in another component.

The class component uses a programming methodology called Encapsulation which basically means that everything relevant to the class component will live within it. Life-cycle methods (constructors, componentDidMount(), render, and so on) give components a predictable structure.

Encapsulation is one of the fundamentals of OOP (Object-Oriented Programming). It refers to the bundling of data within the methods that operate on that data, and is used to hide the values or state of a structured data object inside a class — preventing unauthorized parties’ direct access to them.

With Hooks, the composition of a component changes from being a combination of life-cycle Hooks — to functionalities with some render at the end.

Function Component

The example below shows how custom Hooks can be used in a functional component (without showcasing what the body is). However, what it does or can do is not limited. It could be instantiating state variables, consuming contexts, subscribing the component to various side effects — or all of the above if you’re using a custom hook!

function { useHook{...}; useHook{...}; useHook{...}; return ( 
); }

Class Component

A class component requires you to extend from React.Component and create a render function which returns a React element. This requires more code but will also give you some benefits.

class { constructor(props) {...} componentDidMount() {...} componentWillUnmount() {...} render() {...}

There are some benefits you get by using functional components in React:

  1. It will get easier to separate container and presentational components because you need to think more about your component’s state if you don’t have access to setState() in your component.
  2. Functional components are much easier to read and test because they are plain JavaScript functions without state or lifecycle-hooks.
  3. You end up with less code.
  4. The React team mentioned that there may be a performance boost for functional components in future React versions.

This leads to the first best practice when using React Hooks.

Hooks Best Practices

1. Simplify Your Hooks

Keeping React Hooks simple will give you the power to effectively control and manipulate what goes on in a component throughout its lifetime. Avoid writing custom Hooks as much as possible; you can inline a useState() or useEffect() instead of creating your own hook.

If you find yourself making use of a bunch of custom Hooks that are related in functionality, you can create a custom hook that acts as a wrapper for these. Let’s take a look at two different functional components with hooks below.

Functional Component v1
function { useHook(...); useHook(...); useHook(...); return( <div>...</div> );
Functional Component v2
function { useCustomHook(...); useHook(...); useHook(...); return( <div>...</div> );

v2 is a better version because it keeps the hook simple and all other useHooks are inline accordingly. This allows us to create functionality that can be reused across different components and also gives us more power to control and manipulate our components effectively. Instead of adopting v1 in which our components are littered with Hooks, you should make use of v2 which will make debugging easy and your code cleaner.

2. Organize And Structure Your Hooks

One of the advantages of React Hooks is the ability to write less code that is easy to read. In some cases, the amount of useEffect() and useState() can still be confusing. When you keep your component organized it will help in readability and keep the flow of your components consistent and predictable. If your custom Hooks are too complicated, you can always break them down to sub-custom Hooks. Extract the logic of your component to custom Hooks to make your code readable.

3. Use React Hooks Snippets

React Hooks Snippets is a Visual Studio Code extension to make React Hooks easier and faster. Currently, five hooks are supported:

  • useState()
  • useEffect()
  • useContext()
  • useCallback()
  • useMemo()

Other snippets have also been added. I have tried working with these Hooks and it has been one of the best practices I’ve personally used while working with them.

There are two ways you can add React Hooks snippets to your project:

  1. Command
    Launch the VS Code Quick open (Ctrl+P), paste ext install ALDuncanson.react-hooks-snippets and press Enter.
  2. Extension Marketplace
    Launch ‘VS Code Extension Marketplace’ (Ctrl+Shift+X) and search for ‘React Hook Snippets’. Then, look for the ‘Alduncanson’ icon.

I recommend the first snippet. Read more about the snippets here or check for the lastest Hooks snippets here.

4. Put Hooks Rules Into Consideration

Endeavor to always put the two rules of Hooks we learned earlier into consideration while working with React Hooks.

  • Only call your Hooks at the top level. Don’t call Hooks inside loops, conditions or nested functions.
  • Always call Hooks from React function components or from custom Hooks, don’t call Hooks from regular JavaScript functions.

The ESlint plugin called eslint-plugin-react-hooks enforces these two rules, you can add this plugin to your project if you’d like it as we explain above in rules of hooks section.

Best practices have not been fully resolved because Hooks are still relatively new. So adoption should be taken with precaution one would take in adopting in any early technology. With that in mind, Hooks are the way for the future of React.


I hope you enjoyed this tutorial. We’ve learned the two most important rules of React Hooks and how to effectively think in Hooks. We looked at functional components and some best practices in writing Hooks the right and effective way. As brief as the rules are, it’s important to make them your guiding compass when writing rules. If you are prone to forget it, you can make use of the ESLint plugin to enforce it.

I hope you will take all of the lessons learned here in your next React project. Good luck!


Smashing Editorial (ks, ra, yk, il)