Please refer to the LICENSE file for important Copyright information.
This README has sections for each of the potential roles of the person reading it. So depending on your interests in this site, simply locate the appropriate section(s) below for a targeted introduction along with links to further information.
What's here? This repo contains the source code and data for a Data Collection System, specifically a Performance Measurement (PM) System. What distinguishes this PM implementation is the fact that its data is Git-based.
It's very common for nonprofits and industry groups to develop and deploy PM systems to track and publish the success of their mission and activities, and to promote goodwill, accountability, process improvements, and better outcomes.
This project is about the U.S. freight rail industry. But even if that industry doesn't interest you, here are some of the key "selling points" and characteristics of this solution from a technical standpoint that should help you to decide if this codebase might work well for your use-case:
- Open, MIT-licensed source code
- Developed using a modern technology stack with plenty of software industry activity and support as of 2018
- Designed for zero operational cost in terms of infrastructure (deploy and operate on free cloud services... including a Read/Write REST API)
- Focused exclusively on the collection and publication of quantitative measures (numbers). In other words, this is the complete opposite of something like SurveyMonkey, which focuses largely on surveys with qualitative measures.
Details for Devs
Thanks for taking a detailed look at this Web App developed with Vue.js, Nuxt, Vuetify, and Chart.js!
Please note that this Web App is developed using Visual Studio Code (VSCode) and Chrome on Windows. The NPM scripts have only been tested in the Windows environment.
There are three prerequisites for running and working with this codebase:
- Node.js v10.13.0 or greater (LTS version as of Nov 2018)
- Yarn v1.10.x or greater
- Hugo v0.51 or greater
And of course, VSCode is highly recommended. So before proceeding be sure to install those pieces if you don't already have them.
This repo is organized as a "monorepo" containing multiple private sub-packages. But the complexity here doesn't rise to the point where something like Lerna is needed to help manage things. So to get started, just:
- Clone this repo
- Open a command prompt, and
- Change directory (cd) into your local clone folder and run:
yarn install-all
Note that this is not the typical
npm install
oryarn
command to get started. Instead, we wrap multiple invocations ofyarn
(npm install
) in aninstall-all
script (in lieu of doing something likelerna bootstrap
).
Then, launch VSCode:
code .
And finally in VSCode:
-
Accept the offer from VSCode to install the solution's recommended extensions
-
From the
Tasks
menu selectRun Task...
and launch theall:dev
task. This will start:-
The local Nuxt server for the front-end
-
The Hugo server for the API back-end, and
-
An instance of
live-server
to run the Admin site locally
-
The app should now be running on your local machine here: http://localhost:3000. The API will be running locally on port 1313. And the Admin site will be running on port 8080.
Note that in order to configure the app to use your local API server, you may need to change the API_HOST
setting in app/app.config.js
.
To run the Admin site locally you may wish to change the backend configuration in admin/config.yml
from the git-gateway
microservice to the local test-repo
.
The test-repo
setting simply tells Netlify CMS to work locally in memory in your browser instead of actually hitting GitHub. See here for more information.
Here's a fragment from the config.yml
file tweaked for local development. Basically, comment-out git-gateway
and uncomment test-repo
and login: false
.
backend:
# name: git-gateway
name: test-repo
login: false
You'll also want to tweak the RBAC JavaScript code to fake a user login. So in admin/rrpm-netlify-rbac.js
:
-
Change the constant
FAKE_LOGIN
totrue
const FAKE_LOGIN = true; // Must be set to false for production
-
Change the contents of the
loginFakeUser
function based on the user role that you'd like to testfunction loginFakeUser() { // Tweak fake user role here }
The Admin site's package.json
file lists a custom build of Netlify CMS as a dependency:
"dependencies": {
"@rrpm/netlify-cms": "^2.2.37"
}
To make changes to this custom Netlify CMS NPM package, see the details here.
And then to update the reference to the package and properly install the updated JavaScript file in the Admin site:
-
From a command prompt, change your current working directory to the
/admin
folder of this repo -
Run these commands:
yarn install yarn build
Chrome is highly recommended during development. In Chrome, install:
-
Allow-Control-Allow-Origin: * extension.
- Without this extension, when running the sites locally you may have problems accessing the API from the front-end due to CORS. The local in-memory API server (Hugo) doesn't support custom HTTP response headers. But for deployment to Netlify, we specify the necessary header configuration.
As a web developer I always find it helpful to know how a project got started. So if you're interested in following the steps that were originally taken to create this solution from scratch, here are some of the details.
For the API piece it's about getting Hugo setup for serving primarily JSON instead of HTML.
Details
- From the root folder, I ran
hugo new site api
, which created theapi
subfolder - In the
api
folder- Cleaned a bit, removing Hugo stuff we won't need:
archetypes
,themes
, etc. - Tweaked Hugo's
config.toml
to eliminate RSS and sitemap stuff - Ran
npm init -y
to create an initialpackage.json
so we can use NPM Scripts to control how Hugo does things - NPM Scripts configured to support commands:
npm run dev
oryarn dev
to run a local Hugo development server with live reloadnpm run build
oryarn build
to do a quick, incremental build to./dist
npm run build-full
oryarn build-full
to do a full build, cleaning the./dist
folder
- Cleaned a bit, removing Hugo stuff we won't need:
- Logged-in to app.netlify.com with my GitHub credentials and clicked "New site from Git"
- Under "Continuous Deployment" selected GitHub and then clicked "Authorize netlify"
- Under "Create a new site" selected this repo
- Configured
master
branch to deploy, set "Build command" tocd api && npm install && npm run build
and "Publish directory" toapi/dist
- Clicked "Deploy site"
- Configured subdomain so that the site is hosted under Netlify at: https://api.rrpm.run/
- Please see NOTE in
netlify.toml
config file RE: setup as it is unique to this monorepo approach
For the frontend App I used create-nuxt-app.
Details
- From this project's root folder, I ran
yarn create nuxt-app app
and entered/selected the following options- Project name:
aar-rpm-app
- Project description: RPM App
- Use a custom server framework: none
- Use a custom UI framework: vuetify
- Choose rendering mode: Single Page App
- Use axios module: yes
- Use eslint: yes
- Choose a package manager: npm
- Project name:
create-nuxt-app
initializes git in theapp
folder created. We don't need separate git tracking for this subfolder, so- Changed directory into app:
cd app
- Removed
.git
folder:rd /s /q .git
(on Windows)
- Changed directory into app:
create-nuxt-app
had some outdated dependencies listed in the generatedpackage.json
, so updated to"nuxt": "^1.4.1"
"vuetify": "^1.0.19"
"@nuxtjs/axios": "^5.3.1"
- Ran
npm install
- Changed the default app component style from
dark
tolight
inapp\layouts\default.vue
and the default progress bar color inapp\nuxt.config.js
- Logged-in to app.netlify.com with my GitHub credentials and clicked "New site from Git"
- Under "Continuous Deployment" selected GitHub and then clicked "Authorize netlify"
- Under "Create a new site" selected this repo
- Configured
master
branch to deploy, set "Build command" tocd app && npm install && npm run generate
and "Publish directory" toapp/dist
- Clicked "Deploy site"
- Configured subdomain so that site is hosted under Netlify at: https://app.rrpm.run/
The Admin piece is really just Netlify CMS and its configuration file. You can get started with Netlify CMS in several ways, and they are all nicely documented by Netlify.
Details for Architects
Thanks for your interest in the architecture of this Performance Measurement (PM) System.
The key architectural concept for this solution is:
Perform all server-side logic at build-time, not at run-time!
In other words, the approach here is to eliminate all run-time server processing found in the heavier, monolithic web solution stacks/frameworks such as Java Spring, ASP.NET, Ruby on Rails, and Laravel.
Those solutions typically build each page from scratch every time it is requested by a browser. And they typically do this by coordinating across multiple layers/servers such as load balancers, web servers, caching layers, data access layers, and databases.
In contrast this solution pre-builds responses using a free build server and then simply serves the resulting static sites from a CDN.
Changes to site content automatically kick-off a fresh build, which typically completes in milliseconds.
Any run-time logic required for things such as authentication is handled by cloud microservices whose uptime is managed by others (i.e., using a serverless approach).
Clearly the requirements of some web apps simply can't be adapted to this approach. For example, when website content is changing more frequently than say, by the minute, this approach likely wouldn't work.
This system uses a Single-Page Application (SPA) architecture with:
-
A Vue.js JavaScript Framework front-end using
-
The Nuxt.js application framework for its
-
Basic SPA application organization and convention-based directory structure
-
Routing
-
Layouts/Pages/Components model for composing views/pages
-
Integration with the Vuex state management library
-
Webpack build with code splitting, etc.
-
-
The Vuetify component framework for
-
A Google Material Design-based visual system, and
-
A ready-made, mature, and well-documented set of Vue.js components such as Toolbars, Menus, Buttons, Tables, etc.
-
-
Chart.js for graphs
-
-
A serverless/microservices back-end comprised of:
-
A data-reading REST API based on
-
A JAMstack approach (see also here) for build-time static generation of JSON responses
-
Using the Hugo static content generator, and
-
Hosted on the Netlify static CDN
-
-
A data-writing microservice with stateless JWT-based auth using the Netlify Identity service that
-
Proxies and gateways writes to a GitHub repository of flat files, and
-
Re-builds the data-reading REST API via a Netlify build trigger on the GitHub repo
-
-
-
A data collection/administration portal
-
Based on a custom build (and published NPM package) of the React-based, Git-backed Netlify CMS open source content management system
-
Which is also a SPA hosted on the Netlify static CDN
-
Also using the Netlify Identity service for auth
-
The three main bullets above are referred to in the solution architecture as the App, the API, and the Admin site respectively. And there are top-level folders in this source code repo that correspond to these pieces of the solution.
This system operated for over a decade on a more traditional/legacy stack before being re-imagined in the modern stack described above.
See here for a helpful side-by-side comparison between old and new.