<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.1">Jekyll</generator><link href="https://shubox.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://shubox.io/" rel="alternate" type="text/html" /><updated>2025-09-27T16:00:16+00:00</updated><id>https://shubox.io/feed.xml</id><title type="html">shubox.io</title><subtitle>The easiest and fastest way for your web-app to upload images directly to Amazon S3
</subtitle><entry><title type="html">Shutting down Shubox</title><link href="https://shubox.io/blog/2025/09/24/shutting-down-shubox/" rel="alternate" type="text/html" title="Shutting down Shubox" /><published>2025-09-24T00:00:00+00:00</published><updated>2025-09-24T00:00:00+00:00</updated><id>https://shubox.io/blog/2025/09/24/shutting-down-shubox</id><content type="html" xml:base="https://shubox.io/blog/2025/09/24/shutting-down-shubox/"><![CDATA[<p>Last week I sent the following email out to customers, colleagues, supporters
and advisors:</p>

<blockquote>
  <p>Hello there,</p>

  <p>I truly hope that this email finds you well.</p>

  <p>If you’re getting this email you are currently, or have been, a user, a
customer, or a supporter of the Shubox service. Shubox is an app that adds a
“nice” layer on top of the Amazon Web Services S3 to make uploading files to
S3 easier.</p>

  <p>I’m here to share the news that I plan on shutting Shubox down at the end of
the year. It’s been a truly wonderful ride these last 10 (or so) years and I
wouldn’t change a thing about the experience. I’ve been candid and honest
elsewhere about what the journey has been like, but as with most things
learning hard lessons is often the product of difficult, challenging, trying
experiences.</p>

  <p>The decision to shut things down has been in the back of my mind for several
years and I am finally at peace with the prospect of closing these doors.
It’s time to concentrate on myself, my family, and the long list of things
that “fill my cup” instead of the things I feel I should or need to do.</p>

  <hr />

  <p>What does this mean for you?</p>

  <p>• Most everyone here hosts their own S3 bucket. This will remain yours,
   forever. Your files are yours and I will do nothing with them. No deleting.
   Nothing. 
 • We will work with anyone who’s had Shubox-provisioned buckets move all
   objects to your own S3 Bucket.
 • I will work with anyone who needs guidance on how to move forward with
   transitioning from the Shubox infrastructure to a new solution.
 • I will be sending an email at the end of both October and November, with a
   report on how many files are being uploaded, transformed, etc. This email
   will act as a reminder that Shubox will shut down on New Year’s eve,
   December 31, 2025. (I hope this is enough lead time to make the transition.</p>

  <p>If you have any questions, or need to work with me on timing, please respond
to this email directly. It’ll come right to me.</p>

  <p>I cannot thank you enough for your time, your trust, your collaboration, your
support, and your interest.</p>

  <p>🙏🏼️</p>

  <p>Joel Oliveira
Founder. Engineer. Janitor – Shubox</p>
</blockquote>

<p>And I have written more about this on my personal website at <a href="https://joeloliveira.com/2025/09/22/deciding-to-shut-down-shubox">joeloliveira.com</a>, 
in case you’re interested in some further perspective. It’s been a wonderful ride. 
I wouldn’t change a thing. Thank you.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Last week I sent the following email out to customers, colleagues, supporters and advisors:]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/shubox.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/shubox.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">What is Amazon S3?</title><link href="https://shubox.io/blog/2023/12/29/what-is-amazon-s3/" rel="alternate" type="text/html" title="What is Amazon S3?" /><published>2023-12-29T00:00:00+00:00</published><updated>2023-12-29T00:00:00+00:00</updated><id>https://shubox.io/blog/2023/12/29/what-is-amazon-s3</id><content type="html" xml:base="https://shubox.io/blog/2023/12/29/what-is-amazon-s3/"><![CDATA[<figure class="photo-with-caption">
  <picture>
    <!--[if IE 9]><video style="display: none;"><![endif]-->
    <source srcset="/assets/blog/posts/bucket-guy.webp" type="image/webp" />
    <!--[if IE 9]></video><![endif]-->
    <img src="/assets/blog/posts/bucket-guy.jpg" decoding="async" alt="Man marveling at the amount of data he has stored in, and is now overflowing from, his bucket." width="544" height="311" />
  </picture>

  <figcaption>
    With so much data, where do you put it? In S3! What's an "S3"? Let's talk about it...
  </figcaption>
</figure>

<p>Imagine you have a large collection of data, files, “stuff”, you’d like to
store safely - photos, videos, important documents, backups, you name it. Now,
you could keep all of that under servers of your own control (EG: your own
computer, external hard drive, or server), but what if you run out of space,
your hardware fails, or something catastrophic happens? These circumstances are
where a service like Amazon S3 comes into play.</p>

<p><em>Amazon S3</em> stands for “Amazon Simple Storage Service”. Think of it as a
massive, super-secure warehouse in the cloud where you can store as much data
as you need. It’s akin to renting a storage unit, but instead of physical
<em>stuff</em>, you’re storing digital files. You can access your files from anywhere
in the world, anytime, as long as you have an internet connection. I have seen
it referred to as “the internet’s hard drive”, which, at this point, is a
reasonable and accurate distillation. For a comprehensive deep dive into the
history and technical scale of S3 go <a href="https://www.allthingsdistributed.com/2023/07/building-and-operating-a-pretty-big-storage-system.html">read this post at allthingsdistributed.com</a>
from <a href="https://www.linkedin.com/in/andywarfield/">Andy Warfield</a>, VP and distinguished engineer at Amazon.</p>

<p>Amazon S3 is the brand name for what is more generically called cloud “object
storage”. You might consider it akin to what “Kleenex” is to “facial tissues”,
or what “Xerox” is to “photocopiers”, or “Google” to “web searching”. As a
result, there <strong>are</strong> other object storage vendors out there: <a href="https://developers.cloudflare.com/r2/">Cloudflare</a>,
<a href="https://cloud.google.com/storage/">Google</a>, <a href="https://www.ibm.com/products/cloud-object-storage">IBM</a>, <a href="https://wasabi.com/">Wasabi</a>, and <a href="https://www.digitalocean.com/products/spaces">DigitalOcean</a> to name a few. There are also
open source solutions like <a href="https://github.com/minio/minio">MinIO</a> or <a href="https://garagehq.deuxfleurs.fr/">Garage</a>.</p>

<p>It should be noted, however, that Amazon’s S3 is the originator of this space.
They created the technology, the concept, the utility, and should be afforded
the respect and admiration for their innovation.</p>

<h2 id="so-what-is-a-bucket"><em>So, what is a “bucket”?</em></h2>

<p>Considering <a href="https://shubox.io/">Shubox</a> is in the business of providing you buckets on-demand -
you should know! A bucket is a container for objects stored in S3. If S3 is a
giant warehouse, then a bucket is your personal, ever-expanding, storage
locker. A bucket serves as a means of keeping companies’ and individuals’ data
sequestered away from everyone else’s.</p>

<h2 id="why-is-it-useful"><em>Why is it useful?</em></h2>

<ul>
  <li><strong>Scalability:</strong> You can store an almost unlimited amount of data. That
“storage unit” analogy? Imagine it could expand, on demand, as soon as you
need more space.</li>
  <li><strong>Security:</strong> Amazon S3 will keep your data safe. They’ve got loads of
security measures in place, so you don’t have to worry about your data
getting into the wrong hands.</li>
  <li><strong>Accessibility and Sharing:</strong> You can access your data from anywhere and
easily share it with others. Permissions are flexible and robust enough where
you could go from “world readable” to “restricted to specific Amazon roles
and users”.</li>
  <li><strong>Affordability:</strong> The cost is inexpensive to start (think <em>pennies</em>) until
you reach a considerable scale of storage and data transfer.</li>
</ul>

<h2 id="what-are-some-example-use-cases"><em>What are some example use-cases?</em></h2>

<ul>
  <li><strong>Backup and Storage:</strong> This is the no-brainer. Whether you’re a big company or
someone with a lot of digital photos, S3 is great for keeping that data
safe, and off-site.</li>
  <li><strong>Website Hosting:</strong> Have a website with many images and/or videos? Storing and
serving them via S3 is more efficient and reliable than keeping them on
your own servers.</li>
  <li><strong>Big Data Analytics:</strong> Companies can store massive amounts of data on S3 and
then use other Amazon services to analyze this data to gain insights.</li>
  <li><strong>Disaster Recovery:</strong> In case something goes wrong with your primary data
storage, having a backup on S3 can be a lifesaver. It is, effectively, an
insurance policy for your data.</li>
</ul>

<p>In a nutshell, Amazon S3 is a versatile, super-sized digital storage unit in
the cloud. It’s an essential tool for anyone dealing with significant amounts
of data, whether for personal use or business. And with its pay-as-you-go
pricing, it is also wallet-friendly. If you’re still wondering whether you
should use it, <a href="https://www.onixnet.com/blog/what-is-amazon-s3/">this post at Onixnet</a> sums it up rather succinctly:</p>

<blockquote>
  <p>If you’re still not sure whether Amazon S3 is right for your organization,
consider this: Amazon S3 is designed for 99.999999999% (11 9s) of data
durability. With that level of durability, you can expect that if you store
10,000,000 objects in Amazon S3, you should only expect to lose a single
object every 10,000 years!</p>
</blockquote>]]></content><author><name></name></author><summary type="html"><![CDATA[]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/bucket.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/bucket.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Easy, Quick Webcam Video Recording with Shubox</title><link href="https://shubox.io/blog/2020/08/16/easy-quick-webcam-video-recording-with-shubox/" rel="alternate" type="text/html" title="Easy, Quick Webcam Video Recording with Shubox" /><published>2020-08-16T00:00:00+00:00</published><updated>2020-08-16T00:00:00+00:00</updated><id>https://shubox.io/blog/2020/08/16/easy-quick-webcam-video-recording-with-shubox</id><content type="html" xml:base="https://shubox.io/blog/2020/08/16/easy-quick-webcam-video-recording-with-shubox/"><![CDATA[<p>I won’t lie. The <a href="https://webrtc.github.io/samples/">WebRTC</a> and <a href="https://developers.google.com/web/updates/2016/01/mediarecorder">MediaRecorder</a> API’s aren’t the easiest things
to get working <em>just right</em>. Not easy, still maybe a <em>little</em> fun. Depending on
your outlook, though, Safari might suck a healthy amount of fun out of the
exercise. It’s an objectively great browser but the fact remains that Apple
continues to slow-walk a number of meaningful API’s. MediaRecorder is one of
them. Elsewhere on the web, <a href="https://blog.addpipe.com/safari-technology-preview-73-adds-limited-mediastream-recorder-api-support/">Octavian Naicu writes about</a> some of the
challenges you might run into with Safari/Webkit. It’s a worthwhile read if you
ever expect to make the attempt yourself.</p>

<p>I’m happy to say that you can instead jump ahead of all that <em>if you’re using
Shubox</em>. You can have all the functionality at your fingertips, without the
cross-browser debugging and headache’ery (that’s not a word, but I will allow
it). I am happy to say that <em>*webcam video recording*</em> support is now baked
into the Shubox JavaScript library.</p>

<p>What does that mean?</p>

<p>It means that your work consists of one HTML element [<a href="#note-1">1</a>]:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">style=</span><span class="s">"width: 640px; height: 480px;"</span>
     <span class="na">id=</span><span class="s">"webcam-video"</span><span class="nt">&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p>… and a bit of javascript that will do all of the heavy lifting for you. The
following will create the video and canvas elements, and hook up click events to
start the camera, start recording, and stop recording.</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">video</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Shubox</span><span class="p">(</span><span class="dl">'</span><span class="s1">#webcam-video</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
  <span class="na">key</span><span class="p">:</span> <span class="dl">'</span><span class="s1">SHUBOX-KEY</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">webcam</span><span class="p">:</span> <span class="dl">'</span><span class="s1">video</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">success</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`File </span><span class="p">${</span><span class="nx">file</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2"> successfully uploaded!`</span><span class="p">)</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">file</span><span class="p">.</span><span class="nx">s3url</span><span class="p">)</span>
  <span class="p">},</span>
<span class="p">})</span>
</code></pre></div></div>

<p>The size of the video will be predicated on the size of the <code class="language-plaintext highlighter-rouge">#webcam-video</code>
element. Clicking the element will start the camera. Subsequent clicks of the
element will start and stop recording the video [<a href="#note-2">2</a>], followed by its being
uploaded to your bucket.</p>

<p>Of course, that’s not all you are limited to. You may customize things to suit
your user experience with options to tie the different life cycle events to
other elements that may trigger them, and callbacks for different points of
that life cycle. For example:</p>

<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">videoWithOptions</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Shubox</span><span class="p">(</span><span class="dl">'</span><span class="s1">#webcam-video</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
  <span class="na">key</span><span class="p">:</span> <span class="dl">'</span><span class="s1">SHUBOX-KEY</span><span class="dl">'</span><span class="p">,</span>
  <span class="na">webcam</span><span class="p">:</span> <span class="p">{</span>
    <span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">video</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">startCamera</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#video-start</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">stopCamera</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#video-stop</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">startRecording</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#video-record-start</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">stopRecording</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#video-record-stop</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">audioInput</span><span class="p">:</span> <span class="dl">'</span><span class="s1">.shubox-audioinput</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">videoInput</span><span class="p">:</span> <span class="dl">'</span><span class="s1">.shubox-videoinput</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">cameraStarted</span><span class="p">:</span> <span class="p">(</span><span class="nx">_webcam</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">camera started</span><span class="dl">"</span><span class="p">)</span>
    <span class="p">},</span>
    <span class="na">cameraStopped</span><span class="p">:</span> <span class="p">(</span><span class="nx">_webcam</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">camera stopped</span><span class="dl">"</span><span class="p">)</span>
    <span class="p">},</span>
    <span class="na">recordingStarted</span><span class="p">:</span> <span class="p">(</span><span class="nx">_webcam</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">recording started</span><span class="dl">"</span><span class="p">)</span>
    <span class="p">},</span>
    <span class="na">recordingStopped</span><span class="p">:</span> <span class="p">(</span><span class="nx">_webcam</span><span class="p">,</span> <span class="nx">_file</span><span class="p">)</span> <span class="o">=&gt;</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">recording stopped</span><span class="dl">"</span><span class="p">)</span>
    <span class="p">}</span>
  <span class="p">},</span>
  <span class="na">success</span><span class="p">:</span> <span class="nx">file</span> <span class="o">=&gt;</span> <span class="p">{</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`File </span><span class="p">${</span><span class="nx">file</span><span class="p">.</span><span class="nx">name</span><span class="p">}</span><span class="s2"> successfully uploaded!`</span><span class="p">)</span>
    <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">file</span><span class="p">.</span><span class="nx">s3url</span><span class="p">)</span>
  <span class="p">},</span>
<span class="p">})</span>
</code></pre></div></div>

<p>I’m happy to say that video recording is already being used by <a href="https://www.futureme.org">our friends at
FutureMe</a> where the <em>Pro</em> users are now able to record videos of themselves and
send them into the future where the past versions of themselves can impart some
old knowledge … to … themselves? I’ve confused myself.</p>

<p>Anyway.</p>

<p>If you’d like to see for yourself how this works, I also put up a small demo
<a href="https://codepen.io/shubox/pen/QWyQmMp">at Codepen</a>. Give it a whirl, and let us know what you think <a href="https://twitter.com/shuboxio">on twitter</a>!</p>

<h2 id="notes">Notes</h2>

<ol>
  <li><a name="note-1"></a> The size of the div will be what determines the size
of the video. I suggest sizing it to one of the common video aspect ratios -
4:3 or 16:9.</li>
  <li><a name="note-2"></a> Format of the video depends on which web browser you
are using. If on Chrome or FireFox, the video will be in webm format. If on
safari, it will be an mp4. For more details <a href="https://github.com/shuboxio/shubox.js/blob/master/packages/@shubox/core/src/webcam/video_events.ts#L136-L150">see the source code</a> for how
the codecs are chosen.</li>
</ol>]]></content><author><name></name></author><summary type="html"><![CDATA[I won’t lie. The WebRTC and MediaRecorder API’s aren’t the easiest things to get working just right. Not easy, still maybe a little fun. Depending on your outlook, though, Safari might suck a healthy amount of fun out of the exercise. It’s an objectively great browser but the fact remains that Apple continues to slow-walk a number of meaningful API’s. MediaRecorder is one of them. Elsewhere on the web, Octavian Naicu writes about some of the challenges you might run into with Safari/Webkit. It’s a worthwhile read if you ever expect to make the attempt yourself.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/picture.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/picture.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Shubox JS Library Now With Webcam Support</title><link href="https://shubox.io/blog/2020/04/12/shubox-js-now-with-webcam-support/" rel="alternate" type="text/html" title="Shubox JS Library Now With Webcam Support" /><published>2020-04-12T00:00:00+00:00</published><updated>2020-04-12T00:00:00+00:00</updated><id>https://shubox.io/blog/2020/04/12/shubox-js-now-with-webcam-support</id><content type="html" xml:base="https://shubox.io/blog/2020/04/12/shubox-js-now-with-webcam-support/"><![CDATA[<p>A few months ago I was out to lunch with my friend, Matt Sly. When he and I get
together to catch up, we’d normally shoot the breeze about anything and
everything — our families, our day jobs, basketball, politics, what have
you. Inevitably it would end up with one of us opening up our laptop to discuss
what’s going on with our passion projects. For me that’s Shubox, of course, and
for Matt it’s <a href="https://www.futureme.org">FutureMe</a>. FutureMe has been around for a <em>long</em> time. Eighteen
years!  That is a <em>significant</em> amount of time. That’s a window of time to
accrue a healthy amount of cruft and old tech, a patina of bits and bytes in a
long-lived codebase. Which leads us to this particular lunch for Matt and I.
This time there was something specific that caught my eye while Matt and I were
looking over the FutureMe code — something so stark that I was compelled
to ask, “Friend, what on earth is this <em>SWF</em> file?”</p>

<p>He replied that “that is a remnant from the days I allowed people to take
photos of themselves and attach them to the letters they’d send to themselves
in the future”. It was a Flash component that interfaced with webcams.</p>

<p>We bandied around the idea that with the native controls available in browsers
these days he, we, <em>could</em> replace that old relic with good old JavaScript.</p>

<p>“Why don’t you build that right into Shubox? Think you could?”, he asked.</p>

<p>Think I could? Was that a challenge? Well. Challenge accepted.</p>

<p>That little feature is now released to npm with <a href="https://www.npmjs.com/package/shubox/v/0.3.0">version 0.3.0</a> of the Shubox
JS library. It’s a preliminary take on support for webcam(s) where there exists
some opportunity for further refinement and growth. Things to be added in the
future — selecting from available cameras, video and audio support, event
lifecycle callbacks, etc.</p>

<p>To give you an idea of what it takes to get this set up, let’s show you a
little code. If we have a div that’s properly sized to hold the camera preview:</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">id=</span><span class="s">"webcam-photo"</span>
     <span class="na">class=</span><span class="s">"webcam"</span>
     <span class="na">style=</span><span class="s">"width: 640px; height: 360px;"</span><span class="nt">&gt;&lt;/div&gt;</span>

<span class="nt">&lt;script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">&gt;</span>
  <span class="k">new</span> <span class="nx">Shubox</span><span class="p">(</span><span class="dl">'</span><span class="s1">#webcam-photo</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
    <span class="na">key</span><span class="p">:</span> <span class="dl">'</span><span class="s1">[shubox key]</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">webcam</span><span class="p">:</span> <span class="dl">'</span><span class="s1">photo</span><span class="dl">'</span><span class="p">,</span>
    <span class="na">success</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">file</span><span class="p">)</span> <span class="p">{</span>
      <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">file</span><span class="p">.</span><span class="nx">s3url</span><span class="p">)</span>
    <span class="p">},</span>
  <span class="p">})</span>
<span class="nt">&lt;/script&gt;</span>
</code></pre></div></div>

<p>Done! That is <em>it</em>! If you’ve set up your bucket correctly, clicking
the div will start the camera. Clicking it again will take the photo. And then
finally upload it to S3.</p>

<p>For more information, documentation, demos, gifs, <a href="https://github.com/shuboxio/shubox.js#capture-a-photo-with-your-webcam">visit the GitHub repo</a> and
take a look! If you’d like to see this in action head over to <a href="https://www.futureme.org">FutureMe</a> and
write the <em>future you</em> a letter. Attach a selfie while you’re at it!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[A few months ago I was out to lunch with my friend, Matt Sly. When he and I get together to catch up, we’d normally shoot the breeze about anything and everything — our families, our day jobs, basketball, politics, what have you. Inevitably it would end up with one of us opening up our laptop to discuss what’s going on with our passion projects. For me that’s Shubox, of course, and for Matt it’s FutureMe. FutureMe has been around for a long time. Eighteen years! That is a significant amount of time. That’s a window of time to accrue a healthy amount of cruft and old tech, a patina of bits and bytes in a long-lived codebase. Which leads us to this particular lunch for Matt and I. This time there was something specific that caught my eye while Matt and I were looking over the FutureMe code — something so stark that I was compelled to ask, “Friend, what on earth is this SWF file?”]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/picture.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/picture.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Announcing the NEW Shubox JS Library</title><link href="https://shubox.io/blog/2019/03/19/the-new-shubox-js-library/" rel="alternate" type="text/html" title="Announcing the NEW Shubox JS Library" /><published>2019-03-19T00:00:00+00:00</published><updated>2019-03-19T00:00:00+00:00</updated><id>https://shubox.io/blog/2019/03/19/the-new-shubox-js-library</id><content type="html" xml:base="https://shubox.io/blog/2019/03/19/the-new-shubox-js-library/"><![CDATA[<p><img src="https://s3.amazonaws.com/jekyll-shubox-io/localhost-5001/64ebeac6/544_andre-hunter-62014-unsplash.jpg" alt="YAAAAAAAY!" />
<span class="bg-light-gray f7 db pa2 tr nt5 br3 br--bottom">
Photo by <a href="https://unsplash.com/@dre0316">Andre Hunter</a> on <a href="https://unsplash.com">Unsplash</a>
</span></p>

<p>The Shubox mission from the beginning was simple - make it easier to get any
old arbitrary file from your computer or mobile phone to the biggest cloud
storage player in the world, Amazon S3, without having to hook up all this
boilerplate, <em>and</em> with flexibility and flair in the user experience.</p>

<p>The upload from browser to S3 was table stakes. That was a given. That will
never change. Shubox will always be stupid-simple. That last part, however, has
been an evolving piece of the puzzle. In order to accomplish the “flexibility
and flair” part our users need a javascript library that provides the right
tools in order to make things flexible, while fitting the experience in
your mind’s eye.</p>

<p>Until now(ish) we had the foundation to do this, and it was fine. We had a
javascript file generated specifically for each of our users’ domains. There
were a few custom bits and bobs injected into the JS that made things work.
Over time we noticed this wasn’t entirely scalable, and not entirely
conducive to having a fun development experience on our part.</p>

<p>I won’t belabor any further with the “why’s” and “how’s” things needed to
change because of course there are plenty. Instead let’s talk about the great
things that come with the <em>new</em> library as a way to illustrate how this shift
will benefit not only Shubox but <em>YOU</em>, the every day developer.</p>

<ol>
  <li><strong>It is written in <a href="https://typescript.com/">TypeScript</a>!</strong> It can’t be understated how the marriage
of a strong type system and superset of JavaScript have provided such a
wonderful and comfortable development environment. Once things are all wired
and working together I can say that “developing in JavaScript” is an
absolute joy. Setting up Webpack and all the tooling is another story, but
that is another (blog) story for another (blog) day.</li>
  <li><strong>It is now <a href="https://www.npmjs.com/package/shubox/">a package on NPM</a>.</strong> That’s right, Shubox is finally joining the
JS revolution and is distributed through the NPM package registry. Until now
the philosophy had been to make Shubox a standalone script file, unique to
your project/domain (per the note above) - just include it in your HTML and
you’re off to the races. The downside to this is that approach is analogous
to purchasing a horse and buggy in the age of cars. Single page
applications, react, vue, angular, et al, don’t work that way.  So, it was
beyond the time to get with the program.</li>
  <li>
    <p><strong>There are <em>many</em> new features.</strong> Let’s talk about some of the new ones:</p>

    <ul>
      <li>Transform completion callback. When your processed images are created, or
new file formats are generated, you can watch for existence of those files
and fire a callback function to do whatever you’d like.</li>
      <li>Support for a CDN instead of amazon’s bucket URL. Resulting files can now
be referenced via your chosen CDN hostname - <code class="language-plaintext highlighter-rouge">cdn.mydomain.com</code> instead
of <code class="language-plaintext highlighter-rouge">s3.amazonaws.com/my-bucket</code>.</li>
      <li><em>All</em> provided options are now passed along to Dropzone.js. Previously
there were only a subset of options moved along to the Dropzone instances.</li>
      <li>You can now specify the exact S3 object key for (an) uploaded file(s).
Very useful when you know exactly where a Shubox dropzone should end up,
named specifically to your liking.</li>
      <li>And more … the options, new and old, are <a href="https://github.com/shuboxio/shubox.js#library-documentation">all available to check out at
GitHub</a>.</li>
    </ul>
  </li>
  <li><strong>It is <em>open source</em>!</strong> That’s right. The Shubox TS code is all available
and open at <a href="https://github.com/shuboxio/shubox.js">our GitHub repo</a>. As is <a href="https://github.com/shuboxio/site">this blog</a>, mind you. Let us know over
there if <a href="https://github.com/shuboxio/shubox.js/issues">there are any issues, comments, feature requests</a>.</li>
  <li>There is more documentation – a LOT more documentation. With the guts of
<a href="https://github.com/shuboxio/shubox.js">everything on GitHub</a> the barrier to
shipping new docs with the features is virtually nonexistent.</li>
</ol>

<p>The JavaScript that’s been carrying the work-load up until now will continue to
live on for several more months until the new library makes its way to a 1.0
version. Needless to say, it will be a little while. We will not be pulling
those files off our CDN and will continue to support them. That being said -
we would still encourage you to try out the new version!</p>

<p>Suffice it to say, it’s been a journey getting this new library whipped into
shape to the point where things felt good getting out there.
<a href="https://codepen.io/shubox/pen/dNPyQV">All</a>
<a href="https://codepen.io/shubox/pen/bgNVGL">of</a>
<a href="https://codepen.io/shubox/pen/qRdddM">the</a>
<a href="https://codepen.io/shubox/pen/bgNKmR">demos</a>
at Codepen have been updated to use the new library – some with the
new features I outline above – so we invite you to <a href="https://codepen.io/shubox">kick the tires over there</a>.
Or check out the code <a href="https://github.com/shuboxio/shubox.js">at GitHub</a> and to let us know what you think at our
<a href="https://twitter.com/shuboxio">twitter account</a>, or email us directly at <a href="mailto:team@shubox.io">team@shubox.io</a>.
We’re all ears!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Photo by Andre Hunter on Unsplash]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/balloons.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/balloons.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Choosing the Right Next-Gen Format for Your Images</title><link href="https://shubox.io/blog/2018/05/10/choosing-the-right-next-gen-format-for-your-images/" rel="alternate" type="text/html" title="Choosing the Right Next-Gen Format for Your Images" /><published>2018-05-10T00:00:00+00:00</published><updated>2018-05-10T00:00:00+00:00</updated><id>https://shubox.io/blog/2018/05/10/choosing-the-right-next-gen-format-for-your-images</id><content type="html" xml:base="https://shubox.io/blog/2018/05/10/choosing-the-right-next-gen-format-for-your-images/"><![CDATA[<p>The web is getting bigger and slower. One of the easiest ways to improve the big part is to <a href="https://userinterfacing.com/the-fastest-way-to-increase-your-sites-performance-now/">compress your images</a> (or you can do it <a href="https://shubox.io/docs/#setup-image-transforms">automatically</a> with Shubox). An alternate question you could ask yourself is whether your image formats are the right type of images in the first place.</p>

<h2 id="the-basic-way-to-choose-image-types">The basic way to choose image types</h2>

<p>For the past few years, the easiest and most straightforward way to choose your image type was between photographs and graphics. As a quick rule of thumb: <strong>photographs should be JPEGs and everything else should be PNGs</strong>. There are two exceptions:</p>

<ol>
  <li>If you are using an animated image (or video converted to image), definitely use a GIF</li>
  <li>If you’re using images like icons (where they need to scale with your typography), see if you can convert that image to an SVG (Sketch is easily the best at <a href="https://medium.com/sketch-app-sources/the-best-way-to-export-an-svg-from-sketch-dd8c66bb6ef2">converting to SVG</a>)</li>
</ol>

<p>There are a bunch of other image formats, such as BMPs, EXIFs, and TIFFs, but those have largely fallen out of favor even though they still technically work.</p>

<p>For years this advice would serve you well. But the web is still evolving and there are new file formats to consider when putting your images on the web.</p>

<h2 id="the-advanced-way-to-choose-image-types">The advanced way to choose image types</h2>

<p>Recently there has been a rise in next-generation image formats to make the web lighter and more accessible. Unfortunately, the rules for choosing these formats is not as straightforward as it once was. Here are the 3 main types of next-gen image formats you should be considering when uploading your next image onto Shubox.</p>

<h3 id="jpeg-2000">JPEG 2000</h3>

<p><a href="https://jpeg.org/jpeg2000/index.html">JPEG 2000</a> is a newer incarnation of the JPEG format. The primary purpose of the format is to preserve metadata through radical compression techniques. While most traditional JPEGs have a limited set of metadata for photographs, JPEG 2000 uses structured XML to include a vast array of metadata information.</p>

<p>This is useful for applications like film and medical imaging because a great deal of data needs to be associated with the image. For example, film stills need to store information about high dynamic range and different color spaces. Medical imaging requires absolute precision in image clarity in spite of the large volume of data. With JPEG 2000, you can encode these files completely losslessly, with good-enough compression performance to make transfer acceptable.</p>

<p>Even if you aren’t in the film or healthcare industry, you can take advantage of these new compression techniques in your current JPGs by switching to JPEG 2000. Excluding these specific applications, as a general alternative to JPGs, JPEG 2000 is still superior because it can be compressed down even further than a standard JPEG with less loss in visual quality. With a smaller file size and better visual quality, JPEG 2000 is a total win over the standard JPG format. There is one caveat: if you are writing for the web, JPEG 2000 is only <a href="https://caniuse.com/#feat=jpeg2000">supported on Safari</a>, so it will only benefit your customers on Macs, iPhones, and iPads. As long as you use the other two formats that follow, you should definitely consider JPEG 2000 in your arsenal of image formats.</p>

<p><strong>NOTE:</strong> As of May 21 JPEG 2000 is a supported format by Shubox. You can now convert JPGs and PNGs to JPEG 2000!</p>

<h3 id="jpeg-xr">JPEG XR</h3>

<p><a href="https://jpeg.org/jpegxr/index.html">JPEG XR</a> is yet another next-gen JPEG format and a close cousin of JPEG 2000. JPEG XRs application is less intense than JPEG 2000 and was designed in many ways to be the successor of the standard JPEG format.</p>

<p>The main benefits of JPEG XR over the standard format are for enhanced support for HDR imagery. While the original format uses 3 color channels in a bit-depth of 8, JPEG XR supports multiple color formats like monochrome and CMYK and supports bit-depths of 16 or greater. It was also designed from the ground up to support better compression techniques. In other words, it is like JPEG on steroids.</p>

<p>While this is a more practical and versatile file format compared to JPEG 2000, it suffers from the same adoption blunders by being available on only a limited set of browsers. As of this writing, JPEG XR is only <a href="https://caniuse.com/#feat=jpegxr">supported on IE</a>, so it will only benefit your customers on Windows machines running some form of IE.</p>

<p>Combined, these two formats will cover all of your photography needs across the majority of devices. But what about PNGs? And what about open source browsers like Firefox and Chrome?</p>

<h3 id="webp">WebP</h3>

<p><a href="https://developers.google.com/speed/webp/">WebP</a> is the open source answer to the next generation of both JPGs and PNGs. The primary application of WebP is the web and is routinely 25% smaller than both optimized PNGs and JPGs.</p>

<p>Because of its web roots, WebP is immediately available in both Chrome and Opera. In addition, WebP has animation support and can be a great replacement for GIFs as well. <a href="https://developers.google.com/speed/webp/docs/precompiled"><code class="language-plaintext highlighter-rouge">cwebp</code></a> is a super easy command line tool to quickly convert your JPGs and PNGs into WebP images, which makes it even easier to convert into than JPEG 2000 or JPEG XR. Luckily, Shubox automates this as well and will let you convert your images into the WebP format when you upload them to S3. How cool is that?</p>

<p>Like the other formats, the major flaw is in browser support. As I mentioned, this comes supported out of the box by Chrome and Opera, but that’s it (well, and a bunch of <a href="https://caniuse.com/#feat=webp">other Chromium-based browsers too</a>).</p>

<p>Again, the thing to remember with next-gen photographs is a triple threat approach. <strong>If you want to put a photo on the web, you need to use JPEG 2000, JPEG XR, and WebP.</strong></p>

<h2 id="what-about-firefox">What about Firefox?</h2>

<p>If you overlay all of the browser support links, you’ll notice that Firefox is the only browser to not support any of these formats. Mozilla has tried to implement not <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1294490">once</a>, not <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=600919">twice</a>, but <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=856375">thrice</a>! Technically, they claim it is being worked on and has been assigned and updated within the last 2 weeks of this writing, but I’m not holding out any hope in the near future. In the meantime, keep the original image you used to create the previous three formats, and use that as the fallback for any browsers or devices that aren’t supported.</p>

<h2 id="how-to-combine-everything-to-get-a-total-solution">How to combine everything to get a total solution</h2>

<p>While the next generation image formats above are not supported by all browser vendors there are some tactics you can employ to get these images to your users in the best format possible.</p>

<ul>
  <li><strong>Utilize responsive images.</strong> Libraries like <a href="https://modernizr.com/">Modernizr</a> and <a href="https://scottjehl.github.io/picturefill/">Picturefill</a> can detect what is supported by the browser at runtime, and
polyfill responsive image support.</li>
  <li><strong>Use <code class="language-plaintext highlighter-rouge">srcset</code> to select each file type.</strong> <a href="https://www.w3.org/TR/html-srcset/"><code class="language-plaintext highlighter-rouge">Srcset</code></a> is an image property that lets you toggle between images based on various criteria, such as high-resolution displays which are typically only seen on newer laptops and mobile phones.</li>
  <li><strong>Use external services to convert your images for you.</strong> Shubox will automatically create WebP images for you, while <a href="https://i.onthe.io/jxr">Onthe.io</a> and <a href="https://mygeodata.cloud/converter/jpeg-to-jpeg2000">MyGeoData</a> will convert JPGs into JPEG XRs and JPEG 2000s, respectively.</li>
</ul>

<p>At first blush it might seem like a lot but consider an incremental support approach. With all of these image formats to choose from, you can experience the web of tomorrow, today!</p>]]></content><author><name></name></author><summary type="html"><![CDATA[The web is getting bigger and slower. One of the easiest ways to improve the big part is to compress your images (or you can do it automatically with Shubox). An alternate question you could ask yourself is whether your image formats are the right type of images in the first place.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/picture-x2.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/picture-x2.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Integrating with FormKeep</title><link href="https://shubox.io/blog/2018/03/27/integrating-with-formkeep/" rel="alternate" type="text/html" title="Integrating with FormKeep" /><published>2018-03-27T00:00:00+00:00</published><updated>2018-03-27T00:00:00+00:00</updated><id>https://shubox.io/blog/2018/03/27/integrating-with-formkeep</id><content type="html" xml:base="https://shubox.io/blog/2018/03/27/integrating-with-formkeep/"><![CDATA[<p>When I first started working on Shubox I considered it a distant cousin of
<a href="https://formkeep.com">FormKeep</a>, the “form endpoint” SaaS from <a href="https://www.furiouscollective.com/">Furious
Collective</a>, (formerly of
<a href="https://thoughtbot.com">thoughtbot</a>). It did one job, did it very well, and
went <em>deep</em> on the benefits it brought to those that used it. I have always
hoped that Shubox would deliver in a similar fashion.</p>

<p>In addition to sharing some philisophical DNA, there are some commonalities in
the type of work they do – delegating work from a customer’s website to an
external service. FormKeep offloads the work done to receive, persist, and
deliver form submissions. Shubox handles file and image uploads to the cloud
(S3 specifically, of course), manipulation of those images, and delivery of
that information to your applications.</p>

<p>Where and how can <em>both</em> help simultaneously? Let’s explore that.</p>

<p>Say you are a small business or startup. You’re growing <em>fast</em> and recruitment
and hiring are a high priority. You probably want a form on your site with a
couple of fields, maybe with name, email, cover letter, and some way for your
candidates to upload a Word, PDF, LaTex doc, or plain text (yeah!).
You have a statically generated site, or managed hosting of some sort, or your
developers are <em>completely</em> allocated on the core business and not able to work
on that side of the business.</p>

<p>Other than running a power play around your dev managers and wresting a
developer or two away from “business” for a day or two, what could you do?</p>

<p>Using FormKeep and Shubox and a little know-how you can get this done in ~20
minutes.</p>

<p>How?</p>

<h2 id="lets-start-with-the-form">Let’s start with the form</h2>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;form</span> <span class="na">action=</span><span class="s">"https://formkeep.com/f/xxxx"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">name=</span><span class="s">"position"</span> <span class="na">placeholder=</span><span class="s">"Position Applying For"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">name=</span><span class="s">"name"</span> <span class="na">placeholder=</span><span class="s">"Your Name"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"email"</span> <span class="na">name=</span><span class="s">"email"</span> <span class="na">placeholder=</span><span class="s">"Your Email"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;textarea</span> <span class="na">name=</span><span class="s">"cover_lever"</span> <span class="na">placeholder=</span><span class="s">"Cover letter contents..."</span><span class="nt">&gt;&lt;/textarea&gt;</span>

  <span class="nt">&lt;button</span> <span class="na">type=</span><span class="s">"submit"</span><span class="nt">&gt;</span>Apply for Position<span class="nt">&lt;/button&gt;</span>
<span class="nt">&lt;/form&gt;</span>
</code></pre></div></div>

<p>If you’ve signed up for FormKeep and are pointing to the endpoint they assign
you. You’re done with that part. Configure things on their dashboard – what
email to send new submissions to, integrate with Zapier, etc – and that’s
pretty much it.</p>

<h2 id="how-about-the-resume">How about the resume?</h2>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;form</span> <span class="na">action=</span><span class="s">"https://formkeep.com/f/xxxx"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"text"</span>  <span class="na">name=</span><span class="s">"position"</span> <span class="na">placeholder=</span><span class="s">"Position Applying For"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"text"</span>  <span class="na">name=</span><span class="s">"name"</span> <span class="na">placeholder=</span><span class="s">"Your Name"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;input</span> <span class="na">type=</span><span class="s">"email"</span> <span class="na">name=</span><span class="s">"email"</span> <span class="na">placeholder=</span><span class="s">"Your Email"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;textarea</span> <span class="na">name=</span><span class="s">"cover_lever"</span> <span class="na">placeholder=</span><span class="s">"Cover letter contents..."</span><span class="nt">&gt;&lt;/textarea&gt;</span>

  <span class="nt">&lt;input</span> <span class="na">id=</span><span class="s">"resume"</span>  <span class="na">type=</span><span class="s">"text"</span>  <span class="na">name=</span><span class="s">"resume"</span> <span class="na">placeholder=</span><span class="s">"Click to upload resume"</span><span class="nt">&gt;</span>

  <span class="nt">&lt;button</span> <span class="na">type=</span><span class="s">"submit"</span><span class="nt">&gt;</span>Apply for Position<span class="nt">&lt;/button&gt;</span>
<span class="nt">&lt;/form&gt;</span>

<span class="nt">&lt;script </span><span class="na">src=</span><span class="s">"https://js.shubox.io/v1/id-for-your-local-dev-server.js"</span><span class="nt">&gt;&lt;/script&gt;</span>

<span class="nt">&lt;script&gt;</span>
  <span class="k">new</span> <span class="nx">Shubox</span><span class="p">(</span><span class="dl">"</span><span class="s2">#resume</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span> <span class="na">textBehavior</span><span class="p">:</span> <span class="dl">"</span><span class="s2">replace</span><span class="dl">"</span> <span class="p">})</span>
<span class="nt">&lt;/script&gt;</span>
</code></pre></div></div>

<p>If you’ve signed up for Shubox you’ll be able to <a href="/docs/#local-dev-with-sandboxes">try this out immediately on
localhost</a>. Above, you will see that you would
add the script tag for your development server. (Pro-tip: <a href="https://dashboard.shubox.io/domains/sandbox">you’ll find that in
your dashboard</a>). Then, using the Shubox
javascript lib you can configure <code class="language-plaintext highlighter-rouge">input#resume</code> to start the “attach and upload
file” process once the input field is clicked. When you select your file it
will upload to S3 and populate the contents of that form field with the URL to
the file.</p>

<p><strong>And that’s it!</strong></p>

<p>After someone fills out the form, uploads a resume, and submits it, it will send
all that information to FormKeep, including the URL to the uploaded resume and,
depending on how your FormKeep account is configured, will email you that same
information.</p>

<p><em>Note: Once you deploy your website to your production domain you *will* need
to configure a “domain” in the Shubox dashboard for whatever hostname you use.
For example, if your final website lives at <code class="language-plaintext highlighter-rouge">acme-co.com</code> you’ll need to set that
up in the Shubox dashboard</em></p>]]></content><author><name></name></author><summary type="html"><![CDATA[When I first started working on Shubox I considered it a distant cousin of FormKeep, the “form endpoint” SaaS from Furious Collective, (formerly of thoughtbot). It did one job, did it very well, and went deep on the benefits it brought to those that used it. I have always hoped that Shubox would deliver in a similar fashion.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/doc-markdown.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/doc-markdown.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Use rails-erd Instead of annotate_models</title><link href="https://shubox.io/blog/2018/02/23/use-rails-erd-instead-of-annotate-models/" rel="alternate" type="text/html" title="Use rails-erd Instead of annotate_models" /><published>2018-02-23T00:00:00+00:00</published><updated>2018-02-23T00:00:00+00:00</updated><id>https://shubox.io/blog/2018/02/23/use-rails-erd-instead-of-annotate-models</id><content type="html" xml:base="https://shubox.io/blog/2018/02/23/use-rails-erd-instead-of-annotate-models/"><![CDATA[<p>Before we jump into <a href="https://github.com/voormedia/rails-erd"><code class="language-plaintext highlighter-rouge">rails-erd</code></a> and
how to integrate it into your workflow let’s talk about something adjacent to
that.</p>

<p>Often when dropping into a new Rails app I’ll notice that models, specs, and
factories will be the lucky bearers of the related database table schema thanks
to the <a href="https://github.com/ctran/annotate_models"><code class="language-plaintext highlighter-rouge">annotate_models</code></a> gem.</p>

<p>The <code class="language-plaintext highlighter-rouge">annotate_models</code> gem is a great tool for providing visibility into the
underlying structure of your database tables.</p>

<p>To that, I say “👍” !</p>

<p><em>However</em>, there are some downsides. They’re not necessarily malevolent or
problematic, but more speedbumps along the road of your development process.</p>

<p>To wit:</p>

<ol>
  <li>
    <p>It’s <em>noisy</em> at the top of important pieces of your code. Opening a file,
being met with a wall of comments, and spending time to get to the meat of a
class - it’s a speedbump. I ask you to ask yourself - how often do you
<em>really</em> need to reference the columns and structure of your table? I’d
guess “not so often”. It’s not <em>that</em> big a deal, but over time when your
models grow in size it’s not unfathomable that your editor buffer, on first
open, could be nothing but the contents from <code class="language-plaintext highlighter-rouge">annotate_models</code>.</p>

    <p>If you use vim and tpope’s vim-rails package you can get to your model’s
schema you can get to this information quickly already. <code class="language-plaintext highlighter-rouge">:Eschema
table_name</code> will take you right there. Example: <code class="language-plaintext highlighter-rouge">:Eschema users</code>, <code class="language-plaintext highlighter-rouge">:Eschema
posts</code>, etc.</p>

    <p>If you use Atom there are plugins that will assist with this -</p>

    <ul>
      <li><a href="https://github.com/juliogarciag/atom-rails-model-schema">atom-rails-model-schema</a></li>
      <li><a href="https://github.com/tomkadwill/atom-rails">atom-rails</a></li>
    </ul>
  </li>
  <li>
    <p>A migration should result in 2 files staged in Git. The new migration, and
an updated <code class="language-plaintext highlighter-rouge">schema.rb</code> or <code class="language-plaintext highlighter-rouge">structure.sql</code>. Instead, with <code class="language-plaintext highlighter-rouge">annotate_models</code>
you end up with those two, plus: modified model, factory, and spec – for
<em>each</em> model you update. To me that’s an unnecesary halo effect.</p>
  </li>
  <li>
    <p>Last but not least — and, arguably, most annoyingly — if you or
a teammate neglects to check those updates into git, the next time someone
runs a recently checked in migration, your local files change modifying
files that have nothing to do with the work you’re going to check in.</p>
  </li>
</ol>

<p>I will stop there with my humble request that you reconsider using
<code class="language-plaintext highlighter-rouge">annotate_models</code> and get into the meat of what I feel is a helpful tool for
your project(s). Enter <code class="language-plaintext highlighter-rouge">rails-erd</code> …</p>

<h2 id="rails-erd-entity-relationship-diagram">Rails ERD (Entity Relationship Diagram)</h2>

<p>What is an “Entity Relationship Diagram”? According to <a href="https://www.techopedia.com/definition/1200/entity-relationship-diagram-erd">techopedia</a>:</p>

<blockquote>
  <p>An entity-relationship diagram (ERD) is a data modeling technique that
graphically illustrates an information system’s entities and the
relationships between those entities.</p>
</blockquote>

<p><code class="language-plaintext highlighter-rouge">rails-erd</code> is a utility gem that will generate a PDF with a diagram of your
models, their columns, and the relationship between the models. It looks a
little something like:</p>

<p><img src="https://jekyll-shubox-io.s3.amazonaws.com/localhost-5001/4de972e6/544_rails-erd.png.webp" alt="rails-erd example" /></p>

<p>Per the directions on the project’s repo:</p>

<ol>
  <li>
    <p>Make sure graphviz is installed:</p>

    <ul>
      <li><code class="language-plaintext highlighter-rouge">brew install graphviz</code> 🍎</li>
      <li><code class="language-plaintext highlighter-rouge">sudo apt install graphviz</code> 🐧</li>
    </ul>
  </li>
  <li>
    <p>Add <code class="language-plaintext highlighter-rouge">gem "rails-erd", require: false, group: :development</code> to your
application’s Gemfile</p>
  </li>
  <li>
    <p>Run <code class="language-plaintext highlighter-rouge">bundle exec erd</code></p>
  </li>
</ol>

<p>You should have a PDF in your app root waiting to be opened now!</p>

<p>For extra credit you can set up your app to generate a new erd after you’ve run
new migrations.</p>

<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">bundle</span> <span class="nb">exec</span> <span class="n">rails</span> <span class="n">generate</span> <span class="n">erd</span><span class="ss">:install</span>
</code></pre></div></div>

<p>Your information now resides in that one pdf, unlike <code class="language-plaintext highlighter-rouge">annotate_models</code>. No
polution of all your files. One file that can be <code class="language-plaintext highlighter-rouge">gitignore</code>d if so desired!
Huzzah!</p>

<p>In the grand scheme of things, the gripes I present above are miniscule. I’d
absolutely concede that. It’s really not <em>that</em> big a deal. However, if you’re
on a project using <code class="language-plaintext highlighter-rouge">annotate_models</code> and you’re in the middle of a rebase
having to reconcile the merge conflicts from that gem across several files? I
hope you’ll remember this blog post.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Before we jump into rails-erd and how to integrate it into your workflow let’s talk about something adjacent to that.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/doc.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/doc.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">⚡Fast First Upload 🚀</title><link href="https://shubox.io/blog/2017/12/26/fast-first-upload/" rel="alternate" type="text/html" title="⚡Fast First Upload 🚀" /><published>2017-12-26T00:00:00+00:00</published><updated>2017-12-26T00:00:00+00:00</updated><id>https://shubox.io/blog/2017/12/26/fast-first-upload</id><content type="html" xml:base="https://shubox.io/blog/2017/12/26/fast-first-upload/"><![CDATA[<p><em>Setting up an S3 bucket before using Shubox - no longer required!</em></p>

<p><img src="https://shubox-codepen-io.s3.amazonaws.com/s-codepen-io/6ded4978/ghost-presenter-423726.jpg" alt="" />
<span class="bg-light-gray f7 db pa2 tr nt5 br3 br--bottom">Photo by <a href="https://unsplash.com/photos/VSwlS0PpWwc?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Ghost Presenter</a> on <a href="https://unsplash.com/?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span></p>

<p>As a developer who uses more than their fair share of services as a means to shave
time off from doing <em>task X</em> in order to get <em>feature Y</em> done, I know what it means
to get to a <em>*win*</em> as fast as possible. Push-button successes, right? The nice
touches that get you to “done”.</p>

<p>In light of that, Shubox has put together a “sandbox” bucket that can be used
<em>immediately</em> with your local development environment upon registering your
account. You no longer need to get your S3 bucket ready to go in order to test
the main Shubox functionality. As long as your local app/web server is running
on <code>localhost</code>/<code>127.0.0.1</code>/<code>0.0.0.0</code> then you’re
ready to get started.</p>

<p>All that’s left is to place our javascript library in your html, and hook Shubox into your element(s). Done.</p>

<p>For more information and instructions <a href="https://dashboard.shubox.io/sign_up">sign up</a>, or <a href="https://dashboard.shubox.io/sign_in">sign in</a>, visit the <a href="https://dashboard.shubox.io/domains/sandbox">sandbox page</a>, and get ‘ta uploadin’.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Setting up an S3 bucket before using Shubox - no longer required!]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/bucket.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/bucket.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">Going freemium</title><link href="https://shubox.io/blog/2017/12/17/shubox-going-freemium/" rel="alternate" type="text/html" title="Going freemium" /><published>2017-12-17T00:00:00+00:00</published><updated>2017-12-17T00:00:00+00:00</updated><id>https://shubox.io/blog/2017/12/17/shubox-going-freemium</id><content type="html" xml:base="https://shubox.io/blog/2017/12/17/shubox-going-freemium/"><![CDATA[<p>Happy holidays! Guess what? I have a gift for you (sort of). More on that
shortly. Before we get to that, though, let’s talk a little bit about needs and
motivation.</p>

<p><img src="https://shubox-codepen-io.s3.amazonaws.com/s-codepen-io/35678616/box-2953722_1280.jpg" alt="" /></p>

<p>It’s been several years since I wrote the first line of code for Shubox. From
that first hacking session until today my goal has always been to make
something that would be useful to me, and people like me — people who
work on the web. It’s always been, first and foremost, a scratch of my own
itch.  To that point I feel that I’ve succeeded. I use Shubox <em>all</em> the damn
time.</p>

<p>When I would work on client projects and the need to upload, resize, do much
with AWS S3, then I would suggest using Shubox and be done with it. It worked.
It saved me a tremendous amount of time. For those clients, it was also
ultimately <em>free</em>! Most of their use cases were esspecialy unique and I was
able to learn a lot about what my they needed vis a vis Shubox. The trade
— feedback for service.</p>

<p>It was an easy justification because most of these clients weren’t in need high
volume file or image uploading. As a result a conversation similar to “You
know, I have this service that you should pay $49 a month for. Yes, to upload a
few photos for the 3 or 4 products you add to your catalog every month” never
happened.</p>

<p>In a business’s lifecycle there are long stretches where needs evolve.
Coming out of the gates for an initial launch usually doesn’t <em>need</em> a
Kubernetes cluster, distributed messaging systems, hadoop, tensorflow, bloopity
bloop, whatever. A few dynos on Heroku, droplets on DigitalOcean, or VPS’s on
Linode should be ok. Exception handling, google analytics, Sendgrid, and maybe
a Squarespace account would round out a lot of the first absolute must-haves.</p>

<p>Most of those things have something in common. You can start out using them for
free. Of course some of the leading services people could reach for in Shubox’s
space also have free tiers.</p>

<p>I won’t belabor the point - Shubox <em>should</em> have a free tier. Shubox is something
that people with low usage, or are just starting out, <em>should</em> be able to use for
a while to see if it’s right for them. This much is true.</p>

<p>As a result, as of today, anyone who signs up for an account on Shubox will be
able <em>to use it free, forever</em>, or until they need more, bigger, better service.
For more information on the different tiers, visit <a href="/#pricing">the pricing section</a> on the
home page, or get in touch down below and to the right with the “Send a message”
button! I’ll be on the other end.</p>

<p>Merry Christmas! Happy Chanukah! Happy Kwanzaa! And a lovely Festivus for the
rest of us.</p>]]></content><author><name></name></author><summary type="html"><![CDATA[Happy holidays! Guess what? I have a gift for you (sort of). More on that shortly. Before we get to that, though, let’s talk a little bit about needs and motivation.]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://shubox.io/assets/blog/balloons.svg" /><media:content medium="image" url="https://shubox.io/assets/blog/balloons.svg" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>