vrbtm.co development stream | Week I

Nick Dandakis
VRBTM
Published in
8 min readOct 2, 2016

Meteor, React, routing, style patterns, file picker and architecture.

Not sure what this is, start here with our README.

Exciting times. Starting a new project always has a lot of variables. Architecture, stack, deployment, deliverables and requirements. Good thing Wes fuckin’ Snipes has his shit together and has removed as many unknowns as possible for Verbatim.

Deliverables? A functional MVP of Verbatim — a content approval and versioning system, outlined in good detail in a couple documents and an Invision prototype.

Requirements? Described in a couple documents. No clear list of itemized features, but it’s better than most of what I’ve had to work with before.

Architecture? Up for me to figure out on a micro level, but on a macro level we have three major components. Web application, file management and email notifications. Wes (correctly) suggested using Filestack for content management and Sendgrid for email notifications.

Stack? Completely up for me to figure out. Going to start off as a Meteor project, since it’s incredibly easy to get up and running. Our goal here is an MVP, and we’re going to get there faster if I use a framework I’m familiar with.

Deployment? There’s several ways of deploying a Meteor application. Galaxy, using mup or doing it yourself. I’m probably going to end up going the mup route for this one, since we’d like to keep costs down initially.

Cloned Wes’s empty repo called vbmvp. I’d prefer if it was called vrbtm.co, but that can change later. I already have meteor installed on my computer, so all I had to do was run meteor create . from within the vbmvp/ directory.

meteor run

…and we’ve got a working Meteor application!

initialized_meteor_app.RAW

Now, there are several front-end engines out there that integrate nicely with Meteor. Meteor’s Blaze, Google’s Angular and Facebook’s React. I’ve made a couple projects with Blaze and although I’m fond of it, React has certain patterns that make it much more robust. So, I’m removing Blaze and plugging in React instead.

meteor remove blaze-html-templates
meteor npm install --save react react-dom

Now, I’m not sure if blaze-html-templates needs to be removed, but I’m doing it anyway to keep things light. Meteor has a fragmented package manager at the moment, so you have Meteor packages and npm packages. Either can be used, but I’m going to try to stick to npm because it seems like the ecosystem is moving that way.

Our application is now blank, because the previous files used Blaze and not React. That’s cool, because I was going to delete all the initialized files and start rolling my own. Created the root Application component, made a main.jsx and main.html file, rendering Application component on startup in main.jsx fails. Looks like the HTML in main.html isn’t coming through.. Tried renaming the file and that didn’t work. Turns out, you need the blaze-html-templates Meteor package to compile *.html files. Added that back in.

Installed normalize.css and imported it in Application.jsx. Next up, a router. Normally, you could get away with setting up routing later on, but I want to get all of the setup items out of the way first before starting on layout and functionality. React has a react-router npm package and I’m following a tutorial on how to use it. Basically, your entry point becomes your Router and then you declare routes that correspond to different components.

Next up, some base styling and structure setup for SCSS. What’s wild is that Meteor still hasn’t brought SCSS support into core, so you need to install a package for it.

meteor add fourseven:scss

SCSS is a styling pre-processor. We now have styling post-processors, which I’ll also setup to handle prefixing of all the bullshit browser-specific styling rules.

meteor remove standard-minifier-css
meteor add juliancwirko:postcss
meteor npm install --save-dev autoprefixer

You can then define your supported browser range in package.json. This didn’t work though. Turns out, you can’t get postcss to work on any styling that’s imported with ES6 within a JS (or JSX) file. I was wondering why example applications were importing all their styles globally in client/main.scss

Man, the Meteor Guide is so good.

React, routing, styling all set up. Next is putting an actual frontend together. This is all very straightforward. Make a bunch of routes, make a bunch of React components and hook them together.

import React from 'react';
import { Meteor } from 'meteor/meteor';
import { render } from 'react-dom';
import { Router, Route, IndexRoute, browserHistory } from 'react-router';

import Application from '/imports/ui/Application.jsx';
import Index from '/imports/ui/pages/Index.jsx';
import About from '/imports/ui/pages/About.jsx';
import Pricing from '/imports/ui/pages/Pricing.jsx';
import TermsAndConditions from '/imports/ui/pages/TermsAndConditions.jsx';
import Privacy from '/imports/ui/pages/Privacy.jsx';
import Contact from '/imports/ui/pages/Contact.jsx';
import NotFound from '/imports/ui/pages/NotFound.jsx';

Meteor.startup(() => {
render(
<Router history={ browserHistory }>
<Route path="/" component={ Application } >
<IndexRoute component={ Index } />
<Route path="/about" component={ About } />
<Route path="/pricing" component={ Pricing } />
<Route path="/terms-and-conditions" component={ TermsAndConditions } />
<Route path="/privacy" component={ Privacy } />
<Route path="/contact" component={ Contact } />
<Route path="*" component={ NotFound } />
</Route>
</Router>, document.getElementById('render-target'));
});
thecraft.bitmap
routesman.wow

Next up, some more content and very light styling.

homebefore.jpeg
pricingbefore.jpeg

Sticky fucking footer. Forget normalize.css

Lots of menial styling later and…

homeafter.png
pricingafter.png
upgradenew.png

Next up, some polish on form elements and buttons. Inspiration below:

muchwow.mp4
colorsmaybe.???
suchbutton.mp4

We need styles for:

  • Form elements (text inputs, text areas, dropdowns, checkboxes, radio buttons)
  • Buttons (w/ an alternative)
  • Links and call to action links

Each one of the above needs to have an active/hover state. Which turns this into almost ten pieces that need to be styled. The inspiration above looks pretty busy, so it might be a good idea to toggle between animatable and static. An aspiring UX designer just told me that you probably don’t want each form element to heavily animate in a form with over a handful of inputs.

Input.jsx
buttonz.png

Time to implement FileStack (previously known as FilePicker). Their npm package is still called filepicker-js tho. I’ll keep it consistent with the package and call the component FilePicker.jsx.

npm install filepicker-js --save

Integrating Filepicker is also pretty straightforward. Mostly due to great docs. There’s an API key that needs to get set to the filepicker object before using any of its methods. Then there’s a method for uploading content called filepicker.pick. You can pass in several options for what the allowed content is, size, etc. Then define callbacks for success, error and progress. I’m setting the API key with Meteor’s settings.json file (updated the README.md to say so). Then it’s a matter of some React state usage to inform the UI of changes and a couple of hidden input tags to allow forms to see the uploaded file.

import React, { Component } from 'react';
import { Meteor } from 'meteor/meteor';
import filepicker from 'filepicker-js';
export default class FilePicker extends Component {
constructor(props) {
super(props);

filepicker.setKey(Meteor.settings.public.filestack);
this.state = {
filename: undefined,
file: undefined
}
}
handleOnClick(event) {
filepicker.pick({
mimetype: '*/*',
maxSize: 2*1024*1024*1024,
services: [
'COMPUTER',
'VIDEO',
'AUDIO',
'WEBCAM',
'URL',
'FTP',
'GOOGLE_DRIVE',
'DROPBOX',
'BOX',
'GMAIL',
'IMGUR',
'IMAGE_SEARCH',
'EVERNOTE',
'FACEBOOK',
'FLICKR',
'GITHUB',
'SKYDRIVE',
'PICASA',
'INSTAGRAM',
'ALFRESCO',
'CUSTOMSOURCE',
'CLOUDDRIVE',
'CLOUDAPP',
'CONVERT'
],
}, (blob) => {
this.setState({
filename: blob.filename,
file: blob.url
});
}, (error) => {
console.dir(error);
}, (progress) => {
console.log(progress);
}
);
}
render() {
return (
<span className="file-picker">
<input type="hidden" name="filename" value={ this.state.filename } />
<input type="hidden" name="file" value={ this.state.file } />
<button
className="alternative"
onClick={ this.handleOnClick.bind(this) }>
{ this.state.filename ?
this.state.filename
:
'Upload file'
}
</button>
</span>
);
}
}
workworkworkworkwork.flac

Spent a little bit of time putting together some validations for the form. I’m using input tag types to avoid having to check for syntactically correct emails. Still have to check if a file was picked or if they put in emails in the first place. Not sure if the pattern I’m using is correct, but gotta stop wasting time on this.

redrednotgood.mp3

You’ll notice that the “Provide a file” error doesn’t go away when a file is uploaded. That’s because the FilePicker component isn’t informing the parent form that it’s changed to update its validations. This is something that I’d probably have to fix with Redux, and I’d like to get other things out of the way first.

Alright, alright, alright. Time for some motherfucking backend work yabish. We need to store content in a database to feed content routes and fire off notifications.

Created a Meteor Collection called Content and defined it at /imports/api/content.js. Set up a React route that points any URLs at /ntent/whatever to a ContentDetail component that I defined at /imports/ui/pages/ContentDetail.jsx. Why /ntent? Because http://vrbtm.co/ntent/motherfucker.

Needed to modify the typical structure of a React component for ContentDetail.jsx to use Meteor’s reactive data source. Basically, you create a container that injects props based on any Meteor Collection or Tracker based data sources you like. Feed in the params in the URL from the router and you got a page that renders content based on the URL.

flowslikewaterman.mp4

This page obviously needs a lot of TLC. Styling, mimetype detection with conditional rendering for different content types, fallback if content can’t be rendered, approval mechanism, download functionality and loading screen.

Also still need to code email notifications, a couple more screens, harden Meteor and sort out deployment. Once that’s done, we’ve got ourselves a working prototype.

Fuck me. I forgot to install WakaTime on my personal computer before starting work on this.

Guesstimating that I put in around six hours of work this week.

Read the other half of this week with Wes’ Kicking off VERBATIM | Week I.

vrbtm.co development stream | Week II

We’d love to hear from you…
Get in touch at Founders@vrbtm.co, talk with us on twitter @vrbtm.co, and read our story on medium.

Wes Jones is on Twitter @WesJonesCo
Nick Dandakis is on Twitter @Dandakis

Join our email list for Beta access.

--

--

Nick Dandakis
VRBTM
Editor for

These hands make digital projects finish. Previously @Token_AI, @bigspaceship.