Architecture
Introduction
CaterCow's architecture is built upon a robust and well-maintained collection of services designed for stability, maintainability, and efficient development. The ecosystem is primarily divided into a Ruby on Rails backend, several specialized Vue.js frontend applications, and a React Native mobile application for event attendees. This document outlines the structure of these components.
High-Level Architecture Overview
This diagram illustrates the primary components of the CaterCow platform and how they interact. Users interface with various frontend applications, which all communicate with a central backend API.
Backend: Ruby on Rails API and Admin Interface
The core of CaterCow's platform is a Ruby on Rails 7.1 application. It serves as the central API for all customer and restaurant interactions and includes a comprehensive, full-stack admin interface for internal management of the marketplace. The only running processes for this Rails application are the Puma web server and a Sidekiq job server.
Key Architectural Decisions & Features:
- Framework Choice (Rails): Rails was chosen for its ability to facilitate rapid development and its excellent organization of complex business logic. While the application does not face the same scaling challenges as some larger platforms, it contains a significant amount of intricate business rules. Rails' conventions and extensive ecosystem allow for new features to be implemented quickly and maintained effectively.
- Database: A MySQL database serves as the central data store for the entire application.
- Application & Web Servers: The application runs on the Puma web server, which is horizontally scaled using Kubernetes pods to handle incoming API and web traffic.
- Background Processing: Asynchronous tasks and scheduled jobs are managed by a Sidekiq job server. This service can only be vertically scaled, running as a single replica (
replicas: 1) to prevent duplicate cron job scheduling. - Caching: Two separate Redis instances are utilized: one dedicated to caching data for performance and one to manage the Sidekiq job queue.
- Admin Interface: The admin panel is built using the Trestle admin framework, which provides a balance between rapid UI generation and the flexibility to create custom, organized interfaces. For more dynamic and interactive features within the admin panel, Vue 3 components are integrated directly into the Rails views.
- PDF Generation: To enhance security and isolate dependencies, PDF generation is handled by a
wkhtmltopdfservice running in a sidecar container alongside theapiandsidekiqdeployments. This service shares anemptyDirvolume namedwicked-pdfto pass files between the Rails application and the PDF generator.
Backend Pod Architecture
The diagram below shows how the api and sidekiq Kubernetes deployments are structured as pods containing the main application container and a wkhtmltopdf sidecar. They share a volume for file exchange during PDF generation.
- Testing: The backend has an extensive test suite that covers all API endpoints and critical services, ensuring code reliability and stability.
Frontend: Vue.js Applications
The user-facing frontend is decoupled from the backend and composed of several distinct Vue.js applications. This separation allows for focused development and optimized user experiences for different segments of the platform. Vue.js was selected for its gentle learning curve, making it accessible for backend developers to contribute, and its component-based architecture is intuitive for developers coming from other frameworks like React.
Splitting this out into JavaScript frontends and the API allows us to easily hire devs on either side without requiring people to have full knowledge across the stack. Breaking the frontend into apps also makes the separation clearer as the team continues to grow.
When a component or asset is likely shared among the 3 apps, they will go into a shared namespace which can be freely imported by any of the apps.
By the way, no TypeScript afficionados on our team, but we're not against it.
- Nuxt 3 "Marketing" App (
nuxt3-marketing): This is a modern, server-rendered application built with Nuxt 3. Its primary purpose is to serve SEO-friendly marketing pages. It integrates with a Ghost blog and the Storyblok CMS to pull in dynamic content, in addition to serving handwritten marketing pages. This corresponds to thenuxt3-marketingdeployment. - Nuxt 2 "Public/Orderer" App (
nuxt-public): This application manages the core customer experience. It includes the search and discovery UI, individual package pages, the checkout process, and the entire customer dashboard for managing orders and account details. This corresponds to thenuxt-publicdeployment. - Nuxt 2 "Caterer" App (
nuxt-caterer): This app provides a dedicated dashboard for restaurant partners and caterers to manage their menus, availability, and orders. It is defined as thenuxt-catererdeployment. - Legacy Nuxt 2 "Admin" App (
nuxt-admin): A few essential pages that remain valuable to the operations team are housed in this legacy Nuxt 2 application, which corresponds to thenuxt-admindeployment.
Attendee App: React Native & Expo
For event attendees, CaterCow offers a mobile application built with React Native and leveraging the Expo framework for streamlined development and deployment. The corresponding service is named expo-attendee in the deployment configuration.
- Cross-Platform Functionality: The choice of React Native allows for a high degree of code sharing between the native iOS and Android applications.
- Web Accessibility with React Native Web: Crucially, the application also utilizes React Native Web. This enables attendees to view shared calendars, respond to group orders, and fill out surveys directly in a web browser without the need to download the mobile app, providing a seamless experience across platforms.