React apps in subdirectories that use React Router

If you’ve ever deployed your new React app to a subfolder on your server and you’re using React Router you might notice that React Router starts getting all funky and truncates the subfolder name.  This is the expected behavior, albeit something easy to overlook when deploying to a subfolder.  The good news is that there is a pretty straightforward solution: just add a basepath  to your Router and specify the folder name.

Check out the documentation.

<Router basename="/some/sub/directory/">
  // Other routes here
</Router>

For example, I deploy most of my playground apps to apps.bioramp.com, to deploy the Auto9 app I use a subfolder and the resulting URL is http://apps.bioramp.com/auto9

This is what my Router looks like for that app (keep in mind I import my routes from an external file).

// ... other imports
import { routes } from "./config/routes";

class Auto9 extends React.Component {
  render() {
    return (
      <Router basename="/auto9">
        <div>
            {routes.map((route, index) => (
              <Route
                key={index}
                path={route.path}
                exact={route.exact}
                component={route.component}
              />
            ))}
        </div>
      </Router>
    );
  }
}

Also, keep in the mind that you should have a “homepage” node in your package.json before you a do a build.

Using SMTP relay via Office365 in Rails apps

First you’ll need to add your production box IP address to Exchange Connector

Example URL: https://outlook.office365.com/ecp/?rfr=Admin_o365&exsvurl=1&Realm=yourdomain.com

Then add the following to application production.rb

config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true 
config.action_mailer.smtp_settings = {         
  :address => "yourdomain-com.mail.protection.outlook.com",
  :from => 'somesendername@yourdomain.com',
  :port => 25,
  :domain => "yourdomain.com",
  :enable_starttls_auto => true    
}

and boom! your Rails app will start sending emails through Office 365.

Nginx setup with SSL on Ruby app running Passenger

Once you’ve got your certs all setup you can add an entry to /etc/nginx/sites-available and then symlink it to /etc/nginx/site-enabled

An example snippet below:

server {
        listen 443;
        ssl on;
        ssl_certificate         /home/deploy/.ssl/mydomain_combined.crt;
        ssl_certificate_key     /home/deploy/.ssl/mydomain.key;

        server_name myawesomedomain.com;
        passenger_enabled on;
        rails_env    production;
        root         /home/deploy/apps/my-app/current/public;
        passenger_ruby /home/deploy/.rvm/gems/ruby-2.2.2@my-app/wrappers/ru$

        access_log /home/deploy/apps/my-app/current/log/access.log;
        error_log /home/deploy/apps/my-app/current/log/error.log;

        # redirect server error pages to the static page /50x$
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
}

 

Typed by a human or scanned with barcode reader?

Simple check to determine the speed of user input into a form element. This was to prevent users from typing in barcodes that were required to be entered using a barcode scanner.

HTML:

<!DOCTYPE html>
<html>

<head lang="en">
    <link type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
    <script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
    <script src="check-input-speed.js"></script>
    <meta charset="UTF-8">
    <title>Monitor Form Input Speed</title>
</head>

<body>
    <div class="row">
        <div class="col-md-2"></div>
        <div class="col-md-8">
            <h2>Human or Barcode Scanner?</h2>
            <form>
                <input type="text" id="input_to_check" class="form-control" />
                <div class="row">
                    <div class="col-md-12">
                        <span id="CPM">0</span>
                    </div>
                </div>
            </form>
            <div id="analysis">
                <div class="alert alert-danger" id="human">
                    HUMAN!
                </div>
                <div class="alert alert-success" id="barcode_scanner">
                    BARCODE SCANNER!
                </div>
            </div>
        </div>
    </div>
</body>

</html>

 

JavaScript:

$(function() {
  $("#human,#barcode_scanner").hide();
  $("#input_to_check")
    .keyup(checkSpeed)
    .focus();
});

var iLastTime = 0;
var iTime = 0;
var iTotal = 0;
var iKeys = 0;

function checkSpeed() {
  iTime = new Date().getTime();
  var cpm,
    wpm = 0;
  if (iLastTime != 0) {
    iKeys++;
    iTotal += iTime - iLastTime;

    cpm = Math.round(iKeys / iTotal * 6000, 2);
    $("#CPM").html("Characters per min: " + cpm);

    if (cpm < 300) {
      $("#human").show();
      $("#barcode_scanner").hide();
    } else {
      $("#human").hide();
      $("#barcode_scanner").show();
    }
  }

  iLastTime = iTime;
}

 

 

CSS Media Queries skeleton for mobile devices

/* #Media Queries
================================================== */

/* Smaller than standard 960 (devices and browsers) */
@media only screen and (max-width: 959px) {}

/* Tablet Portrait size to standard 960 (devices and browsers) */
@media only screen and (min-width: 768px) and (max-width: 959px) {}

/* All Mobile Sizes (devices and browser) */
@media only screen and (max-width: 767px) {}

/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
@media only screen and (min-width: 480px) and (max-width: 767px) {}

/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
@media only screen and (max-width: 479px) {}