<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[superhighfives - Medium]]></title>
        <description><![CDATA[Tutorials and thoughts on front end development - Medium]]></description>
        <link>https://medium.com/superhighfives?source=rss----d2901740a9f0---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>superhighfives - Medium</title>
            <link>https://medium.com/superhighfives?source=rss----d2901740a9f0---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 24 Jun 2026 04:45:28 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/superhighfives" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Lysterfield Lake — An AI Experiment]]></title>
            <link>https://medium.com/superhighfives/lysterfield-lake-an-ai-experiment-71345aa8c016?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/71345aa8c016</guid>
            <category><![CDATA[generative-ai]]></category>
            <category><![CDATA[music]]></category>
            <category><![CDATA[art]]></category>
            <category><![CDATA[machine-learning]]></category>
            <category><![CDATA[creative-coding]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Mon, 04 Dec 2023 11:08:25 GMT</pubDate>
            <atom:updated>2024-05-31T08:06:11.682Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XmShaFO_kh5uEUr2wXNIvQ.jpeg" /><figcaption>The visuals of Lysterfield Lake.</figcaption></figure><h3>Lysterfield Lake</h3><h4>Machine learning, art, accelerometers, and the joy of slow progress and fast feedback loops (or, how I built <a href="https://lysterfieldlake.com/">Lysterfield Lake</a>)</h4><h3>⚠️ <strong>You can see a new <em>(updated, mobile, and dark-mode friendly)</em> version of this case study at </strong><a href="https://charliegleason.com/work/lysterfield-lake">charliegleason.com/work/lysterfield-lake</a></h3><p><a href="https://wearebrightly.com/">Lysterfield Lake</a> is a song about a place outside Melbourne, Australia. It’s about the endless summers of your youth, and the tiny changes in you that you don’t even notice adding up. It’s also about memories, which, like polaroids, fade and change over time.</p><p>I don’t remember exactly when I wrote it in much the same way I don’t remember exactly when I started this project, which has spanned the better part of a year and has all but consumed the most creative bits of my brain.</p><p>I think it all began when I came across <a href="https://replicate.com/">Replicate</a> (and by extention, their open-source container for running machine learning models, <a href="https://github.com/replicate/cog">Cog</a>.) I was so inspired by their <a href="https://replicate.com/explore">Explore</a> page, and, if I’m being totally honest, I was worried about the cost of experimenting with AI. I’d set up a gaming PC in the weird limbo of the 2020 lockdowns, and these tools made it effortless (and for the most part, free) to try, and test, and many, many times, fail.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1-nWOHdCsr71AmDZqTfzXg.jpeg" /><figcaption>A selection of dreams from the final video.</figcaption></figure><p>When I decided to release new music (it’s been seven years since <a href="https://wearebrightly.com/">the last Brightly record</a>) I knew I wanted to build something with these bits and pieces I’d been noodling with. I knew I wasn’t great at making traditional music videos, and I felt empowered by the flexibility of the browsers, and the creative opportunties afforded by using machine learning and AI. I think the result is something greater than the sum of its parts.</p><p>And there are a lot of parts.</p><p>(Also, if you haven’t seen the video, <a href="https://lysterfieldlake.com/">you should go and check it out</a> before I ruin the magic by shining a very bright light on exactly how it all works.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TfMVHZLXL5DO_d9S_vfrRw.gif" /></figure><p>(And if you’d <a href="https://youtu.be/a-9gGCQIPo8">rather check out a recording, you can jump over to YouTube</a> to see a simplified version that should give you a pretty good idea.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Pj698pLZ61e0nNBy9uCLkg.jpeg" /><figcaption>Three images from the video at <a href="https://lysterfieldlake.com/">https://lysterfieldlake.com/</a></figcaption></figure><h3>What is it?</h3><p><a href="https://lysterfieldlake.com/">Lysterfield Lake</a> is a 3D generative interactive music video. It works in the browser, using <a href="https://threejs.org/">Three.js</a> and <a href="https://docs.pmnd.rs/react-three-fiber/getting-started/introduction">react-three-fiber</a> to stitch together seven feeds of video frame by frame, turning a single piece of footage shot on an iPhone into a three-dimensional fever dream. It uses the accelerometer in your phone, if it’s available, or your mouse if you’re on a computer. It shows and hides the protagonist as you watch depending on your actions, offering a myriad of ways to experience it. New dreams can be added at any time.</p><p>Behind the scenes it was modelled in <a href="https://www.blender.org/">Blender</a>, (using a polaroid model by <a href="https://sketchfab.com/edoardogalati">Edoardo Galati</a>), generated in python and shell scripts, and built in JavaScript. It is made up of entirely open-source projects that are freely available.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CbNvx0bZX2ay66YRCR1zkA.jpeg" /><figcaption>A frame of each of the initial dreams.</figcaption></figure><h3>The process</h3><p>So, how does it work? I made a diagram to help.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uF2V2tVSWz7O0iaPv2Jw5A.png" /></figure><p>First, a single video file, shot on an iPhone, is fed through a series of python and shell scripts. The initial one splits the video into individual frames. These frames then go through a bunch of processes depending on their final output.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O9RTYpMfIXkLZUwKTRZ5Iw.gif" /><figcaption>The original footage vs the final output. Note to self: I probably should’ve gotten a haircut before this.</figcaption></figure><h4><strong>The Avatar</strong></h4><p>A 3D-watercolour version of the subject matter (which is, in this case, me).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8qstZlyYHy-fJMnLJ1-lXQ.png" /></figure><ul><li><a href="https://replicate.com/gwang-kim/diffusionclip?input=form&amp;output=preview">DiffusionCLIP</a> turns the image into a painted watercolour style.</li><li><a href="https://replicate.com/arielreplicate/robust_video_matting?input=form&amp;output=preview">RobustVideoMatting</a> finds the subject in the video and creates an alpha mask of it.</li><li>In python, the mask is used with the original image and passed to <a href="https://replicate.com/cjwbw/zoedepth?input=form&amp;output=preview">ZoeDepth</a>, which creates a depth mask.</li><li>These three elements (the watercolour image, the alpha mask, and the depth mask) are used to render the avatar.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4WeH4TJLoUkKhE5QSVXclQ.png" /><figcaption>From frame to 3D avatar.</figcaption></figure><h4><strong>The Background</strong></h4><p>A watercolour version of the original image, without the subject matter.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ucApjXjEx7PgRC3U7L2lWg.png" /></figure><ul><li>Using the alpha mask and the original image, <a href="https://github.com/geekyutao/Inpaint-Anything">Inpaint Anything</a> creates a version of the scene without the avatar in it.</li><li>This inpainted image is then also painted in watercolour using <a href="https://replicate.com/gwang-kim/diffusionclip?input=form&amp;output=preview">DiffusionCLIP</a>.</li><li>This element is then used to render the background.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_FR2X3LnJtr0Ikdo4HzNhA.png" /><figcaption>From frame to watercolour background.</figcaption></figure><h4><strong>The Outline</strong></h4><p>A comic-book style sketch of the subject matter.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tZ2W3LOsMK0Zgnv4J9uFcg.png" /></figure><ul><li>In python, the original image is combined with the alpha mask to create a version with no background.</li><li>This is then fed into <a href="https://github.com/Linzmin1927/Artline_torch">artline-torch</a>, which creates a rough outline sketch.</li><li>This sketch is then overlaid on the avatar during rendering (it also uses a bit of dithering in the custom shader in <a href="https://threejs.org/">Three.js</a>, which is what gives it the printed ink / slight comic book style).</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*o05fPcO6egw_Bcn76pzOVw.png" /><figcaption>From frame to outline.</figcaption></figure><h4><strong>The Dreams</strong></h4><p>Prompt-generated reinterpretations of the original image.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bs4WNCcCUIbKt9ydA29Qvg.png" /></figure><ul><li>The original images are fed into <a href="https://replicate.com/deforum/deforum_stable_diffusion?input=form&amp;output=preview">Deforum Stable Diffusion</a>, along with a prompt, creating unique scenes that mirror the subject matter. For example, trees and a lake that match the contours of the image.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Njykj7-c0k2SEx9ezR6Xbg.png" /><figcaption>From frame to dreams.</figcaption></figure><ul><li>Finally, each frame is manually reviewed one by one and removed if not appropriate. (The primary reason for this is that Stable Diffusion models are trained on image sets that include a large amount of <a href="https://www.dictionary.com/e/fictional-characters/waifu/">waifu</a>’s. Which, because the input clearly contains the shape of a person, means a lot of waifu’s end up in the output, even when politely asking Stable Diffusion not to.)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ax7w7RChWtryBx3B8RuJ2A.png" /><figcaption>Turns out every creative process eventually takes a sharp detour into the uncanniest valleys.</figcaption></figure><ul><li>The remaining images are fed into <a href="https://github.com/nihui/rife-ncnn-vulkan">rife-ncnn-vulkan</a>, which interpolates the missing frames and generates new ones to fill the gaps.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*0ah4bLw1ap2eV8N9Gy4F_w.png" /></figure><h4><strong>The Lyrics</strong></h4><p>(Apologies for my handwriting. I clearly should’ve been a doctor.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Y0nHCS61apVlbhbHwbOnig.png" /></figure><p>At the same time, I recorded myself hand writing the lyrics in Procreate, and then cleaned them up in Adobe’s After Effects.</p><h4>The output</h4><p>An ultra-wide for each dream.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yt-7FiGDVvX5ZTmHhknjlQ.png" /></figure><p>This gets stitched together into an ultra-wide video with 7 square images side-by-side. Originally I tried using a single video for each element, but it‘s impossible to guarantee frame sync across multiple videos in the browser. Fortunately, much like how there’s no rule against eating a candy bar on a dance floor, there’s no rule that videos need to be 16x9. Using custom shaders in the browser, you can simply grab the crop of footage you need for each element in real time.</p><p>And having all of these elements in the one shader affords new opportunities. By passing the depth mask, alpha mask, and the watercolour scene, I was able to generate a rough 3D model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ExHGyPIM2NJm8a6SOlUI0Q.png" /><figcaption>An example of the 3D avatar rendering process.</figcaption></figure><p>Custom shaders essentially let you paint with pixels in real time, and it’s an incredibly exciting medium once you start to explore the possibilities. It is how I can use the pixels from the depth mask to directly impact how close or far each fragment of the 3D avatar is. And, if you’d like to learn more, <a href="https://thebookofshaders.com/">The Book of Shaders</a> is a great resource.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Kh7s2QnV0Vh8g44LuQfNFw.gif" /><figcaption>AI interpreting a depth mask from a video, because we live in the future. (Also, I hand painted a lot of these frames, because technology is, sadly, fallible.)</figcaption></figure><p>Each frame of each video includes the handwritten lyrics, the watercolour scene, the watercolour scene with the background removed, the alpha mask, the depth mask, the sketch, and the dream. And those ultra-wide videos form the backbone of the project.</p><h4>The conclusion</h4><p>The selected dream, represented by one of these videos, is then chopped up and stitched back together in real time in the browser, using <a href="https://github.com/pmndrs/react-three-fiber">react-three-fiber</a>, and many of the incredible resources provided <a href="https://github.com/pmndrs/drei/">as part of the drei project</a>. You can explore each dream one by one, wandering through a landscape that has been imagined by a computer, listening to a song about a time that sits on the very edge of my conciousness. Memory, like AI, is funny like that.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZxvNeoEsg39DUED7Q9lu9g.png" /><figcaption>The rendered final output.</figcaption></figure><p>This is a probably a good time to mention that, while this is the conclusion, this project took every possible detour, hit every possible technical hitch, and explored every possible weird twist and turn. What I’ve ended up with is absolutely nothing like what I imagined, because I didn’t really know what I was going to get at the end. Which makes it a sort-of love letter to the creative process, and to the joys of pursing something purely for the “what-if” of it. There are so many ways that sticking with something can truly surprise you, and that doesn’t have to involve making weird music videos — it could be baking, or cross stitch, or learning a language, or dance. Things you can experiment with, be creative with, grow with. Things that make you feel like you did something you previously couldn’t. Maybe even something great. That might be the greatest feeling there is.</p><p>I hope you find it inspiring, or at the very least, mildly interesting, and I appreciate you taking the time to learn more about how the project works.</p><h3>Okay, how do I find out more?</h3><h3>🎨 📸</h3><p>If you’d like to check it out, you can do so here:<br><a href="https://lysterfieldlake.com/">https://lysterfieldlake.com/</a></p><p>The project itself is entirely open-source, and available at the following GitHub repositories:</p><h4><a href="https://github.com/superhighfives/lysterfield-lake">superhighfives/lysterfield-lake</a></h4><p>A React app, powered by React and <a href="https://docs.pmnd.rs/react-three-fiber/getting-started/introduction">react-three-fiber</a>.</p><h4><a href="https://github.com/superhighfives/lysterfield-lake-pipeline">superhighfives/lysterfield-lake-pipeline</a></h4><p>The pipeline that generates the video used by the app, powered by python and shell-scripts.</p><blockquote><strong>Author’s note: </strong>Fair warning—it’s not the cleanest code, and in the case of the pipeline, it’s not something that will work locally out of the box. I definitely intended open-sourcing this to be educational, in the sense of “oh, that’s how he did that!”, as opposed to aspirational, like “oh, that’s how he thinks React should be written??” It was a passion project, so maybe bear that in mind. Cheers. 😅</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*g397qfMgkYnXmrD7kYoN6w.jpeg" /><figcaption>The cover art for Lysterfield Lake.</figcaption></figure><h4>🎵 🥁</h4><p>If you’d like to check out my music, you can find Brightly here:<br><a href="https://wearebrightly.com/">https://wearebrightly.com/</a></p><h4>💌 🥰</h4><p>If you’d like to share this project, that would be greatly appreciated.</p><h4>🙏 👏</h4><p>Thanks to all my mates who came on country walks while I filmed myself awkwardly mouthing along to my own music. To Ian and Georgia for filming the real thing in Scotland. And to everyone who told me I’m not too old to keep making things.</p><p>Also, this project wouldn’t have happened, like all my projects, without the support and encouragement of <a href="https://github.com/geelen">Glen Maddern</a>. ❤️</p><p>Produced and Mixed by James Seymour in Naarm.<br>Mastered by Andrei “Ony” Eremin in Philadelphia.</p><p>Thank you for listening.<br><a href="http://twitter.com/wearebrightly">@wearebrightly</a> / wearebrightly.com</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=71345aa8c016" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/lysterfield-lake-an-ai-experiment-71345aa8c016">Lysterfield Lake — An AI Experiment</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Introducing Pika]]></title>
            <link>https://medium.com/superhighfives/introducing-pika-d7725c397585?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/d7725c397585</guid>
            <category><![CDATA[swiftui]]></category>
            <category><![CDATA[design-tools]]></category>
            <category><![CDATA[swift]]></category>
            <category><![CDATA[mac]]></category>
            <category><![CDATA[open-source]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Mon, 11 Jan 2021 21:49:47 GMT</pubDate>
            <atom:updated>2021-01-11T21:49:47.155Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*G2iQfb_4dG81BdgZSeIAuQ.jpeg" /><figcaption>A collection of screenshots of Pika, in dark and light modes.</figcaption></figure><h4>A free, open-source colour picker app for macOS</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/128/1*0tKxof34FkThyQ8XGay2gQ@2x.png" /></figure><p><strong>Pika</strong> (pronounced pi·kuh, like picker) is an easy to use, open-source, <a href="https://superhighfives.com/pika">native colour picker for macOS</a>. Pika makes it simple to quickly find colours onscreen, in the format you need, so you can get on with being a speedy, successful designer.</p><p>It was designed and built from the ground up as a love letter to macOS, by a designer, for designers. In that spirit, <a href="https://github.com/superhighfives/pika">the source code is freely available</a>, as is the app, and I would love for more people to get involved in its roadmap and its future.</p><h3>The TL;DR:</h3><ul><li><strong>You can check Pika out at </strong><a href="https://superhighfives.com/pika"><strong>superhighfives.com/pika</strong></a><strong>.</strong></li><li>The source code is <a href="https://github.com/superhighfives/pika">available on GitHub</a>. Contributions are welcomed and encouraged. I have a laundry list of stuff I’d love to do in the project <a href="https://github.com/superhighfives/pika/projects/1">roadmap</a>, and you can <a href="https://github.com/superhighfives/pika/issues/new">create issues</a>, or <a href="https://github.com/superhighfives/pika/compare">open your own PR</a>. The world is your oyster.</li><li>The core code licence is MIT, while all libraries and third-party extensions have their own licences, which are flagged in each.</li><li>I’d love to hear your feedback, and your contributions. The easiest way is to open a <a href="https://github.com/superhighfives/pika/issues/new?assignees=&amp;labels=enhancement&amp;template=feature_request.md&amp;title=">feature request on GitHub</a>.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/768/1*ljmELxsz2LMHuKHzX8CdEA@2x.png" /><figcaption>The primary Pika interface, pronounced pi·kuh, in light and dark mode.</figcaption></figure><h3>The Longer Story</h3><p>I’ve always wanted to develop for macOS.</p><p>I got my first iMac (the <a href="https://en.wikipedia.org/wiki/IMac_G4">ridiculous, and ridiculously great, G4 lamp</a>) when I started university, and coming from Windows I grew a real affection for the craftspersonship of Mac apps. I loved the attention to detail, and the way the operating system seemed really connected–you could easily add the rad emo song you were listening to in iTunes to a LiveJournal post you were writing in another app. It felt effortless, and magic.</p><p>Since then, I’ve wanted to craft something that made people feel how that felt. But every time I tried to start learning, I’d download XCode, open it up, and come unstuck. Objective-C has always felt wildly verbose to me, and when I got the urge to dip yet another toe in the water I’d end up wrestling with certificate signing until I gave up, deflated.</p><p>Then, in 2014, Swift was announced, and it promised to be the answer to all of my questions. A new syntax, with modern features, and an excited new community. In 2019, the declarative SwiftUI framework followed, as did opportunities to share code between macOS, iOS, tvOS, and watchOS. Suddenly all I needed was a genuinely horrifying pandemic to justify not leaving my study for a couple of weeks, and I was all set to fulfil my lifelong dream.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/954/1*gRKcfhuEH7VWefPTn2BmPQ@2x.png" /></figure><p>As tends to be the case, it ended up leading me down an endless warren of endless warrens of rabbit holes, which included (but was not limited to):</p><ul><li>Diving deep into the Apple ecosystem, its history, and the many, many different frameworks and APIs (from UIKit to AppKit to Cocoa to SwiftUI).</li><li>Writing some very questionable, and then hopefully slightly less questionable, Swift code.</li><li>Designing and building a <a href="https://nextjs.org/">NextJS</a>-powered marketing site, at <a href="https://superhighfives.com/pika">superhighfives.com/pika</a>, enchanced with WebGL and <a href="https://greensock.com/gsap/">GSAP</a>.</li><li>Constructing a toolchain to support the <a href="https://sparkle-project.org/">Sparkle</a> release framework, generating XML via markdown.</li><li>Creating a custom shader in WebGL, and porting it to Apple’s (very cool) <a href="https://developer.apple.com/metal/">Metal</a> framework.</li><li>Refactoring things an <em>absurd</em> number of times. Just an <em>absurd</em> number.</li><li>And, because I couldn’t help myself, designing and developing a brand, with its own colour scheme, typography, iconography, and look and feel.</li></ul><p>But, even with all that, it was an absolute blast.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XQRvdh4OGbDG89U9vwODvA.png" /><figcaption>The Pika visual mark.</figcaption></figure><p>I genuinely sweated every single pixel of it, and <a href="https://github.com/superhighfives/pika/projects/1">while there’s much more to do</a> (and some wild SwiftUI features / bugs to dig deeper into) hopefully that effort shows. I’m incredibly excited about the future of Swift and SwiftUI, and I don’t think there’s been a better time to <a href="https://github.com/superhighfives/pika">dip your toe in</a>.</p><p>In that spirit, <strong>I’d love it if you’d take the time to </strong><a href="https://superhighfives.com/pika"><strong>check out Pika</strong></a>, and to contribute to its future, so we can collectively keep this love letter going.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_3zS8zhtBMfP0nGrj-RxEQ.jpeg" /><figcaption>https://superhighfives.com/pika</figcaption></figure><p>PS: You can check out more of my work at <a href="https://charliegleason.com">charliegleason.com</a>,or explore more helpful apps and libraries at <a href="https://superhighfives.com">superhighfives.com</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d7725c397585" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/introducing-pika-d7725c397585">Introducing Pika</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ Zero Config Client Side Routing With Surge.sh]]></title>
            <link>https://medium.com/superhighfives/serving-client-side-routing-with-surge-sh-7b705542cf3?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/7b705542cf3</guid>
            <category><![CDATA[single-page-applications]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[react-router]]></category>
            <category><![CDATA[create-react-app]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Thu, 08 Jun 2017 15:42:37 GMT</pubDate>
            <atom:updated>2020-12-28T01:58:39.885Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LnBkkQtGFRd7rBFS7koSjw.png" /></figure><p><em>Using create-react-app, react-router, and zero configuration</em></p><p>Quick tip—if you’ve built something fancy with <a href="https://github.com/facebookincubator/create-react-app">create-react-app</a> and <a href="https://github.com/ReactTraining/react-router">react-router</a> and you’re not doing any server side stuff (as in, it’s all on the client side), you can get Surge to automatically catch and pass requests to your app. All you need to do is duplicate your index.html after the build step, naming it 200.html.</p><p>You can see this in action here. Without the 200.html, visiting /lyrics would result in a 404:<br><a href="https://stretchurskin.com/lyrics">https://stretchurskin.com/lyrics</a></p><blockquote>Surge’s <em>200.html</em> file is a fallback, like the <em>404.html</em> file, but for single page apps and client-side routing. —<a href="https://surge.sh/help/adding-a-200-page-for-client-side-routing">Surge docs</a></blockquote><p>With create-react-app it’s as easy as amending your build step in your package.json:</p><pre>&quot;build&quot;: &quot;react-scripts build &amp;&amp; cp build/index.html build/200.html&quot;</pre><p>And deploying:</p><pre>surge build</pre><p>And then celebrating, because you are a success. 💖</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7b705542cf3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/serving-client-side-routing-with-surge-sh-7b705542cf3">👌 Zero Config Client Side Routing With Surge.sh</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[A Top Shelf Web Stack—Rails 5 API + ActiveAdmin + Create React App]]></title>
            <link>https://medium.com/superhighfives/a-top-shelf-web-stack-rails-5-api-activeadmin-create-react-app-de5481b7ec0b?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/de5481b7ec0b</guid>
            <category><![CDATA[heroku]]></category>
            <category><![CDATA[create-react-app]]></category>
            <category><![CDATA[how-to]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Mon, 06 Mar 2017 12:23:44 GMT</pubDate>
            <atom:updated>2018-05-16T16:14:58.813Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uJGPKQhqbjEAHkqMz6sCwg.png" /></figure><p>Blending a rock-solid API and CMS with the absolute best in front-end tooling, built as a single project and hosted seamlessly on Heroku.</p><p><strong>Update, 16 May 2018: </strong>First off, thank you to everyone who has taken the time to give feedback, share their experiments, and clap this post. Since I finished this last year I joined Heroku, and with their help I’ve rewritten it to iron out the bugs, implement your feedback, and to include support for Rails 5.2.0, React Router, and Yarn.</p><p><strong>You can find version 2.0 of this post here: </strong><a href="https://blog.heroku.com/a-rock-solid-modern-web-stack"><strong>https://blog.heroku.com/a-rock-solid-modern-web-stack</strong></a></p><p>You can also find latest repo, including a Heroku button you can automagically deploy with, here: <a href="https://github.com/heroku/list-of-ingredients">https://github.com/heroku/list-of-ingredients</a></p><p>Once again, I could not be more appreciative of your support and feedback.</p><p><a href="http://rubyonrails.org/">Rails</a> is an incredible framework, but sometimes you don’t need all the bulk of the asset pipeline and a layout system. In Rails 5 you can now create an API-only Rails app, meaning you can build your front-end however you like. <a href="http://david.heinemeierhansson.com/2012/rails-is-omakase.html">It’s no longer 100% omakase</a>.</p><p>Like using <a href="https://github.com/facebookincubator/create-react-app">create-react-app</a>, for example.</p><p>And for projects that don’t need CMS-like capabilities, that works pretty great straight away. create-react-app even supports <a href="https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#proxying-api-requests-in-development">proxying API requests in development</a>, so you can be running two servers locally without having to do any if NODE_ENV === ‘development’ voodoo. Gosh, create-react-app is great.</p><p>Still, I’ve worked with <a href="https://github.com/activeadmin/activeadmin">ActiveAdmin</a> on a few projects, and as an interface between you and the database, it’s pretty unmatched for ease of use. There are a host of customisation options, and it’s super easy for clients to use if you need a CMS.</p><p>The issue is that removing the non-API bits of Rails breaks it. Not ideal. But never fear, all is not lost! With a couple of steps you can be running a Rails 5, API-only, serving your create-react-app client on the front end, with full access to ActiveAdmin.</p><p>We’re going to build it, then we’re going to <a href="https://list-of-ingredients.herokuapp.com/">deploy it to Heroku</a>, and then we’re going to celebrate with a drink. Because we will have earned it. Given that theme, we’re going to build an app that shows us recipes for delicious drinks. It’s thematically appropriate!</p><p>So, what are we going to use?</p><ul><li><a href="https://github.com/facebookincubator/create-react-app"><strong>Create React App</strong></a><br>All the power of a highly-tuned Webpack config without the hassle.</li><li><a href="http://edgeguides.rubyonrails.org/api_app.html"><strong>Rails in API-only mode</strong></a><br>Just the best bits, leaving React to handle the UI.</li><li><a href="https://github.com/activeadmin/activeadmin"><strong>ActiveAdmin</strong></a><br>An instant CMS backend.</li><li><strong>Seamless deployment on </strong><a href="https://heroku.com/"><strong>Heroku</strong></a><br>Same-origin (so no CORS complications) with build steps to manage both Node and Ruby.</li></ul><p>And it’ll look something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zMIbs0d_Jjfjtb698fweKg.png" /><figcaption>Our app, <a href="https://list-of-ingredients.herokuapp.com/">List of Ingredients</a>, which really does what it says on the tin.</figcaption></figure><p>If you want to skip ahead to the finished repo, you can do so here:<br><a href="https://github.com/superhighfives/list-of-ingredients">https://github.com/superhighfives/list-of-ingredients</a></p><p>And if you want to see it in action, you do that here:<br><a href="https://list-of-ingredients.herokuapp.com/">https://list-of-ingredients.herokuapp.com/</a></p><p>Let’s get started, shall we?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*ATdx9uR70qNq8ATfZ8Odyw.png" /></figure><h3>Step 1: Getting Rails 5 set up</h3><p><em>With that delicious low-carb API-only mode</em></p><p>There are a ton of great tutorials on getting Ruby and Rails set up in your local development environment. <a href="https://gorails.com/setup/">https://gorails.com/setup/</a> will work out your operating system, and will walk you through getting Rails 5.0.1 installed.</p><p>If you’ve already got Rails 5, awesome. The best way to check that is to run rails -v in your terminal. If you see Rails 5.0.1, we’re ready to roll.</p><blockquote>Note: At the time of writing the newest version of Rails, 5.1, doesn’t quite work with these steps. Best to stick with 5.0.1 for now.</blockquote><p>So, first up, start a new Rails app with the --api flag:</p><pre>mkdir list-of-ingredients<br>cd list-of-ingredients<br>rails new . --api</pre><p>Right. We are already part of the way to making a delicious cocktail. Maybe use this time to congratulate yourself, because you’re doing great.</p><p>Once the install process has finished, you can fire up Rails:</p><pre>bin/rails s -p 3001</pre><p>It’ll do some stuff, eventually telling you that it’s listening on <a href="http://localhost:3000.">http://localhost:300</a>1. If you visit it, you should see something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QDHE8QPtVUcXzYQSggti8g.png" /><figcaption>Yay Rails!</figcaption></figure><p>There’s even a <em>kitten!</em> So great.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*kogBntixkKhdzepmePdoEQ.png" /></figure><h3>Step 2: Getting ActiveAdmin working</h3><p><em>With a couple of small tweaks to Rails</em></p><p>(<a href="https://rrott.com/blog/ror/rails-5-api-with-activeadmin-integration.html">Thanks to Roman Rott for this bit.</a>)</p><p>So, incredibly (and awesomely, which is not a word), you can still get <a href="https://github.com/activeadmin/activeadmin">ActiveAdmin</a> working like a charm with this set up. Before you can install it, you just need to switch a couple of Rails classes and add some middleware that ActiveAdmin relies on.</p><p>First, you’ll need to swap your application_controller.rb from using the API to using Base:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/33a01a66063709edef5d46f095af41c7/href">https://medium.com/media/33a01a66063709edef5d46f095af41c7/href</a></iframe><p>As <a href="http://www.carlosramireziii.com/how-to-add-active-admin-to-a-rails-5-api-application.html">Carlos Ramirez mentions</a>, this requirement is an unfortunate design decision from ActiveAdmin, as now any controllers we make that inherit from ApplicationController won’t take advantage of the slimmed down API version.</p><p>There is a work around, though. Add a new api_controller.rb to your app/controllers:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/68a82f964ffc5c8757a9f16f855d2ea2/href">https://medium.com/media/68a82f964ffc5c8757a9f16f855d2ea2/href</a></iframe><p>So you can get your controllers to inherit from ApiController, not ApplicationController. For example:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a06b2613a2b4867ad8aba41b0527ef71/href">https://medium.com/media/a06b2613a2b4867ad8aba41b0527ef71/href</a></iframe><p>From there we’ll need to ensure that the middleware has the stuff it needs for ActiveAdmin to function correctly. API mode strips out cookies and the flash, but we can 100% put them back. In your config/application.rb add these to the Application class:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/10e972ce461e41f9d4c63b3db3ab1184/href">https://medium.com/media/10e972ce461e41f9d4c63b3db3ab1184/href</a></iframe><p>Your config/application.rb should look something like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f27f4c0c1d5684c19b62170210fc368b/href">https://medium.com/media/f27f4c0c1d5684c19b62170210fc368b/href</a></iframe><p>Do not confuse the flash with The Flash, who is likely heavily trademarked. I don’t have the kind of money I’d need laying around if he turns out to be litigious.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FxvfamXvEGnN8A%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fthe-flash-xvfamXvEGnN8A&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FxvfamXvEGnN8A%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="230" frameborder="0" scrolling="no"><a href="https://medium.com/media/fe06af04b3bb4d8a75180b69609b2e92/href">https://medium.com/media/fe06af04b3bb4d8a75180b69609b2e92/href</a></iframe><p>You should also move gem &#39;sqlite3&#39; into the :development, :test group and add gem &#39;pg&#39; into the :production group. Heroku doesn’t support sqlite, and you’ll need to swap those things around once you get to deploying your app. Why not do it now?</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1dd8da48a53d3774ee6dbdf48fd4fd52/href">https://medium.com/media/1dd8da48a53d3774ee6dbdf48fd4fd52/href</a></iframe><p>Now, keen developers will be sharpening their pitchforks right now, because you should 100% run Postgres locally if you’re developing a Real Application, to ensure your local environment matches your production one. But for the purposes of this exercise, let’s just be <em>roguish</em> and tell no one. They’ll never know.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FkKdgdeuO2M08M%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2FkKdgdeuO2M08M&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FkKdgdeuO2M08M%2F200.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="326" frameborder="0" scrolling="no"><a href="https://medium.com/media/dbfe66fd0eda51b6091031f71634cf26/href">https://medium.com/media/dbfe66fd0eda51b6091031f71634cf26/href</a></iframe><p>Bundle and install everything, and then install ActiveAdmin:</p><pre>bundle install<br>bin/rails g active_admin:install</pre><p>You should see something like the following:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/ad53355851535ad7703738b8faae1a7a/href">https://medium.com/media/ad53355851535ad7703738b8faae1a7a/href</a></iframe><p>Finally, migrate and seed the database:</p><pre>bin/rake db:migrate<br>bin/rake db:seed</pre><p>Once again you can fire up Rails:</p><pre>bin/rails s -p 3001</pre><p>But this time hit <a href="http://localhost:3001/admin">http://localhost:3001/admin</a>. You should see something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*64gZz8YHM0p166A5mz0gQg.png" /><figcaption>(Yours will be called List of Ingredients, but I was still working out what to build at this point. Shame on me for not taking a fresh screen grab. This is amateur hour.)</figcaption></figure><p>And you should take a moment to feel pretty great, because that was <em>a lot</em>.</p><p>You can log into ActiveAdmin with the username admin@example.com and the password password. Security! You can change it really easily in the rad ActiveAdmin environment, though, so fear not.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*ub9e3EXBhAHX2V4x8aRDwQ.png" /></figure><h3>Step 3: Adding create-react-app as the client</h3><p><em>Yay! Super-speedy Webpack asset handing!</em></p><p>(<a href="https://www.fullstackreact.com/articles/how-to-get-create-react-app-to-work-with-your-rails-api/">Shout out to Full Stack React for this bit.</a>)</p><p>So. We need a front end. If you don’t have create-react-app yet, install it globally with:</p><pre>npm install create-react-app -g</pre><p>And then, in the root of your app, generate it into the /client folder:</p><pre>npm install -g create-react-app<br>create-react-app client</pre><p>It’ll take a bit. You probably have time for a cup of tea, if you’re feeling thirsty.</p><p>Once it’s installed, jump in and fire it up:</p><pre>cd client<br>npm start</pre><p>Right! You have a simple create-react-app running. That is good. But we can do more than that.</p><p>As I mentioned earlier, one of the best bits about working with create-react-app and an API is that you can automatically proxy the API calls via the right port, without needing to swap anything between development and production. To do this, jump into your client/package.json and add a proxy property, like so:</p><pre>&quot;proxy&quot;: &quot;http://localhost:3001&quot;</pre><p>Your client/package.json file will look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/94268b9d64288b85a3a8b0aa7c2b0978/href">https://medium.com/media/94268b9d64288b85a3a8b0aa7c2b0978/href</a></iframe><p>(You might wonder why we’re proxying port 3001. Once we hook everything up our scripts will be running the API on port 3001, which is why we’ve been running Rails that way. Nice one picking up on that, though, eagle-eyes. Asking the right questions!)</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fl3vR9sjPQfJBUex9u%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fnetflix-oitnb-alex-l3vR9sjPQfJBUex9u&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fl3vR9sjPQfJBUex9u%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/bbb4a19d5a7f68a211b7c833c521f3e9/href">https://medium.com/media/bbb4a19d5a7f68a211b7c833c521f3e9/href</a></iframe><p><a href="https://github.github.io/fetch/">fetch</a> (along with a bunch of fancy new language features and polyfills <a href="https://github.com/facebookincubator/create-react-app/blob/master/packages/react-scripts/template/README.md#supported-language-features-and-polyfills">you should 100% check out</a>) is included with create-react-app, so our front end is ready to make calls to the API. But right now that would be pretty pointless—we’ll need some data to actually fetch.</p><p>So, let’s get this cocktail party started. We’ll need two relations, the Drinks, and the Ingredients that those drinks are made with. You’ll also potentially need a blender, but honestly, a margarita with a couple of ice cubes is still so delicious. Promise.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fl44QC1iWl0uoSpirm%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fstudiosoriginals-margarita-national-day-l44QC1iWl0uoSpirm&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fl44QC1iWl0uoSpirm%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="280" frameborder="0" scrolling="no"><a href="https://medium.com/media/03ec1f3e0a5ed928d356f9fc8ce2a107/href">https://medium.com/media/03ec1f3e0a5ed928d356f9fc8ce2a107/href</a></iframe><p>Now, normally I’d say avoid scaffolding in Rails, because you end up with a ton of boilerplate code that you have to delete, but for the purposes of the exercise, let’s use it. And then delete it. Do what I say, not what I do and all that.</p><p><em>Before </em>that though, I should mention something. One downside to ActiveAdmin using inherited_resources, which reduces the boilerplate for Rails controllers, is that Rails then uses it when you scaffold <em>anything</em> in your app. That breaks stuff:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eae5bc469d9fff3e1477e3209b712411/href">https://medium.com/media/eae5bc469d9fff3e1477e3209b712411/href</a></iframe><p>Fortunately, this is a solvable problem. You just need to tell Rails to use the regular scaffolding process. You know, from when we were young and scrappy and people didn’t say JavaScript fatigue like having options is a bad thing. The Good Old Days.</p><p>Just remind Rails which scaffold_controller to use in your config/application.rb and we can be on our way:</p><pre>config.app_generators.scaffold_controller = :scaffold_controller</pre><p>Your application.rb should look something like this, and everything should be right with the world again:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/de97bf3b279ff8cbd1958746baf69448/href">https://medium.com/media/de97bf3b279ff8cbd1958746baf69448/href</a></iframe><p>Crisis averted!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FzYnjyO07Nr6PS%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2FzYnjyO07Nr6PS&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FzYnjyO07Nr6PS%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="220" frameborder="0" scrolling="no"><a href="https://medium.com/media/a67a6f15567ee8bbe2aaefaf7a6ee065/href">https://medium.com/media/a67a6f15567ee8bbe2aaefaf7a6ee065/href</a></iframe><p>So, scaffolding. First, the Drink model:</p><pre>bin/rails g scaffold Drink title:string description:string steps:string source:string</pre><p>Then, the Ingredient model:</p><pre>bin/rails g scaffold Ingredient drink:references description:string</pre><p>Notice that the Ingredient references the Drink. This tells the Ingredient model to belong_to the Drink, which is part of the whole has_many relative database association thing.</p><p>See, my Relational Databases 101 comp-sci class was totally worth it.</p><p>Unfortunately this won’t tell your Drink model to has_many of the Ingredient model, so you’ll also need to add that to app/models/drink.rb all by yourself:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/72b8d3d3b20e5f41cac0828ab833d31c/href">https://medium.com/media/72b8d3d3b20e5f41cac0828ab833d31c/href</a></iframe><p>Then we can migrate and tell ActiveAdmin about our new friends:</p><pre>bin/rake db:migrate<br>bin/rails generate active_admin:resource Drink<br>bin/rails generate active_admin:resource Ingredient</pre><p>Go team.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fl0HlErtakz1N4Impq%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2FRuPaulsDragRaceAllStars-episode-1-rupauls-drag-race-all-stars-season-2-l0HlErtakz1N4Impq&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fl0HlErtakz1N4Impq%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="231" frameborder="0" scrolling="no"><a href="https://medium.com/media/051584ca5b720819c1243debf8b9f45b/href">https://medium.com/media/051584ca5b720819c1243debf8b9f45b/href</a></iframe><p>Now, Rails is a security conscious beast, so you’ll need to add some stuff to the two files ActiveAdmin will have generated, app/admin/drink.rb and app/admin/ingredient.rb. Specifically, you’ll need to permit ActiveAdmin to change your model, which when you think about it is pretty important.</p><p>First up, app/admin/drink.rb:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4e3f127a5031e5a308a241daa262214a/href">https://medium.com/media/4e3f127a5031e5a308a241daa262214a/href</a></iframe><p>Then app/admin/ingredient.rb:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/10619f3af7f00dcc33f9c0263e609652/href">https://medium.com/media/10619f3af7f00dcc33f9c0263e609652/href</a></iframe><p>Without permit_params, you can never edit your delicious drink recipes. Not on my watch.</p><p>In our routes, we’ll need to hook up the drinks resource. I like to scope my API calls to /api, so let’s do that:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3bfdb4e354a1e64517585bd30b37068b/href">https://medium.com/media/3bfdb4e354a1e64517585bd30b37068b/href</a></iframe><p>Start the server:</p><pre>bin/rails s -p 3001</pre><p>And you should be able to visit <a href="http://localhost:3001/api/drinks">http://localhost:3001/api/drinks</a> to see… *<em>drumroll*</em></p><pre>{<br>}</pre><p>Nothing. We should probably add some drinks. To save some time, here’s a db/seeds.rb that I prepared earlier, featuring a delicious negroni and a delicious margarita:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/23458a3017aa04880921d3bb44e60b70/href">https://medium.com/media/23458a3017aa04880921d3bb44e60b70/href</a></iframe><p>You’ve already migrated, so it’s just a case of seeding the database:</p><pre>bin/rake db:seed</pre><p>Now when you refresh you should see:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IqcHm6U9A9MdelJbsaXV_g.png" /><figcaption>Yay! Drinks!</figcaption></figure><p>So, we’re pretty much good to go on the database front. Let’s just massage our scaffolded controllers a little. First, let’s cut back the DrinksController. We can make sure def index only returns the id and title of each drink, and we can make sure def show includes the id and description of each ingredient of the drink. Given how little data is being sent back, you could just grab everything from index, but for the purposes of showing how this could work in the Real World, let’s do it this way.</p><p>You’ll want to make sure your controllers are inheriting from ApiController, too.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1ccc162ecdbc7e43491e90bc21e00a7f/href">https://medium.com/media/1ccc162ecdbc7e43491e90bc21e00a7f/href</a></iframe><p>And let’s just get rid of 99% of ingredients_controller.rb, because it’s not going to be doing a lot:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/143b5c1c3d3780d1b8b5b2ac3d1bcc8a/href">https://medium.com/media/143b5c1c3d3780d1b8b5b2ac3d1bcc8a/href</a></iframe><p>And now we have some fancy data to feed the client. Good for us! This is a big chunk of the setup, and you’re doing great. Let’s celebrate with some Adventure Time, and take this opportunity to think about how great that cocktail is going to be. Talk about earning it:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fw96fryVwyKlMs%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Ftired-sleepy-bed-w96fryVwyKlMs&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fw96fryVwyKlMs%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="244" frameborder="0" scrolling="no"><a href="https://medium.com/media/8b62659b0a5a64938ad8a5d25630eb3e/href">https://medium.com/media/8b62659b0a5a64938ad8a5d25630eb3e/href</a></iframe><p>Next up, let’s create a Procfile in the root of the app for running the whole Rails / create-react-app setup locally, because Heroku uses procfiles to manage your bundle. If you haven’t used them before, <a href="https://devcenter.heroku.com/articles/procfile">you can read about them here</a>.</p><p>We’ll call it Procfile.dev, because while we <em>do</em> need to run a Node server locally we’ll be deploying a pre-built bundle to Heroku, and we won’t need to run a Node server as well. Having a Node server and Rails server locally massively speeds up development time, and it is p<em>retty great</em>, but it’s overkill for production. Your Procfile.dev should look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e82f11ba12218578712c4b15270dd0c4/href">https://medium.com/media/e82f11ba12218578712c4b15270dd0c4/href</a></iframe><p>Procfiles are managed by foreman, which if you don’t have installed you can add with:</p><pre>gem install foreman</pre><p>And you can fire up the new set up with:</p><pre>foreman start -f Procfile.dev</pre><p>Who wants to type that every single time though? Why not make some rake tasks to manage running development and production locally for you? Just add start.rake to your /lib/tasks folder:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/eea109d08e2c1b2bd985b8707f619121/href">https://medium.com/media/eea109d08e2c1b2bd985b8707f619121/href</a></iframe><p>You’ll also need to add Foreman to your Gemfile (I’d recommend putting it in your :development group:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/65be55c34752c2315e47a73f914da97a/href">https://medium.com/media/65be55c34752c2315e47a73f914da97a/href</a></iframe><p>Then install it:</p><pre>bundle install</pre><p>And from there all you need to do to fire up your development environment is run the super simple:</p><pre>bin/rake start</pre><p>Glorious! Ten keystrokes to fire up two servers? What magic is this?!</p><p>And to test production (which will take a while to build without a great deal of output):</p><pre>bin/rake start:production</pre><p>Well, that step was a lot. So what’s happening here?</p><p>foreman will start the front end, /client, on port 3000 and the API on port 3001. It’ll then open the client, <a href="http://localhost:3000">http://localhost:3000</a> in your browser. You can access ActiveAdmin via the API, at <a href="http://localhost:3001/admin">http://localhost:3001/admin</a>, just like you’ve been doing all along.</p><p>Now we can sort our the React app. The simplest thing is to just check it works:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c953386a480aa29ddd1fa16611f154d3/href">https://medium.com/media/c953386a480aa29ddd1fa16611f154d3/href</a></iframe><p>In your console, you should see the API call logged:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/748/1*MhaTowTQ6K4Bu_75_5aDBg.png" /></figure><p>Which we can 100% use to grab the actual details of each fine beverage from drinks#show in Rails. Sure, we could’ve just sent everything from the server because it’s only two drinks, but I figure this is closer to how you’d really build something, so let’s go with it.</p><p>Now, rather than go through the full front end application, you can either grab the client folder from the repo:</p><p><a href="http://github.com/superhighfives/list-of-ingredients">http://github.com/superhighfives/list-of-ingredients</a></p><p>Or you can install the following dependencies:</p><pre>npm install semantic-ui-react --save<br>npm install semantic-ui-css --save</pre><p>And add them to your /client app. First, add the css to client/src/index.js:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8462ad24da44d7c10e0906bb147194b7/href">https://medium.com/media/8462ad24da44d7c10e0906bb147194b7/href</a></iframe><p>And the all the fancy bells and whistles to your client/src/app.js:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/29ccb16835a5ddff50a67aef687d8190/href">https://medium.com/media/29ccb16835a5ddff50a67aef687d8190/href</a></iframe><p>Either way you choose to do it, you’re golden!</p><p>You should have a fancy front end that uses <a href="http://react.semantic-ui.com/">Semantic UI</a> and looks something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pKE6ejDwBt7ATR9T4MIDiw.png" /><figcaption>So close! So, so close!</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*2wKcAN6GaglCQOgHKMzFHw.png" /></figure><h3>Step 4: Get everything ready for production</h3><p><em>With Rails serving the Webpack bundle</em></p><p>So, how do we get our Rails app serving the Webpack bundle in production?</p><p>That’s where the magic of NPM’s package.json‘s postinstall comes in. We can get Heroku to build the app on the server, and copy the files into the /public directory to be served by Rails. We end up running a single Rails server managing our front end and back. It’s win win! There are a couple of steps to make that happen.</p><p>First up, let’s make a package.json file in the root of the app, which tells Heroku to compile the create-react-app. The postinstall command will get run after the node build is (you guessed it) installed. First up it’ll build it, then it’ll move the files into /public. How easy is that?</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4c594f76ac01cced39e83af34e7cd682/href">https://medium.com/media/4c594f76ac01cced39e83af34e7cd682/href</a></iframe><p>As always, you are doing great. Also, honestly, my hands are getting sore. On the plus side, this step is super short! Go team!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FxT1XGHkP7hqm0JvWrS%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fbobs-burgers-bobs-burgers-linda-belcher-xT1XGHkP7hqm0JvWrS&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FxT1XGHkP7hqm0JvWrS%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="448" frameborder="0" scrolling="no"><a href="https://medium.com/media/c8ec5e6f5b6c4ff91f8220cdf4e6d47f/href">https://medium.com/media/c8ec5e6f5b6c4ff91f8220cdf4e6d47f/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*9DCwwXvVkd6qRrSzm0Fd9g.png" /></figure><h3>Step 5: Deploy it to Heroku</h3><p><em>And celebrate, because you’ve earned it</em></p><p>We are super close! Soon, everything the light touches will be yours, including a fresh, tasty beverage. So let’s create a new Heroku app and get this thing over the finish line:</p><pre>heroku apps:create</pre><p>Now, if you push to Heroku, this looks like a dual Rails / Node app. But your Node code needs to be executed first so it can be served by Rails. This is where <a href="https://devcenter.heroku.com/articles/buildpacks">Heroku’s buildpacks</a> come in — they transform your deployed code to run on Heroku. We can tell Heroku, via the terminal, to use two buildpacks (or build processes) in a specific order. First nodejs, to manage the front end build, and then ruby, to run Rails:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/990360bd21f324b6b477d186240d4ded/href">https://medium.com/media/990360bd21f324b6b477d186240d4ded/href</a></iframe><p>Let’s make a Procfile, in the root, for production, which will tell Heroku to run the Rails app:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/18c696b75893fe1758ed94d71638a97c/href">https://medium.com/media/18c696b75893fe1758ed94d71638a97c/href</a></iframe><p>Before we deploy it’s worth noting that create-react-app defines react-scripts, which manages the build of the client (along with a bunch of other stuff), as a devDependency in your package.json. Heroku sets an ENV var, NPM_CONFIG_PRODUCTION, to true, which means your build will disregard any devDependencies and it will fail. Not ideal.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F14gMU9YMLLn2ne%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Flaura-palmer-14gMU9YMLLn2ne&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F14gMU9YMLLn2ne%2F200.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="245" frameborder="0" scrolling="no"><a href="https://medium.com/media/dca316adc682b6a34de368ac9b55282e/href">https://medium.com/media/dca316adc682b6a34de368ac9b55282e/href</a></iframe><p>But not unfixable! To overcome this you have two options. You can either set NPM_CONFIG_PRODUCTION to false:</p><pre>heroku config:set NPM_CONFIG_PRODUCTION=false</pre><p>Or you’ll need to move the react-scripts in your /client/package.json out of devDependencies into dependencies:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6802ee3b0004808f53a4f58c9039ebf7/href">https://medium.com/media/6802ee3b0004808f53a4f58c9039ebf7/href</a></iframe><p>Both options will work, but given that you’ll likely have more than one devDependency, it’s easier to tell Heroku to recognise them. Normally I’d say you should always tune your production environment for, well, production, but in this case we’re building the assets with Node, not serving them.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F111ebonMs90YLu%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fthumbs-up-111ebonMs90YLu&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F111ebonMs90YLu%2F200.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="326" frameborder="0" scrolling="no"><a href="https://medium.com/media/eae68c2d9cc01cb75af79d628b26acbb/href">https://medium.com/media/eae68c2d9cc01cb75af79d628b26acbb/href</a></iframe><p>With that sorted, we can deploy this beautiful beverage-based beast:</p><pre>git add .<br>git commit -vam &quot;Initial commit&quot;<br>git push heroku master</pre><p>Heroku will, following the order of the buildpacks, build the client, and then fire up Rails.</p><p>You’ll need to migrate and seed your database on Heroku, or ActiveAdmin will not be thrilled (and you won’t be able to log in). That’s easy enough though:</p><pre>heroku run rake db:migrate<br>heroku run rake db:seed</pre><p>And there you have it:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*TuvvWzTUMYkZoUXAl-BlDQ.png" /><figcaption><a href="https://list-of-ingredients.herokuapp.com/">https://list-of-ingredients.herokuapp.com/</a></figcaption></figure><p>When you visit your app you’ll see the create-react-app on the client side, displaying some delicious drink recipes. You’ll also be able hit /admin (for example, <a href="https://list-of-ingredients.herokuapp.com/admin">https://list-of-ingredients.herokuapp.com/admin</a>) and access your database using that truly terrible username and password ActiveAdmin chose for you. I’d recommend changing those on production ASAP. I did, so you can’t just change all my demo recipes to be really rude. I’m gutted you’d even try to, honestly, after everything we’ve been through.</p><p>It’s worth noting, if you’re planning to use react-router from here, there’s a <a href="https://medium.com/@superhighfives/hey-logan-d73126d71271">few more steps you’ll need to take</a>. <a href="https://medium.com/u/5ff39a2d3038">Logan</a> asked about it, so thanks Logan!</p><p>This isn’t exactly the most thrilling demo (especially given it suggests putting prosecco in a negroni, which is a capital crime in some parts of the world) but hopefully it gets you up and running. All the ingredients to make a delicious Rails API / Activeadmin / create-react-app beverage are here, and the sky’s the limit.</p><p>You can see a ready-to-go repo here, too: <br><a href="http://github.com/superhighfives/list-of-ingredients">http://github.com/superhighfives/list-of-ingredients</a></p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FvmmqeD1Mxdy0g%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Falcohol-champagne-cheers-vmmqeD1Mxdy0g&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FvmmqeD1Mxdy0g%2F200.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="228" frameborder="0" scrolling="no"><a href="https://medium.com/media/c937de77d0b421871ff5231e4d449c4e/href">https://medium.com/media/c937de77d0b421871ff5231e4d449c4e/href</a></iframe><p>Thanks for taking the time to have a look, and I genuinely hope you celebrated with a drink, alcoholic or otherwise. 🍹</p><p>Shout out to <a href="https://rrott.com/blog/ror/rails-5-api-with-activeadmin-integration.html">Roman Rott</a> and <a href="https://www.fullstackreact.com/articles/how-to-get-create-react-app-to-work-with-your-rails-api/">Full Stack React</a> for the inspiration to put this together. And a massive thank you to <a href="http://twitter.com/glenmaddern">Glen</a> and <a href="https://twitter.com/quitexander">Xander</a> for taking the time to make suggestions and proofread this small essay for me. 💖</p><p>If you have any questions leave a comment <a href="https://twitter.com/superhighfives">or say hi via Twitter</a>. Alternatively, enjoy a GIF of a dog wearing a hat.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FH3ElMwEfyhJU4%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fcute-dog-hat-H3ElMwEfyhJU4&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FH3ElMwEfyhJU4%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="326" frameborder="0" scrolling="no"><a href="https://medium.com/media/d7fb5113ba0d211dc134cb1f83af0a4b/href">https://medium.com/media/d7fb5113ba0d211dc134cb1f83af0a4b/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=de5481b7ec0b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/a-top-shelf-web-stack-rails-5-api-activeadmin-create-react-app-de5481b7ec0b">A Top Shelf Web Stack—Rails 5 API + ActiveAdmin + Create React App</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Announcing ⛱ Sandpit]]></title>
            <link>https://medium.com/superhighfives/announcing-sandpit-a5da86fd49ed?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/a5da86fd49ed</guid>
            <category><![CDATA[creative-coding]]></category>
            <category><![CDATA[canvas]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[sandpit]]></category>
            <category><![CDATA[javascript]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Tue, 21 Feb 2017 12:22:03 GMT</pubDate>
            <atom:updated>2017-02-21T12:58:30.768Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kAv9oP-3ohT1k_RaG2gzNA.png" /><figcaption><a href="https://sandpitjs.com">https://sandpitjs.com</a></figcaption></figure><p><em>A playground for creative coding using JavaScript and the canvas element.</em></p><p>I’ve long been fascinated with <a href="https://www.wikiwand.com/en/The_Two_Cultures">blurring the line between art and technology,</a> and there are few places where exploring it is more easily achievable, or enjoyable, than the web. Browsers have come a long way since the heady days of IE6, and building <a href="http://inconvergent.net/generative/">complex visualisations</a> and / or <a href="http://pickle.cat/">GPU-powered looping cat gifs</a> is just a few tutorials away.</p><p>My <a href="https://charliegleason.com/projects">experiments</a>, over time, have relied more and more on the &lt;canvas&gt; tag. The wealth of incredible tools and resources available to manipulate this seemingly innocuous DOM element seem limitless, and I built <a href="https://github.com/sandpit/sandpit"><strong>Sandpit</strong></a> as a love letter to them.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FxTiN0Oto1N0SiENwCk%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fcreative-coding-canvas-xTiN0Oto1N0SiENwCk&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FxTiN0Oto1N0SiENwCk%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="217" frameborder="0" scrolling="no"><a href="https://medium.com/media/0cd6923afd2f5c366861977ece8f2853/href">https://medium.com/media/0cd6923afd2f5c366861977ece8f2853/href</a></iframe><h3>🤓 So, what is it?</h3><p>At its heart, <a href="https://sandpitjs.com/"><strong>Sandpit</strong></a> is a library that helps simplify creative coding. It does what it can to help, and gets out of the way when it can’t. Because you always have access to the &lt;canvas&gt; object, and to its context, you only have to use <a href="https://sandpitjs.com/"><strong>Sandpit</strong></a> when it benefits you. It looks like this:</p><pre>const sandpit = new Sandpit(&#39;body&#39;, Sandpit.CANVAS)</pre><p>The key features of <a href="https://sandpitjs.com/"><strong>Sandpit</strong></a>:</p><ul><li>Custom settings are easy to automagically configure, and then manipulate, with <a href="http://workshop.chromeexperiments.com/examples/gui">dat.GUI</a>. For example, the following will give you a colour picker with red as a default:</li></ul><pre>sandpit.settings = {strokeColor: {value: &#39;red&#39;, color: true}}<br>console.log(sandpit.settings.strokeColor) // &#39;red&#39;</pre><ul><li>The current state is stored in the query string, making it simple to copy and paste your exact configuration to anyone who’s got the same settings as you—like in a staging environment, or locally. Tweak it, then paste it in Slack (👍, says your friend / client / co-worker).</li><li>The animation loop is ready to go via sandpit.loop(), without needing you to write a single requestAnimationFrame.</li><li>Inputs are normalised, from mouse to touch to gyroscope data, and there are event hooks, like sandpit.move(), to access them.</li><li>Support for 2D or 3D canvases — it plays nice with libraries like <a href="https://threejs.org/">Three.js</a>, too, in case you just want simple access to touch inputs or the animation loop.</li><li>Canvas resizing is automatically handled, with a preference towards setting and respecting the size in CSS (and a hook to override that).</li><li>A bunch of related tools and libraries that are simple to access, including maths helpers, <a href="https://github.com/Qix-/color">Color</a>, and <a href="http://victorjs.org/">Victor</a>.</li><li>A growing suite of demos and documentation, and support for ES6, ES5, and the &lt;script&gt; tag.</li></ul><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2Fl3q2LrylMrPbXdk6k%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fcreative-coding-canvas-l3q2LrylMrPbXdk6k&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2Fl3q2LrylMrPbXdk6k%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="217" frameborder="0" scrolling="no"><a href="https://medium.com/media/3706bbfc9ed3379545315777488c6a0d/href">https://medium.com/media/3706bbfc9ed3379545315777488c6a0d/href</a></iframe><h3>👏 Why use it?</h3><p>Good question. There are a number of tools that exist already that you should absolutely check out, but <a href="https://sandpitjs.com"><strong>Sandpit</strong></a> offers a bunch of unique features, easy to use demos, examples and documentation at <a href="https://sandpitjs.com">https://sandpitjs.com</a>. That said, I’ve made a list of <a href="https://sandpitjs.com/docs/tutorial-02-inspiration.html">tools worth considering</a>, because due diligence is a Very Good Thing.</p><p>I’d love you to try <a href="https://sandpitjs.com/"><strong>Sandpit</strong></a><strong> </strong>(you can start <a href="https://github.com/sandpit/sandpit-site">playing with the demos here</a>), suggest features by <a href="https://github.com/sandpit/sandpit/issues">opening an issue</a>, and generally let me know what you think. And if you wanna skip the setup and get straight to building stuff, <a href="https://codepen.io/superhighfives/pen/BpoPeJ">fork this Codepen</a> and check out the <a href="https://sandpitjs.com/docs/tutorial-01-documentation.html">documentation</a>.</p><p>Oh, and 100% comment with your experiments so I can tell you how great they are, you superhero. ✨</p><pre>sandpit.start()</pre><p><strong>⛱ Sandpit:</strong> <a href="https://sandpitjs.com">https://sandpitjs.com</a><br><strong>⚡ Github:</strong> <a href="https://github.com/sandpit/sandpit">https://github.com/sandpit/sandpit</a><br><strong>😍 Examples:</strong> <a href="https://github.com/sandpit/sandpit-site">https://github.com/sandpit/sandpit-site</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a5da86fd49ed" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/announcing-sandpit-a5da86fd49ed">Announcing ⛱ Sandpit</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[An Almost Static Stack]]></title>
            <link>https://medium.com/superhighfives/an-almost-static-stack-6df0a2791319?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/6df0a2791319</guid>
            <category><![CDATA[create-react-app]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react-router]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[react]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Fri, 03 Feb 2017 12:59:05 GMT</pubDate>
            <atom:updated>2019-06-21T09:14:01.464Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Le7RdBhB9yZbpyo_fsUw_A.png" /></figure><p>Or how <em>create-react-app</em>, with a couple of modern tools, can make building static sites (with benefits) a breeze.</p><p><strong>Update, 11 December 2017:</strong> The response to this setup has been super cool. My sincere thanks to those who have helped people get set up in the responses, and to those who have reached out with advice and high fives.</p><p>I have updated the dependencies <a href="https://github.com/superhighfives/an-almost-static-stack">in the repo</a> to the latest versions, along with the guide, and tested that everything is still working as expected. Some of the output in your terminal might look slightly different than the screengrabs, but do not fear—you’re all good! Also, <a href="https://github.com/stereobooster">stereobooster</a> has put together an <a href="https://github.com/stereobooster/react-snap/blob/master/doc/an-almost-static-stack-optimization.md">amazing overview of possible performance optimisations</a> for the final product which is well worth a read.</p><p>And again, thanks for reading.</p><h3>Charlie Gleason on Twitter</h3><p>Speaking of, react-helmet + react-snapshot + react-router = instant joy. Note to self: write blog post / love letter.</p><p>I’m a big fan of <a href="https://github.com/facebookincubator/create-react-app">create-react-app</a>. It hugely simplifies starting a new React-based project, and it serves pretty well for any ES6 / ES2015 setup regardless of whether you use React. I originally built <a href="https://sandpitjs.com">Sandpit</a> with it, purely because I could get straight to coding, writing tests, and deploying to a static site host like <a href="https://surge.sh">Surge</a> or <a href="https://zeit.co/now">Now</a>.</p><p>create-react-app’s best feature is its simplicity, but that that simplicity comes at a cost. As your application grows in complexity, you either have to yarn eject and take the entire set up into your own hands, or live with the limitations.</p><p>But hey, neither of those options are necessarily bad. But if you’d rather stick within create-react-app, there are a few tools you can use to take advantage of the incredible ease of use and speed of development that comes with create-react-app, without any terrifyingly massive webpack.config.js files keeping you up at night.</p><h4>So, what are they?</h4><p>There are five ingredients to this delicious paella of web development joy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2VkObOLVl99DwBfdfwdsAA.png" /></figure><p><a href="https://github.com/facebookincubator/create-react-app"><strong>create-react-app</strong></a><strong><br></strong>Kind of goes without saying, really.</p><p><a href="https://reacttraining.com/react-router/"><strong>react-router</strong></a><br>Declarative routing for React, with a fancy new v4 that resolves a lot of the confusion around using the library.</p><p><a href="https://github.com/nfl/react-helmet"><strong>react-helmet</strong></a><br>Manages the document head, including title, description and meta tags.</p><p><a href="https://www.npmjs.com/package/react-snapshot"><strong>react-snapshot</strong></a><br>A zero-configuration pre-renderer for React apps.</p><p><a href="https://github.com/styled-components/styled-components"><strong>styled-components</strong></a><strong><br></strong>All the cool kids are into it, and it allows you use SCSS-like code in create-react-app (which, out of the box, supports vanilla CSS)—styling for the component age.</p><h4>Okay, so, why?</h4><p>One of the challenges of deploying an app built with create-react-app is that it is rendered entirely client side. Although Google can render JavaScript content when crawling a site, it doesn’t always, and there is always the risk that your JavaScript bundle will fail anyway. It’s incredibly worthwhile to send your HTML with the initial packet, which is where everything above comes into play.</p><p>When you build your site, react-snapshot fires up a server, visits each relative link, and saves a copy of the rendered page in the build folder. When you deploy it to <a href="http://surge.sh/">Surge</a> the app is “hydrated” with the JavaScript hooks, and you can spend the remainder of your afternoon sipping a crisp white wine spritzer (or apple juice and soda, depending on your personal preference).</p><p>So, let’s go.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xEEhF9aM8uPak38dn0ZRAw.png" /><figcaption>The create-react-app installation process, now with added emojis!</figcaption></figure><h4>Setting it up</h4><p>First off, get create-react-app running.</p><pre>npm install -g create-react-app</pre><p>Then you can make a new app, which will take a while, so maybe make yourself a coffee? It’ll take the edge off that daytime wine you had.</p><pre>create-react-app app-name</pre><p>When the installation completes, jump into the directory and install some fancy dependencies.</p><pre>cd app-name &amp;&amp; yarn add react-router-dom react-helmet react-snapshot styled-components</pre><blockquote>Also, you 100% do not need to use yarn if you don’t want to. npm is also great, but yarn is super fast, and let’s face it we’re all still reeling from that whole create-react-app installation waiting game. Plus it has emojis!</blockquote><p>react-snapshot requires a couple of quick changes to the default create-react-app setup.</p><p>First off, change your package.json build option.</p><pre>&quot;build&quot;: &quot;react-scripts build &amp;&amp; react-snapshot&quot;</pre><p>And then patch up the default src/index.js.</p><pre>import React from &#39;react&#39;;<br>import { render } from &#39;react-snapshot&#39;;<br>import App from &#39;./App&#39;;<br>import &#39;./index.css&#39;;</pre><pre>render(<br>  &lt;App /&gt;,<br>  document.getElementById(&#39;root&#39;)<br>);</pre><p>And voila. If you run yarn build, you’ll see some sweet snapshot magic.</p><pre>$ react-scripts build &amp;&amp; react-snapshot<br>Creating an optimized production build...<br>Compiled successfully.</pre><pre>🕷   Starting crawling <a href="http://localhost:2999">http://localhost:2999</a><br>✏️   Saving / as /index.html<br>🕸   Finished crawling.<br><br>✨   Done in 11.06s.</pre><p>As you can see, react-snapshot is taking the app and outputting a static index.html.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8a6870ac605762b36316e744ac375715/href">https://medium.com/media/8a6870ac605762b36316e744ac375715/href</a></iframe><p>It might not look like much, but it’s <em>so great</em>.</p><p>Still, it doesn’t do much about the key areas that a search engine is looking at—the title and metadata in the head. That’s where react-helmet comes in. It is a component that helps you manage the document head, meaning while someone navigates your app, your metadata stays in sync.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e2efb2194d0754d56ef25bd9411c09cd/href">https://medium.com/media/e2efb2194d0754d56ef25bd9411c09cd/href</a></iframe><p>Here we’re populating the title with “You Are Doing Great”, which is true, using the Helmet component. It displays in your browser tab, and all is well with the world.</p><p>Unfortunately, when viewing the source, the &lt;title&gt; is still React App.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/860/1*Jh0MSy0Lz1An2xO4Rl5PfA.png" /><figcaption>ლ(ಠ益ಠლ)</figcaption></figure><p>That’s where react-snapshot comes in. By using react-snapshot in conjunction with react-helmet, you can pre-populate both the head of each route, and the body, on server and client side. It is literally win-win. So let’s build it.</p><pre>yarn build</pre><pre>🕷   Starting crawling <a href="http://localhost:2999">http://localhost:2999</a><br>✏️   Saving / as /index.html<br>🕸   Finished crawling.</pre><p>And when we look at the generated index.html?</p><pre>&lt;title&gt;You Are Doing Great&lt;/title&gt;</pre><p>Omg, see? Even the server gets it.</p><p>For routes that aren’t snapshotted (I don’t think that’s a word, honestly), react-snapshot provides a fallback, 200.html, which behaves exactly like the non-snapshotted (still not a word) index.html. Hosts like <a href="https://surge.sh">Surge</a> serve it automatically if no other snapshot is found, meaning react-router can grab the URL and route it appropriately. It’s auto<em>magical</em>.</p><p>I’ve pulled together a repo that shows all this in action, called <strong>You Are Doing Great</strong>, or <strong>YADG</strong>. <a href="http://yadg.surge.sh/">You can see the live version in action here.</a></p><p>The repo is on Github, too:<br><a href="https://github.com/superhighfives/an-almost-static-stack">https://github.com/superhighfives/an-almost-static-stack</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-w282VnRQdg7mO6ds0Psng.png" /><figcaption><a href="http://yadg.surge.sh/">http://yadg.surge.sh/</a></figcaption></figure><p>It’s set up with all the features I’ve mentioned, including routing, snapshotting, metadata management, <a href="https://medium.com/superhighfives/hot-reloading-create-react-app-73297a00dcad">almost hot-reloading</a>, and using styled-components.</p><p>Also, if you’re looking for an example in the wild, <a href="https://charliegleason.com">I built my site on, essentially, the same stack</a>.</p><p>If you have any questions leave a comment <a href="https://twitter.com/superhighfives">or say hi via Twitter</a>. Alternatively, enjoy a GIF of an owl being petted.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2FWaEDmi1vk4vFm%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fcute-adorable-owl-WaEDmi1vk4vFm&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2FWaEDmi1vk4vFm%2Fgiphy.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="229" frameborder="0" scrolling="no"><a href="https://medium.com/media/fed35305f8739397cbd8661d95be0b51/href">https://medium.com/media/fed35305f8739397cbd8661d95be0b51/href</a></iframe><p>Owls are <em>so</em> great.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6df0a2791319" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/an-almost-static-stack-6df0a2791319">An Almost Static Stack</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Making An Interactive Music Video With WebGL]]></title>
            <link>https://medium.com/superhighfives/making-a-music-video-f60757ceb4cf?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/f60757ceb4cf</guid>
            <category><![CDATA[webgl]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[music]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Thu, 02 Feb 2017 10:25:55 GMT</pubDate>
            <atom:updated>2023-02-09T12:59:42.552Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DCwru2rZOowAJ1bbzehmiw.jpeg" /></figure><p><em>Or how to make After Effects in your browser</em></p><p><strong>Update: </strong>You can view the full source code for the project, including instructions for setting it up locally, <a href="https://github.com/superhighfives/iwnlyg">over at Github</a>.</p><p>A couple of years ago, my band <a href="https://wearebrightly.com">Brightly</a> wrote a record called <a href="http://music.wearebrightly.com/album/beginnings-endings"><em>Beginnings &amp; Endings</em></a>. <a href="http://glenmaddern.com/">Glen Maddern</a> and I, along with a few of our friends, built an interactive tweet-powered music video for the single Preflight Nerves, which we affectionately called <a href="http://tweetflight.wearebrightly.com">Tweetflight</a>.</p><p>It took searched out tweets that matched the lyrics of the song in real-time, and animated them against a backdrop of public domain and found footage.</p><p>It did pretty great, and we were pretty chuffed.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*NjA2iItrSnDrsEHhluKsUw.jpeg" /><figcaption>Tweetflight, a real-time Twitter-powered music video</figcaption></figure><p>Since then, I’ve been a bit obsessed with the concept of interactive music videos — inspired in part by projects like Arcade Fire’s <a href="http://www.thewildernessdowntown.com">The Wilderness Downtown</a> and Rome’s <a href="http://www.ro.me">3 Dreams Of Black</a> — and I’ve since put out a couple of smaller scale clips, like <a href="http://true.wearebrightly.com">True</a>.</p><p>When I moved to the UK and started to work on an EP, I had a vague idea for the design, and I wanted to step away from the muted colours that have accompanied our previous releases. I knew I wanted to put out something bold and bright to accompany the first single, <a href="https://iwillneverletyougo.wearebrightly.com/"><em>I Will Never Let You Go</em></a>, about the lengths we go to in order to save a failing relationship, a sinking ship.</p><p>I’d collected a series of watercolours, and I liked the idea of animating them into frame using a simple ink blot mask. I pulled together a quick example in After Effects, felt pretty great about myself, and then realised I had absolutely no idea what to do with it.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fzippy.gfycat.com%2FUnderstatedAdvancedFurseal.mp4&amp;src_secure=1&amp;url=http%3A%2F%2Fgfycat.com%2FUnderstatedAdvancedFurseal&amp;image=https%3A%2F%2Fthumbs.gfycat.com%2FUnderstatedAdvancedFurseal-thumb100.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=video%2Fmp4&amp;schema=gfycat" width="640" height="360" frameborder="0" scrolling="no"><a href="https://medium.com/media/df197d35310d78c430f0d1a6be0335e8/href">https://medium.com/media/df197d35310d78c430f0d1a6be0335e8/href</a></iframe><p>I told Glen about it while were in a car, pre-dawn, driving to Golden Plains; a musical festival in Australia. I wanted to communicate the feeling of a rapidly declining relationship, that final break up over coffee, and the emotionally manipulative tug of war that accompanies it. The masks we wear and the way they deteriorate. He mentioned he’d been looking at <a href="https://www.khronos.org/webgl/wiki/Getting_Started">WebGL</a>, I mentioned the ink blot, and we started planning.</p><p>The initial concept was to build a realtime mask over any number of videos, so they could be interchanged without needing pre-rendering. We weren’t sure if it was technically possible, so we initially started playing with short square videos, overlaid on one another.</p><p>The more we talked it through, the more concerned we were about trying to synchronise multiple streams, so we decided to stitch them together into one giant one. We wrote a simple WebGL shader to display one area of the video at a time, and to do the After-Effects-style blending. It turns out, apart from a couple of sizing limits you should keep in mind (which is ultimately dependant on the graphics card), that approach works really well — and doesn’t need a particularly powerful GPU to run.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/400/1*g-21d6hicrcaGaJyq-W4zA.jpeg" /><figcaption>Exploring the frustration of singing in reverse by making a series of facial expressions that make me look like an idiot.</figcaption></figure><p>At the same time, I was experimenting with the video itself, creating short clips of myself singing the lyrics emphatically at the camera, trying to get across the core concept behind the track. It was awkward when Glen’s mate, who was staying with him at the time, walked into the apartment as I was midway through tearing at my hair, aggressively mouthing lyrics like some kind of confused wildebeest trying to eat its own reflection.</p><p>Initially I’d planned to mime the song backwards, in much the same vein as those bastions of culture and style, Coldplay, in their video for <a href="https://www.youtube.com/watch?v=RB-RcX5DS5A">The Scientist</a>. However, I learnt something deeply valuable while spending four hours in front of the camera. It is <em>really, really</em> hard to mime something backwards. Do not do it. Save yourself. Save. Yourself. Do not say I didn’t warn you.</p><p>So it was back to the drawing board. Inspired by the debauchery of <a href="https://www.youtube.com/watch?v=DTkoKiyfmps">Spender’s Never Again</a>, I covered myself in make up, and over the course of the song proceeded to super-duper ruin it. I have a newfound respect for any and all who wear make up more than once in a blue moon, because mascara is <em>hellish</em> to take off.</p><p>At the same time I continued refining the user interface, eyes stinging, while playing with <a href="http://www.html5rocks.com/en/tutorials/webgl/shaders/">shaders</a> via <a href="http://threejs.org/">Three.js</a>. Without exaggeration, shaders offer a phenomenal level of control over the output of WebGL. They run entirely on your GPU, which means you get a pretty ridiculous amount of grunt out of a browser. And that is not a sentence I ever thought I’d type back when I was trying to get pages to render properly in IE6.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/860/1*lYybwU8_IGY94ysePVAOAA.png" /><figcaption>Writing GLSL shaders is pretty metal. Well, as metal as writing code into a text editor can possibly be.</figcaption></figure><p>When you fire up <a href="https://iwillneverletyougo.wearebrightly.com/"><em>I Will Never Let You Go</em></a>, a bunch of things happen. The browser requests the video; which includes two separate streams and the ink blog mask, and optionally, access to the webcam. These get passed into a scene, along with an image; which creates the texture and colour, and two integers, which define which video frame is being displayed, and whether or not the webcam is currently visible. It’s a relatively chunky amount of information to flick through, but WebGL seems to handle it pretty gracefully.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3oCmqeYoZYkRLSDhGcXYYw.jpeg" /><figcaption>Looking serious while my shadow also looks pretty serious. Serious shadow is serious.</figcaption></figure><p>The webcam video gets treated slightly differently by the shader. It is turned to greyscale to try and achieve a similar visual aesthetic to the pre-recorded video, which is in turn masked in real-time using the ink blot.</p><p>I used <a href="https://facebook.github.io/react/">React</a> for the interface, which manages the views and UI while passing states to the Three.js scene, which, as a component, is agnostic. It’s a pretty comfortable arrangement, especially when using <a href="https://facebook.github.io/flux/">Flux</a> to dispatch events between each separate element. I managed the browser assets with <a href="http://jspm.io/">jspm</a>, and the build with <a href="http://gulpjs.com/">Gulp</a>, both of which I absolutely recommend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*iSw1yRhjId3QhDlVUc5q4A.png" /><figcaption>The 3840 x 720 pixel video, which essentially powers the whole beast.</figcaption></figure><p>I focused on creating a sense of rhythm by timing the switching of the streams to the beats of the song — first in time with the pulses, then with the drum pattern. Alternating this against the webcam footage finally felt like everything coming together — like being there, in that moment, witnessing that scene.</p><p>But what’s the point? Me, in a different order? That’s not interactive. It’s a technical demo, at best. I sent it to a few friends to check out, and Will emailed me back.</p><blockquote>“Oh wow that’s so confronting!!! :o</blockquote><blockquote>Is this something that could mash together all the people using the app at once into a mega-everyone thing? or just me and you (baby)?</blockquote><blockquote>You’re so obnoxiously talented.”</blockquote><p>(I 100% didn’t need to leave the last line in, but Will is one of my absolute heroes, and I was so chuffed. Also, I apparently have zero shame. Go figure.)</p><p>But he had a point.</p><p>I’d considered the idea of doing something more communal, like sharing video been people watching, but with the app designed, built, deployed and CDN’d, I’d kind of had enough. I’d wrote the EP at Christmas, the first single still wasn’t out, and it was nearly September.</p><p>But the joy of refactoring is that it gives you a new enthusiasm for any project. The process of pulling together each thread to get the video live meant I suddenly had a finished thing. And a finished thing is a lot more fun to mess with.</p><p>I brought it up with Glen, and he mentioned he’d used <a href="https://imgur.com">Imgur</a> for his typographic React-based project <a href="http://typeslab.com/">Typeslab</a> (which is awesome). He linked me to some of the open-sourced code, and I started patching it together on a new branch.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*_mi1hpJfxJbGe1KkAKikjQ.png" /><figcaption>The first test, my hand covering the camera because my hair was terrible.</figcaption></figure><p>I set it to surreptitiously capture an image from the webcam while the viewer watched, and added the option for them to approve it to be uploaded at the end of the video. After wrestling with the <a href="https://api.imgur.com/">Imgur API</a> for a little while, I had a functional prototype, and I marvelled at how awkward I can manage to look from any angle via a webcam.</p><p>And Glen made a really good point — people don’t move a lot while they watch a video. By capturing three images in tandem and stitching them together in canvas, I could recreate the idea of a moving image without the hassle of WebRTC or live streaming video or rebuilding Chatroulette from scratch.</p><p>So I did, and waited with baited breath for the result.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tkC4-ShqnGr9v8x-yibq8w.jpeg" /></figure><p>Upon reflection, it was not the best photo.<br>(And it was late. And I was in bed. And I don’t wear those glasses outside.)</p><p>Using the Imgur API I was able to store and display the images as they were captured. I rewrote the shaders in WebGL to manage the new element, marvelled at how effortless JavaScript feels in ES2015, and momentarily pondered how many dick pics I’d have to moderate if 4Chan got involved.</p><p>And in a homage to my love of Mario Kart and Patrick Swayze, I called them ghosts, because I guess they are. Little fragments of the people watching, flickering over and over again, like background noise.</p><p>It was a trial and error experience, each iteration building on the last to make something, hopefully, greater than the sum of the parts. It is a testament to the power of the web that these kind of experiences, once the bastard child of the Flash plugin, can be recreated natively with nothing more than JavaScript and a sense of adventure.</p><p>With the exception of iOS and its truly terrible WebGL video support.</p><p>I encourage you to try out <a href="http://threejs.org/">Three.js</a>, and to continue exploring the possibilities of the web. Oh, and to <a href="https://iwillneverletyougo.wearebrightly.com/">watch the video</a>.</p><p>Obviously.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fzippy.gfycat.com%2FEmbarrassedEvergreenCrossbill.mp4&amp;src_secure=1&amp;url=http%3A%2F%2Fgfycat.com%2FEmbarrassedEvergreenCrossbill&amp;image=https%3A%2F%2Fthumbs.gfycat.com%2FEmbarrassedEvergreenCrossbill-poster.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=video%2Fmp4&amp;schema=gfycat" width="836" height="464" frameborder="0" scrolling="no"><a href="https://medium.com/media/09ac453eb5a1d8b265ddb57eafa67b3e/href">https://medium.com/media/09ac453eb5a1d8b265ddb57eafa67b3e/href</a></iframe><h4><a href="https://iwillneverletyougo.com/">Watch the video</a></h4><p>Thank you a million times over to <a href="http://glenmaddern.com/">Glen Maddern</a> for all his help, and for being a pretty constant source of self doubt when I place myself next to his absurd genius. Thanks to <a href="http://eremin.com/">Andrei Eremin</a> for mixing, mastering and being a superhero. Thanks to <a href="http://samaraclifford.com/">Samara Clifford</a> for taking photos that cover up how awkward I really am. And thank you for taking the time to check it out.</p><p><strong>Brightly </strong><em>I Will Never Let You Go</em><br>Watch it <a href="https://iwillneverletyougo.wearebrightly.com/">here</a>.<br>Buy it <a href="http://music.wearebrightly.com/">here</a>.<br>Find out more about Brightly <a href="https://wearebrightly.com">here</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Da3iR8e3EN-P4cbfK80rMw.jpeg" /><figcaption>The artwork for the single, which you can buy on Bandcamp.</figcaption></figure><p>If you want to get in touch, you 100% should, by <a href="mailto:charlie@wearebrightly.com">email</a> or <a href="http://twitter.com/wearebrightly/">tweet</a>.<br>Thanks for listening.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f60757ceb4cf" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/making-a-music-video-f60757ceb4cf">Making An Interactive Music Video With WebGL</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Hot Reloading + create-react-app]]></title>
            <link>https://medium.com/superhighfives/hot-reloading-create-react-app-73297a00dcad?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/73297a00dcad</guid>
            <category><![CDATA[hot-reloading]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[create-react-app]]></category>
            <category><![CDATA[webpack]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Wed, 01 Feb 2017 17:25:17 GMT</pubDate>
            <atom:updated>2017-02-01T18:23:26.676Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*EReAlJwh7-dVm_yhOhC2oQ.png" /></figure><p><em>Without</em> pressing that big shiny red eject button</p><p>One of the caveats to using <a href="https://github.com/facebookincubator/create-react-app">create-react-app</a> is that you don’t get <em>true</em> hot reloading via Webpack. The page will reload if you make edits, not the application itself. This is usually fine for when you’re starting out, but once you want to get down to the nitty gritty it can be a pain.</p><p>Do not despair. You can get <em>almost</em> <em>true</em> hot reloading without having to yarn eject, by hooking into Webpack’s module.hot in your index.js.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f951a6d284f99f246546eb22ceabfc35/href">https://medium.com/media/f951a6d284f99f246546eb22ceabfc35/href</a></iframe><p>By replacing the contents of your app with each edit, you no longer need to wait on a page refresh. What a time to be alive!</p><p>If you’re looking to avoid hot reloading on certain elements (for example, Three.js doesn’t love WebGLRenderer being fired up too many times) you can initialise them in your index.js, and then pass them as a prop to your application. Do I have an example? Why yes, I do. Here’s one I prepared earlier.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4c239d24b349269748eaa6d7022c3873/href">https://medium.com/media/4c239d24b349269748eaa6d7022c3873/href</a></iframe><p>And there you have it. Speedy hot reloading with create-react-app. You can see it in action on <a href="https://github.com/superhighfives/react-three-playground">React Three Playground</a>, if you’re looking for a proper example.</p><p>PS: You’re doing a great job. Even Beyoncé says so.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fgiphy.com%2Fembed%2F13B3a2WWKcEo9O%2Ftwitter%2Fiframe&amp;src_secure=1&amp;url=http%3A%2F%2Fgiphy.com%2Fgifs%2Fbeyonce-yes-gif-13B3a2WWKcEo9O&amp;image=https%3A%2F%2Fmedia.giphy.com%2Fmedia%2F13B3a2WWKcEo9O%2F200.gif&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=giphy" width="435" height="245" frameborder="0" scrolling="no"><a href="https://medium.com/media/d3dbbd03a9d2b8b3d055a2fd84497eca/href">https://medium.com/media/d3dbbd03a9d2b8b3d055a2fd84497eca/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=73297a00dcad" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/hot-reloading-create-react-app-73297a00dcad">Hot Reloading + create-react-app</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Harp, Gulp And BrowserSync]]></title>
            <link>https://medium.com/superhighfives/harp-gulp-and-browsersync-7d2ed7c8ac7c?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/7d2ed7c8ac7c</guid>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[gulp]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[static-site]]></category>
            <category><![CDATA[harp]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Fri, 20 Jan 2017 21:07:13 GMT</pubDate>
            <atom:updated>2017-01-21T13:25:37.779Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2Qyppngjh9dcgY-7yTi2eQ.png" /><figcaption>Originally posted August 2014 at <a href="https://charliegleason.com">https://charliegleason.com</a></figcaption></figure><p><em>Or how I have a weird enthusiasm for static site generators</em></p><p>A couple of weeks ago I decided to rejig my personal site, because I hit a particularly tough patch in <a href="http://www.saintsrow.com/uk">Saints Row 4</a> and what else would I spend a Saturday doing? Previously I’d had good experiences with <a href="https://github.com/mdub/pith">Pith</a>, which is a really solid Ruby based static site generator, but I’d overcomplicated the whole thing and it felt a bit clunky. Plus I wanted to try some new fanciness.</p><p>After setting up <a href="http://jekyllrb.com/">Jekyll</a>, another Ruby based static site generator (we should acronym that, no?), I got a <a href="https://twitter.com/glenmaddern/status/499330737431015425">tweet</a> from Glen Maddern, mentioning a deep affection for <a href="http://harpjs.com/">Harp.js</a>. It made me realise that though I’ve admired it from afar, I hadn’t really messed much with <a href="http://nodejs.org/">Node.js</a>, and a personal site is a pretty good place to get your hands dirty.</p><p>At the same time, I was hearing good things about <a href="http://gulpjs.com/">Gulp.js</a>, the Node based streaming build system, and I’d always found it’s predecessor <a href="http://gruntjs.com/">Grunt.js</a> a little verbose.</p><p><a href="http://browsersync.io">BrowserSync</a> was the final piece of the puzzle, and I was primarily curious about its much touted ability to inject CSS changes without reloading the page.</p><p>So I dug in.</p><h4>Setting it all up</h4><p>So, we’ll need <a href="http://gulpjs.com/">Gulp</a>, <a href="http://harpjs.com/">Harp</a> and <a href="http://browsersync.io">BrowserSync</a>.</p><h4>Getting started with Gulp</h4><p>The first thing I noticed, when checking out Gulp, was the simplicity. After wrestling with Grunt for so long, I was chuffed to see a single named function was all that’s needed to get started.</p><p>(To be fair, I’ve not written anything particularly onerous in Gulp, so that’s a bit harsh.)</p><p>First, make sure you’ve got <a href="https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md#getting-started">Gulp installed</a>.</p><pre>npm install --global gulp</pre><p>Then you’ll need a gulpfile.js at the root of your project.</p><pre>var gulp = require(&#39;gulp&#39;);<br><br>gulp.task(&#39;default&#39;, function() {<br>  console.log(&quot;Gulp lol look at me being rad.&quot;);<br>});</pre><p>As it’s the default task, just run gulp.</p><pre>gulp</pre><h4>Getting started with Harp</h4><p>Similarly, Harp is super straightforward.</p><pre>sudo npm install -g harp</pre><p>You can then use harp to generate the bones of a project.</p><pre>harp init myproject</pre><p>That will give you the barest of projects, using <a href="http://lesscss.org/">Less</a> for styles and <a href="http://jade-lang.com/">Jade</a> for HTML. Personally, I prefer <a href="http://sass-lang.com/">Sass</a> and <a href="http://embeddedjs.com/">EJS</a>, but it’s not hard to change things over. Harp tends towards convention over configuration, so all you really need is a single .ejs or .jade page and you’re good to go.</p><h4>Getting started with BrowserSync</h4><p>Finally, <a href="http://browsersync.io">BrowserSync</a>.</p><p>Technically you don’t need to install this globally, unless you’re using it separately from the command line, so you can skip this step and just have it in your npm package.json.</p><p>But, if you’re keen:</p><pre>npm install -g browser-sync</pre><p>For this example we’ll run BrowserSync via Gulp, so you don’t need to do anything else at this point. You can run from the command line though, using the browser-sync command.</p><h4>Setting the scene</h4><p>So, there are some dependencies involved. To make life a little easier, I’ve pulled together the cleverly titled boilerplate, <a href="https://github.com/superhighfives/harp-gulp-browsersync-boilerplate">harp-gulp-browsersync-boilerplate</a>. You can use it to get the whole thing up and running straight away, and then I’ll go through and explain what’s happening. Cool? Cool.</p><p>Let’s take a moment to look at a lolcat.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/575/1*y7uMxwPANQ-sHBG6B4VOrw.png" /><figcaption>Phew.</figcaption></figure><p>That was awesome.</p><p>So, Harp has a really great feature where you can use any repo as a boilerplate. To use my super-fancy repo, you just need the --boilerplate (or -b) option.</p><pre>harp init src --boilerplate superhighfives/harp-gulp-browsersync-boilerplate</pre><p>Then, once it’s downloaded (maybe make a tea or something?) you can jump into src and grab the dependencies.</p><pre>npm install</pre><p>Maybe make another tea? You may be sick of tea by now. I’m not confident in how much tea you drink each day, so I don’t want to be presumptious.</p><p>Finally, run gulp.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/555/1*qH3Rf8W-zoFkT4GZ-tSdwQ.png" /><figcaption>An example of the terminal output you should probably see.</figcaption></figure><p>Here’s what is happening. Gulp fires up Harp on port 9000 (you can change that in the gulpfile.js), and BrowserSync proxies it, usually on 3000. So just hit up localhost:3000 and you’re ready to party. It’s worth checking the output in your terminal though, as it will give you the definitive address.</p><h4>Changing things, because you can</h4><p>Now you can edit main.scss and the updates will happen in real-time. It’s the same system that’s currently running this blog, and you can see the full range of tasks (including deploying straight to <a href="https://pages.github.com/">Github Pages</a>) in the source <a href="https://github.com/superhighfives/charliegleason.com">over on Github</a>.</p><p>This is the sound of you succeeding, you beautiful human.</p><p><em>Acknowledgements:</em><strong> </strong><a href="http://twitter.com/glenmaddern">Glen Maddern</a> cracked the BrowserSync injection, and is just the best human</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7d2ed7c8ac7c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/harp-gulp-and-browsersync-7d2ed7c8ac7c">Harp, Gulp And BrowserSync</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deploying To GitHub Pages With Gulp]]></title>
            <link>https://medium.com/superhighfives/deploying-to-github-pages-with-gulp-c06efc527de8?source=rss----d2901740a9f0---4</link>
            <guid isPermaLink="false">https://medium.com/p/c06efc527de8</guid>
            <category><![CDATA[gulp]]></category>
            <category><![CDATA[javascript]]></category>
            <category><![CDATA[github]]></category>
            <category><![CDATA[web-development]]></category>
            <dc:creator><![CDATA[Charlie Gleason]]></dc:creator>
            <pubDate>Fri, 20 Jan 2017 21:06:42 GMT</pubDate>
            <atom:updated>2019-12-11T10:21:08.572Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Abid82ajmmD7ZLQs96M6FQ.png" /><figcaption>Originally posted September 2014 at <a href="https://charliegleason.com">https://charliegleason.com</a></figcaption></figure><p>The older I get, the more I realise that I do not like <a href="http://en.wikipedia.org/wiki/Don&#39;t_repeat_yourself">doing things more than once</a>.</p><p>When I first starting making the Internets, I would spend a massive amount of cognitive energy transferring things via FTP; dragging files to <a href="transmit">Transmit</a>, hoping I hadn’t inadvertently overwritten something super important. It was dark, people. It was a dark time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*FcDPYdXP78ezQwOh4grs8Q.png" /><figcaption>No, FTP. No.</figcaption></figure><p>Fortunately, this is no longer the case. You don’t have to live like this. <strong>We</strong> don’t have to live like this.</p><p>I’ve been using <a href="http://pages.github.com/">GitHub Pages</a> to deploy static sites for a while now. It’s quick, easy, and pretty painless. You can easily get a static site set up and hosted in no time, and it’s free. Win win! I actually used it for the client side of <a href="http://tweetflight.wearebrightly.com">Tweetflight</a>.</p><p>If you’ve run through my <a href="http://charliegleason.com/articles/harp-gulp-and-browsersync">Harp, Gulp and Browsersync</a> tutorial, you can use that as the basis for deployment. If you haven’t, all you need is a <a href="https://github.com/repositories/new">repo</a> and a directory to deploy. Easy as.</p><p>First up, you’ll want to install <a href="http://gulpjs.com/">gulp</a> and <a href="https://github.com/rowoot/gulp-gh-pages">gulp-gh-pages</a>, which will handle the deployment.</p><h4>Getting started</h4><p>So, you’ll need a package.json file, to use manage the required Node packages.</p><pre>npm init</pre><p>If you don’t have <a href="http://nodejs.org/">Node.js</a>, you can install it <a href="http://nodejs.org/">here</a>.</p><p>It will ask you some questions about your project, and it’s pretty friendly. Good for you, NPM. Good. For. You.</p><p>Right. To celebrate, let’s enjoy a photo of a cat in the snow.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*f2fVA3dValwNQm1f9cSfdg.png" /><figcaption>Yes. You are the best cat.</figcaption></figure><p>So good.</p><p>Add <a href="http://gulpjs.com/">Gulp</a>, which powers this glorious, gorgeous beast.</p><pre>npm install gulp --save-dev</pre><p>Then you’ll need to add <a href="https://github.com/rowoot/gulp-gh-pages">gulp-gh-pages</a>.</p><pre>npm install gulp-gh-pages --save-dev</pre><p>Now, in your gulpfile.js, add the following:</p><pre>var gulp        = require(&#39;gulp&#39;);<br>var deploy      = require(&#39;gulp-gh-pages&#39;);<br><br>/**<br> * Push build to gh-pages<br> */<br>gulp.task(&#39;deploy&#39;, function () {<br>  return gulp.src(&quot;./dist/**/*&quot;)<br>    .pipe(deploy())<br>});</pre><h4>So what’s going on here?</h4><p>We’re defining a <strong>task</strong>, called deploy. You could get gulp to run a build task here, if you needed to, prior to deploying it. To do so, just update ‘deploy’, function() { to ‘deploy, [‘build’], function () { (or whatever the name of you gulp build task is) and gulp will take care of it. It’s one of the many reasons gulp is wild.</p><p>I used gulp four times in that paragraph. Calm down, Charlie.</p><p>/dist is the directory we’re deploying, and /**/* means it will deploy recursively. All files and directories inside of /dist will be included.</p><h4>GitHub-ing</h4><p>So, given that you’re deploying to GitHub, you’re going to need to have your site in a repository. You can see an example I set up at <a href="https://github.com/superhighfives/testing-gulp-gh-pages">testing-gulp-gh-pages</a>. If you don’t already have your site on <a href="http://github.com/">GitHub</a>, you should anyway. It’s awesome, and means you’ll be using proper version control for your site. Which is a huge piece of mind. Which you obviously deserve.</p><p>You’ll want to avoid pushing your whole /node_modules directory on GitHub, as it’s being managed by your package.json file. To stop this happening, make a file called .gitignore. That’s essentially a space where you can <a href="https://help.github.com/articles/ignoring-files">list files you don’t want to end up in source control</a>, each on a new line.</p><p>Just make sure node_modules is listed:</p><pre>node_modules</pre><p>That way, when you push to GitHub, you won’t accidentally push all of your sites Node depedencies.</p><p>If you don’t want to commit your /dist, or the folder that is holding your built site, you can add that too:</p><pre>node_modules<br>dist</pre><p>It really depends on how you’re managing your folder structure. There’s no wrong way, but it’s worth noting that if your repo is public you should avoid putting any fancy paid fonts or similar in there.</p><p>In that case you’re likely better hosting them remotely with <a href="http://aws.amazon.com/s3/">S3</a> or <a href="http://www.rackspace.co.uk/cloud/files">Rackspace</a>. I use Rackspace, personally.</p><h4>Custom domains</h4><p>If you want to use a <a href="https://help.github.com/articles/setting-up-a-custom-domain-with-github-pages">custom domain</a> for your GitHub hosted site, you’ll need to do two things first.</p><ol><li>Make a text-based CNAME file that will end up in the root of the directory you’re deploying. For example, /dist/CNAME. All it needs inside is the url you want to point to your new site. For me, it’s charliegleason.com.</li><li>Update your DNS records. GitHub has a <a href="https://help.github.com/articles/setting-up-a-custom-domain-with-github-pages">pretty good walkthrough of how to do this</a>.</li></ol><p>When you’re ready to deploy, the folder you’re pushing to GitHub should have CNAME in the root. As long as that’s in there, you’re golden.</p><blockquote>One thing I should also mention—people have flagged that because their website was hosted from <em>my_username.github.io</em>, their custom domain wasn’t working. Using a repository name other than <em>my_username</em> seemed to fix things. Just an FYI. (Thanks Nikolas!)</blockquote><p>And then you’re all set.</p><h4>Fire away!</h4><p>When you’re ready to deploy, push the latest changes to your repo to GitHub.</p><pre>git add . # Add any untracked files<br>git commit -va # Commit the changes<br>git push # Push it to GitHub</pre><p>You’ll also need to make sure you have a gh-pages branch, if you don’t already. (Be careful when using git rm -rf ., too!)</p><pre>git checkout --orphan gh-pages<br>git rm -rf .<br>touch README.md<br>git add README.md<br>git commit -m &quot;Init gh-pages&quot;<br>git push --set-upstream origin gh-pages<br>git checkout master</pre><p>So, now you just need to run your deploy task.</p><pre>gulp deploy</pre><p>And voila. You can visit your fancy new site at your-username.github.io/your-reponame, or (if the DNS has propogated) at the custom domain you set up.</p><p>You can see <a href="http://superhighfives.github.io/testing-gulp-gh-pages/">one I prepared earlier</a>, which is using the testing-gulp-gh-pages <a href="https://github.com/superhighfives/testing-gulp-gh-pages">repo</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-mB1ulq--2Y9ETqH8uGqOw.png" /><figcaption>Yes, Github Pages. Yes.</figcaption></figure><p>You’re great. Good for you. If you have any problems, I can probably help. Just <a href="mailto:hi@charliegleason.com">email me</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c06efc527de8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/superhighfives/deploying-to-github-pages-with-gulp-c06efc527de8">Deploying To GitHub Pages With Gulp</a> was originally published in <a href="https://medium.com/superhighfives">superhighfives</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>