LiteFarm's packages and deployments

This guide introduces the app structure and deployment environments to new LiteFarm contributors.

The LiteFarm monorepo defines two packages: webapp and api. As we will see, there is a kind of a third package, embedded within the api folder, that provides a certification export service, variously known as "exports", "scheduler", or "job scheduler".

The webapp package

This is the React-based frontend application. If you haven't seen React before we strongly recommend you go through the React Documentation and the tutorial. They are both extremely helpful getting started sources.

We use Redux for state management. If you haven't heard about Redux before, we strongly recommend you study the materials on their site. Or if you are more of a visual learner, Redux creator Dan Abramov has a free tutorial.

Conceptually, we divide the frontend into three categories.

“Pure” components are found in packages/webapp/src/components. These simple React components hold no logic and simply control the layout and rendering of their props.

“Container” components, sometimes called “smart” components, are found in packages/webapp/src/containers. These complex React components hold logic, connect to the Redux store, dispatch actions, and render the pure components with the required props. Within the container folders we will also define sagas, actions and reducers in case there are any of those that relate to that particular component logic.

Finally we have stories, which are tests of our containers that are rendered through Storybook. A story can import both pure and container components. In the case of testing isolated views, the most likely scenario is importing pure components. When rendering complete flows, however, you might use container components to test user interactions with the store or to test changes on events.

To do that, create a new folder and corresponding file that ends in ".stories.js" in the stories folder, and import the pure component in that file.

The api package

The API uses Node along with Express. Under packages/api/src there are folders for routes, middleware, controllers, and models.

Express defines the approach used for routes and middleware. Our routes and middleware generally follow RESTful API conventions for URLs and response codes.

Controllers and models are concepts borrowed from the MVC architecture pattern.

Controllers act as a kind of translator between the model(s) and the user interface. (The V in MVC is for View, an older approach to UI issues that React handles for us.) In general terms, a controller accepts input from the UI, converts it to commands to the model(s), transforms the results and responds to the UI. In terms specific to LiteFarm, a controller is a group of Express route handler functions that handle all routes related to a type of entity, such as farms. Via Express, the controller receives requests from the frontend in HTTP, following REST conventions. The farm controller makes appropriate calls to the farm model (and perhaps other models) to retrieve and/or modify database contents. The controller then sends the results back to the frontend via Express, usually in HTTP/JSON format.

A model is a dynamic data structure that directly manages the data, logic and rules of the application. We use ObjectionJS to define the models. Objection builds on Knex, a query builder for multiple SQL database platforms. We use the PostgreSQL database management system.

The exports “package”

The file packages/api/src/jobs/index.js is the entry point for a Node service that is run separately, as if it were a third package. This service monitors Redis-based work queues to receive and process requests for exports of certification information.

Deployments

Each of the three packages is deployed to the LiteFarm production environment, and to a pre-production environment generally known as “beta” (though it is not used for traditional beta testing).

These deployments share some components.

The production environment consists of:

  • litefarmapp, a Digital Ocean Droplet that:

    • runs the webapp package (behind an Nginx reverse proxy) in litefarm-web, a Docker container assigned the hostname app.litefarm.org

    • runs the api package in litefarm-api, a Docker container assigned the hostname api.app.litefarm.org

    • runs PostgreSQL in a Docker container named litefarm-db

    • provides file storage for the database contents and backups

  • litefarm-imaginary, a Digital Ocean Droplet that:

    • provides file storage for ? images

    • runs the “exports package” jobs scheduler Node service

    • runs the Redis-based work queues used by the API server to submit export jobs to the scheduler

    • runs the image manipulation microservice imaginary in a Docker container

    • runs an Nginx web server, hostname image.litefarm.org, that reverse proxies access to a Docker container running the image manipulation microservice imaginary

  • Object storage “buckets” (Digital Ocean Spaces) that store images and documents uploaded by users, as well as certification exports for users to download.

 

The pre-production environment consists of:

  • liteformbeta, a Droplet that duplicates the services on litefarmapp, with hostnames beta.litefarm.org and api.beta.litefarm.org

  • export-beta, a Droplet that duplicates the services of on litefarm-imaginary, with one exception

  • Buckets that duplicate those in the production environment.

 

Individual developers run local instances of the the litefarm-web, litefarm-api, and litefarm-db Docker containers. There are buckets dedicated to object storage for development setups.

 

All deployments-- production, pre-production, and individual developers-- use the single instance of the imaginary microservice on image.litefarm.org