Reed Water is an IOT device that manages property water levels. We were tasked in creating the frontend of the user journey for potential clients. The website required 3 main features; Subscription Billing, eCommerce & Resource database.
The client's main request was being able to manage content on their own. We wanted to stay within reasonable budget, so instead of creating our own CMS, we opted for Strapi. Flexibility was important, and staying within the Node ecosystem was preference.
The clients needed a subscription model to accommodate purchasing and continued use of Reed products and services. Tiers for varied levels of features could be modified by the client, in the Strapi CMS.
We connected our front-end solution to authorize.net, which then sends a notification to the hardware that the customer owns. The external payment provider handles failed payment, or cancelation from their API.
With eComm solutions being few and in-between, Shopify is the usual go-to. The issue is we needed to create a custom solution that works within the client's current technical ecosystem.
Orders are sent to the Srapi CMS for the client to view & manage. Payment is collected from authorize.net, which first verifies the order before placing it in the shipping queue.
Introducing hardware and software as new as this, having docs, or in this case, Resources - is vital. We created a visual database for resources with the ability for Reed to upload PDF files, images, text, what comes in-a-box, and associate it with a product on the Strapi back-end.
Managing frontend has become a lot easier the past few years. Our main tool of choice when dealing with frontend work, is React. This choice stems from the fact that we enjoy writing Javascript, instead of logic in data-attribute tags. Of course, being personal preference.
We wanted to render on a server, while still keeping components modular. Again, instead of doing this from scratch, our favourite solution is Next.js. They take care of rendering React on the server, which really benefits in speed & SEO advantages.
Authentication & Next.js was pretty complicated originally. Eventually Zeit released a way to customize each page initialization (https://nextjs.org/docs/#custom-app). We check for a token stored in the users localStorage on every page load, using a custom HOC (higher order component) that wraps around each page.
For this clients scenario, we had to tap in to an external auth system. The one that controls the actual hardware. Fortunately, the engineers on the other team provided an OpenId solution, where users can login & register on our frontend app, while the external backend handles supplying the token.
Last but not least, was handling deployment. DevOps plays a crucial role in the Reed development ecosystem. Handling deployment for multiple moving parts became a challenge. Docker to the rescue, we containerized the whole project. We separated Strapi, the Mongo database, a web server named Caddy & finally the Next.JS app.
Below you can see the Docker Script on how we orchestrated Reeds' DevOps solution
version: '3'
services:
caddy:
image: registry.gitlab.com/creatorsneverdie/reed/caddy:latest
restart: unless-stopped
ports:
- 443:443
- 8443:8443
- 80:80
volumes:
- caddy-certs:/root/.caddy
depends_on:
- api
- web
logging:
options:
max-size: 50m
environment:
ACME_AGREE: "true"
HOST: reedwater.io
WWW: "true"
web:
image: registry.gitlab.com/creatorsneverdie/reed/frontend:latest
ports:
- 3000:3000
depends_on:
- api
restart: unless-stopped
logging:
options:
max-size: 50m
environment:
OIDC_AUTHORITY: ****
OIDC_CLIENTID: ****
OIDC_REDIRECT: ****
OIDC_REDIRECT_SILENT: ***
OIDC_POST_LOGOUT: ***
MONGOURL:mongodb://@mongo/strapi
AUTHORIZED_NET_API_LOGIN : ****
AUTHORIZED_NET_TRANSACTION_KEY : ****
API_ENDPOINT: ****
API_ENDPOINT_SERVER: ****
API_ENDPOINT_PORTAL: ****
SENDGRID_API_KEY: ****
MAIL_SENDER: ****
api:
image: registry.gitlab.com/creatorsneverdie/reed/backend:latest
ports:
- 1337:1337
environment:
APP_NAME: api
DATABASE_CLIENT: mongo
DATABASE_HOST: mongo
DATABASE_PORT:27107
DATABASE_NAME: ****
HOST: ****
volumes:
- api-uploads:/usr/src/api/api/public/uploads
restart: unless-stopped
logging:
options:
max-size: 50m
mongo:
image: mongo:3.6.6
restart: unless-stopped
tmpfs:
- /var/lib/mongodb
volumes:
- mongo-data:/data/db
mongo-express:
image: mongo-express
restart: always
ports:
- 8081:8081
environment:
ME_CONFIG_BASICAUTH_USERNAME: ****
ME_CONFIG_BASICAUTH_PASSWORD: ****
volumes:
api-uploads:
driver: local
mongo-data:
driver: local
caddy-certs:
driver: local
Part of any great DevOps experience, requires some sort of CI (continuous integration). We host our projects on GitLab, who offer an amazing free solution. We wrote a .gitlab-ci file that pulled the docker-compose file above. Depending on which branch you pushed to, it would deploy to either the production or staging server. This allows for the client to watch as we iterate, without messing up the production server.
All-in-all, this was a great project for us to test different technologies. This really opened our eyes to the gap in finding a headless CMS that does exactly what we wanted. Maybe in the future, this can be the next open source project we tackle.