 Hi, I'm Allison Hurt and I'm the Graphics Editor on the Visuals Team at NPR. We're an interdisciplinary team of photographers, photo editors, designers, and developers who help tell stories in the NPR newsroom. My focus most often is on small-scale, short turnaround graphics that a company's stories published in our CMS, bar charts, maps, tables, things that need to be turned around anywhere from a couple hours to a couple days. So I've been trying to cook more lately, but inevitably that half-hour recipe actually takes me like an hour, an hour and a half. And then I finally realized that these recipes often don't take into account how long it takes to get everything ready so you can actually make dinner. You have to clean the cook service, find the right pots and cooking implements, chop all those vegetables. If you prep everything ahead of time, the actual cooking process goes much more efficiently. You're able to focus on the act of cooking rather than that onion you're racing to chop before the garlic burns in the pan. And really the same philosophy applies to a lot of the work that we do that needs to be done on a very short timeline. If your tools and processes are shut up ahead of time, you're good to go when the assignment comes in. Or maybe this is a slightly better analogy. You're an iron chef and you've got to be ready for whatever challenge your secret ingredient, Chairman Kaga, throws down. Today's secret ingredient is yam. So from here I'm going to talk a lot about our specific tools, all of which are open sourced and available on GitHub. What works for us may not work for you, but hopefully there are some useful ideas here as you optimize your own internal best practices. So this is what we're starting with. On our team, everyone's using Macs, running the latest or near-latest operating system. We host our work on Amazon S3. When we develop our projects, we're running a Flask app locally to render content dynamically. And then we bake out flat files to deploy to S3. Sort of philosophically, our team prefers to build static sites over dynamic sites with like a database backend. Static sites stand up better to heavy traffic. And there's less or no kind of long-term maintenance required. And so many of our projects are just kind of like one-offs that they're not necessarily things that need to be kind of maintained over a long period of time. We do some development in Python. Most of what we do is in JavaScript. Most charts and data visualizations are done in D3. So first we start with, we all start from the same place, working from the same initial development environment. On our team blog, we have a how to set up your computer guide. And we use it ourselves as a resource whenever we have a new teammate or someone gets a new machine. We have a new intern, and that's three times a year. One of the first thing he or she does is they wipe their assigned machine. They set it up from scratch. And then they update the blog post because if there's like a new OS that's come out, like inevitably there are new quirks that are introduced. Every project that we build has a read me with detailed set of instructions. And it's generally structured the same way. You install node, you make a virtual environment, you pip install requirements. Each project operates in its own virtual environment with the requirements text file that lists all of the relevant dependencies. This makes it easy to start a new project, to pick up someone else's code, to go back and look at an old project. And we're also playing with sort of smaller optimizations like writing Apple scripts to launch terminal windows that are relevant to a given project. This one is for our daily graphics rig, which requires three terminal windows. One for to generate new projects and publish them out. One for the web server and one to commit graphics to GitHub. Because we store our graphics in a separate private repo. So, guilty admission. As recently as a few years ago, we were still sort of copying and even editing files directly on the server. We had few real backups of our work. And it was very hard to work collaboratively on the same file without big fitting each other. So, yeah, don't be like going back up your work. So if it catches fire, you can recover it. GitHub is your friend. I love that gift. Also have a style guide or some agreed upon best practices. That's the link to ours up there on GitHub. This is a snippet from our team's JavaScript best practices document. Some of the highlights, we prefer single quotes to double quotes. Most JavaScript variables should be camel case. Unless they're constants or configuration parameters, in which case they're all caps with underscores. So you can tell the difference between them by the glance. We prefer to use bracket notation rather than dot notation. I know that a lot of D3 example code out there is all about dot notation. D dot, like aid or D dot, whatever. But I do like how bracket notation makes it clear that you're accessing a piece of data rather than trying to call a function or get the length of the array or something like that. And it lets you pass in variables. Anyway, I'm not saying this is how everyone else should write their JavaScript. This is just the standards that our team has agreed to follow. So that we're all consistent in our work. And a coding style guide helps make your code more consistent and readable like to current teammates offering feedback and bug fixes. And also to future you. Also important, have defined color and type standards and sort of bake these in, these will probably evolve over time. But it's much easier to work within a design system, especially on a really short deadline than it is to have to reinvent it every time. Also, one thing that we're trying to be better at, we're not all working on the same projects and it's sometimes hard to keep up with what everybody else is doing and how they're solving problems. So we've recently started periodic code review sessions among the team members who write code to discuss and critique approaches we've taken in our work. And we're looking to do the same with periodic design reviews. We found that it's useful to have a consistent starting point for all of our projects. For us, our projects tend to follow one of two tracks, big standalone projects and smaller works that we embed into stories in our CMS. With the bigger projects, we clone what we call the app template. It includes less, bootstrap, custom Google events for analytics, Google spreadsheet integration. I'll talk more about that soon. And some GitHub project management helpers like default issue labels and tickets for all those things like device testing that we have to do for every single project. We've even gotten into things recently like AB testing. So we build our project on top of that and afterwards if we learn some new way to optimize our process. We fold that back into the app template for the next project. Incidentally, this particular project, we've learned a lot since this project which ran a little over a year ago. It was a massive undertaking, an international documentary project that followed the supply chain of a T-shirt from Cotton in Mississippi to Yarn in Indonesia to Assembly in Bangladesh to and then to Brooklyn for printing. It's all over the place. And it was a combination of video and text and graphics and it was quite a project. For smaller projects, like quick turnaround graphics that go with news stories, we have a single overall project that we call daily graphics. It's a lighter weight version of the app template with some sort of customizations we've made like for this particular use case. Everything exists in the same repo. It's all part of the same ecosystem. So in this case, we're cloning folders of starter code for various frequently used chart types. And they have the HTML, the JavaScript, the CSS and a Google spreadsheet for text. So in this case, we're just, whoops. We're just typing in like a fab command and it just copies over a folder of stuff. And honestly, frankly, there are so many ways. There are really only so many times I want to define an axis or draw stacked bars in D3. I kind of just want to do it once and then reuse it. This way I have starter code to give me part of the way there or most of the way if it's a really simple graphic. And then I can modify it as needed for the project at hand. Or go in a completely different direction. So there are also common design problems that we come across all the time. And you can certainly adapt them from project to project but oftentimes you don't need to reinvent the wheel. For example, our code templates already include approaches for making our D3-based graphics work responsively. About half our audience is on mobile so we need to produce work that they can read and understand. We went to almost fully code-based graphics in part because with a flat chart, a static chart, the text may be totally readable on desktop but on a phone everything is scaled down and then possible to read. So one thing I like to do with charts is lock the aspect ratio. Everything stays at four by three or 16 by nine. So the relationship of elements within the chart remains the same. I may also adjust the number of Y-axis and X-axis ticks depending on the display width which is not the same as the window width. On desktop we have a right rail for an ad and related stories. As the window shrinks the right rail goes away and there's extra padding here and there. So the width available to the actual chart shifts quite a bit. So our usual strategy for handling the window resize is a bit kind of cheating. When the screen resizes the existing chart is destroyed and quickly redrawn to reflect the new dimensions. If the graphics relatively simple there's no obvious performance hit. But for more complex graphics say like a world map where there are lots of objects being drawn to the screen this isn't really an optimal approach like it becomes kind of visibly sluggish. It's better to draw the map once and then update it to the page resizes. And honestly like the only people who are doing like the squishy like expanding thing or like other nerds. So it's not like your average user is doing this. So we've also been working on approach to making data tables responsive based on a blog post written by Aaron Gustafson. If you shrink the, as you shrink the view for it down the table and the table becomes too wide. You can use CSS media queries to shift the table into something more row based. And we've built that into our responsive data table template and we can use it or not depending on kind of what the project needs. So like here we used a sort of heat mapping approach to presenting segments of responses to full questions about how people respond to stress. It's presented as a grid on desktop. And then as we get to smaller grid, smaller screens it's more row based but we preserve the color shading. So you can still sort of see at a glance the kind of the difference in intensity. For most of our projects we use Google spreadsheets as a kind of mini CMS. One that can take slightly different shapes with every use. So my colleague Chris Grosskopf created a Python library called copy text, which takes a Google spreadsheet or any XLSX file and makes the data accessible for use on the page. And then we write these values to the page with JINJA tags which is a JINJA Python template language. Our most common use case is arbitrary key value pairs because specify a key and a value in the sheet in this case a headline and then the headline, the subhead and the subhead. Refer to those keys on the template page. And here in this case it's kind of tiny but the all uppercase copy refers to the copy object like the universe of stuff that came from the spreadsheet. Labels refers to the individual sheet that the key value pairs live on. And you can have multiple sheets in a single Google spreadsheet all with different content, different uses. And here's how it looks on the rendered page. I try to collect all of the text in my project from the intro blurbs to the footnotes to the tiny labels and error messages. In the Google spreadsheet it's good for sanity to have these like things together and it's good for copy editors to be able to see everything in all in one place. Because like going through the biz on their own they're not necessarily gonna catch everything and nobody wants to be responsible for the error message with the really embarrassing typo. You can also use the Google spreadsheet to as a spreadsheet and store structured data in it. And then you can loop through it row by row to make an HTML data table. Or you can even write it to the page as a serialized JSON object if you wanna manipulate it with D3 and make a graphic out of it. This way you don't even have to load in a separate CSV or JSON file, it's just baked onto the page and you can access it immediately. We've also used spreadsheets to reflect configuration. This is from a longer form story, a standalone project. Here the leftmost column refers to a particular display template, a chapter header, a photo with a quote, a block of text. Every sort of like style of rendering like gets its own template. And then it feeds that sort of sub template the appropriate information. This is the template code that kind of loops through that. And here's how a couple of those sort of like sub templates as many templates appear on the page. You have a fragment of a title card up at the top, a couple graphs of text, a photo with a pull quote and each of those were separate rows in the spreadsheet and they're calling separate like sort of template includes. This was from a story about a unit within the military that works to identify the remains of missing servicemen and women and the relatives of one such servicemen who were frustrated with that offices sort of speed and methodology. Similarly our friends at the New York Times recently released something called RGML that works similarly except it's based on Google Docs rather than spreadsheets. It's arguably a more natural environment to write and edit like big blocks of text. I haven't used it yet but I'm pretty intrigued. So we have another reason for wanting to separate out text from code and that's open sourcing. Our team motto is work in public. I let her press these cards a while back and we try to be pretty open about what we do and how we do it. Our lawyers are cool with us open sourcing our code but understandably there's some sensitivity about open sourcing content. That's text, audio, photos, et cetera. So having all of our text in a spreadsheet rather than in the GitHub repo allows us to separate code and content. And on that note, we do have a separate workflow for larger assets, the images, the audio files and that kind of thing. We don't want them in the repo because they're content and we also don't want them in the repo because they're kind of huge. They don't change often and they slow down syncing with GitHub. So we store them in a separate get ignored assets folder and then there's a separate process to publish them out to S3 and sync up assets between users. It's a process we're still sort of iterating on. For example, there's no version control in these files. The original assumption being that they wouldn't change often. But if they are changing and we experimented earlier this year with storing markdown files in the assets folder it's again easy for people to big foot each other. So last week we had a project involving crime clearance data from the FBI. The crime clearance rate measures the number of crimes a police agency solved in a given year versus the number of new crimes reported. Clear crimes are counted against the year they're cleared not the year they happened. So an agency could have a clearance rate of over 100%. Clearance doesn't necessarily mean that someone was arrested, tried and convicted. Generally means the subject was identified and arrested and then passed on to the courts. So we made a look up tool for people to be able to look up how their local police agencies are doing with caveats. And we were going to display these against sort of medians for their population groups but the data was a little like there for some cities like major cities we didn't have all the data. So it just seemed where to calculate medians based on that. So we just kind of left that out and displayed messages where the data was a little questionable. So the way we structured this we had a CSV with agency names, states and IDs to use as a look up table. And then we had like 22,000 JSON files one for each agency. And like the normal way these JSON files took forever to upload like set it to run and like go to lunch. So my colleague David Eads wrote a script to upload many files all at once paralyzed and brought the upload time to just like a couple of minutes. And this is something I imagine we'll reuse again sometime. So finally we published the project out to S3. It's just one command typed into the terminal and it runs a script that pulls down the latest Google spreadsheets content bakes out a flatten page, syncs the larger assets and deploys all the files out to Amazon S3. Here's a snippet of the Python code that's deploying everything. So once I have my finished product I need to get it on the story page in the CMS. Now our CMS at NPR it's a homegrown system called Jamus. It's remarkably flexible. We can drop in chunks of HTML and JavaScript even add custom CSS to a page. But there's a trade off. Any inline code is subject to potential JavaScript or CSX conflicts later on as the site evolves. And we ran into this in a big way when the site went responsive a couple of years ago. So we've gone all in on iframes to sort of like encapsulate our work. So you can set an iframe to 100% width but that doesn't make it responsive. The height is still hard coded and as the frame like widens and narrows the content inside it shifts. The text may wrap in such a way that the overall content is actually taller. Or the chart shrinks so the overall content is shorter. But the iframe's height remains the same. So the result is that either the content gets cut off or you have this really ugly white space at the bottom. So based on some earlier work from the NPR tech team and others we made a library for responsive iframes called PIM.js. In its simplest form, this is what you do. You add one bit of code to the CMS or parent page or if your CMS likes to strip out inline JavaScript you can embed it this way. And then you add a bit of code to your project or child page. You can specify a callback function to run on load and then every time the page resizes it calls that function. And so this is what I use to draw the charts and redraw them as needed. It's just the same function that's being called over and over again. So what all this does, this parent and child thing, this sets up a connection between the parent page and the child iframe and they can pass messages back and forth. Messages like the width of the parent or the height of the child. And you can also within your code trigger the iframe to resize at any time. Say a user clicks a button that opens a drawer of text which increases the height of the content inside the frame. And with that, we've served up our project and we're ready to face the next challenge in solving so many of the other problems that we have to deal with when creating a project. Our development environment, template code, responsive strategy, putting it on a page. We've prepared our kitchen and then when the next meal is ordered we can dive right in. So thank you. Thank you.