The infrastructure of DevLaunchers is designed to ensure scalability, efficiency, and reliability in hosting, testing, and deploying applications. By leveraging modern containerization, orchestration, and CI/CD practices, DevLaunchers maintains a robust platform for both development and production environments. This section provides a detailed breakdown of the infrastructure components, hosting setup, and CI/CD pipeline.
DevLaunchers leverages Azure Kubernetes Service (AKS) to host and manage its applications. The platform uses Kubernetes for container orchestration, providing a scalable and resilient infrastructure. Both staging and production environments run on the same Kubernetes cluster, but in different namespaces.
Staging Environment with Serverless Optimization:
The staging environment is designed to optimize costs by leveraging Kubernetes-native serverless technology (Knative).
Knative enables the staging deployments to scale workloads to zero when not in use, minimizing resource consumption during idle periods.
The deployment is scaled up when there is a new request.
DevLaunchers uses a GitOps workflow powered by FluxCD to handle deployments in both staging and production environments. This ensures that the infrastructure and application states are always consistent with the configuration defined in the Git repository. Flux deploys a few controllers in the flux-system to achieve this.
FluxCD Workflow:
The image reflect controller scans Docker Hub for new docker images
When there is a new image, the image automation controller commits the new image version to the Git repository. For example, this commit updates the staging strapi image
The source controller monitors the GitHub repository for changes to manifests, configurations, or Docker image tags.
When changes are detected, the kustomize controller applies the new Kubernetes manifest to the relevant namespace.
This approach ensures declarative, version-controlled deployments with minimal manual intervention.
The CI is implemented using GitHub Actions to automate the testing and building processes. The CD pipeline is managed by FluxCD. The pipeline is broken into distinct stages to ensure code quality, efficiency, and reliability.
Pipeline Architecture
Continuous Integration (CI):
Runs automated tests, including linting, unit testing, and end-to-end testing.
Generates Docker images for both staging and production environments.
Continuous Delivery (CD):
Deploys Docker images to AKS clusters using FluxCD, ensuring that new versions are seamlessly integrated.
Key Workflows:
The frontend and backend have similar workflows. In the following example, we will reference workflows for the backend.
Test Workflow (test.yaml
):
Triggered on each pull request (PR)
Runs automated tests on each PR to ensure code quality and prevent regressions.
Includes end-to-end tests using Playwright to validate application behavior.
Staging Image Workflow (staging-image.yaml
):
Triggered when there is a new commit in the main branch
Builds and tags Docker images by the timestamp of the build (YearMonthDayHourMinute)
Push Docker images to Docker Hub.
Release Workflow (release.yaml
):
Triggered when there is a new commit in the release branch
Handles semantic versioning using semantic-release.
Creates a new release tag
Production Image Workflow (production-image.yaml
):
Triggered when there is a new release is published (by the release workflow)
Builds and tags Docker images by the release version
Push Docker images to Docker Hub
Triggering CI/CD:
We will use an example to demonstrate our CI/CD. The following happens when a PR is merged to the main branch:
The staging image workflow builds a new Docker image that is tagged in the format of <sha>-<timestamp>.
The image is pushed to DockerHub which triggers a webhook.
The webhook is sent to a dockerhub flux receiver. We configured the receiver to reconcile the ImageRepository resource.
The image reflector controller will discover a new image tag.
The ImagePolicy will extract the timestamp and pick the latest timestamp as the latest image.
The ImageUpdateAutomation writes the new tag back to the repository.
The repository has a webhook to notify the github receiver. The receiver reconciles the GitRepository resource.
The source controller pulls the latest Kubernetes manifests from the repository. It'll see the new image tag and update the deployment.
DevLaunchers uses a combination of tools to monitor application health, gather metrics, and alert the team in case of issues:
Monitoring:
Prometheus: Used to collect metrics from the Strapi backend and Kubernetes clusters. The current setup generates application and system metrics but requires further development to set up dashboards and store metrics for analysis.
External Monitoring: The Uptime Robot platform monitors the production environment’s uptime by sending regular HTTP requests to the production endpoints.
Alerting:
Alerts from Uptime Robot notify the team when the production website is down or experiencing performance issues. The backend service is also integrated into this monitoring system.
The database for the DevLaunchers platform is hosted on a cloud cluster platform, providing scalable and highly available Postgres cluster. The staging and production use different databases but on the same cluster.
This documentation provides a comprehensive guide to the backend architecture and functionality of the Strapi application at DevLaunchers. It aims to ensure smooth collaboration and faster onboarding.
What is Strapi?
Strapi is a headless CMS (Content Management System) designed for flexibility and ease of use. As a headless CMS, Strapi allows developers to build and manage content while delivering it through APIs to various platforms, such as websites, mobile apps, and IoT devices.
Key benefits of using Strapi:
API-Centric: Strapi automatically generates REST or GraphQL APIs for all content types, making it easy to integrate with any frontend.
Customizable: Developers can extend or customize Strapi to suit specific project needs by modifying its controllers, services, or plugins.
Ease of Management: Content editors can use Strapi's intuitive admin panel to manage and organize content efficiently without developer intervention.
At DevLaunchers, Strapi plays a crucial role in managing content and serving APIs for various applications, ensuring a seamless flow of data across environments.
Strapi is built on the following core technologies:
Framework: Node.js - a JavaScript runtime for building scalable backend applications.
Language: JavaScript - the primary language used for development within the Strapi ecosystem.
Database:
Development Environment: SQLite - a lightweight relational database used locally for ease of setup during development.
Production and Test Environments: PostgreSQL - a robust relational database ideal for handling large-scale production data and testing scenarios.
This section provides an overview of the project structure for the backend powered by Strapi. It is essential to understand the purpose and functionality of each major folder and file. This section will break down the structure into key components for better clarity.
Key Folders and Their Purposes
src/
This is the core directory for the backend logic and Strapi implementation. It contains all the custom configurations, APIs, components, and other Strapi-related features.
api/
:
This folder includes all the APIs that power the backend. Each sub-folder corresponds to a specific content type or feature. For example:
applicant/
, project/
, notification/
, and others represent individual APIs created within Strapi.
Each API folder includes the following subfolders and files:
controllers/
: Handles the logic for the specific API endpoints.
services/
: Contains reusable business logic.
models/
: Defines the data structure for the API.
routes/
: Configures the available API routes for the content type.
components/
:
Houses reusable data structures or logic that can be shared across multiple APIs. For example:
people/
, positions/
, and links/
may define reusable building blocks or relationships used in content types or APIs.
extensions/
:
Contains custom extensions or plugins added to Strapi.
middlewares/
:
Holds custom middleware for handling requests and responses.
config/
This folder contains the configuration files for various environments (e.g., development, production). It includes the database configurations, server settings, and other environment-specific files.
database/
Manages database configurations and related setups. It ensures the backend can connect to and interact with the correct database based on the environment.
public/
Stores publicly accessible files such as uploaded assets, images, or static resources.
.env
A key configuration file for managing sensitive environment variables such as database credentials, API keys, and Strapi configurations.
Dockerfile
and Dockerfile.dev
These files contain instructions for containerizing the application using Docker. This is helpful for ensuring consistent development and deployment environments.
Local Development Using Node.js
To set up the Strapi backend for local development with Node.js, follow these steps:
Node.js Version Requirement: Ensure that Node.js v20 is installed. Using the correct version is crucial for compatibility with the Strapi application.
Set Up a Version Manager: It is recommended to use a version manager like NVM (Node Version Manager) or NPM Version Manager (n) to manage Node.js versions easily.
Refer to the following guides for installation:
Install Dependencies and Initialize the Database: Run the following command from the project’s root directory to install all required dependencies and initialize the local SQLite database for development:
Start the Development Server: Launch the local development server using:
Email: local-admin@devlaunchers.org
Password: W&x5ZzOMtBCVt1YAUiuSzt~5
Using Docker
For developers who prefer a containerized setup, the backend can be run using Docker. Follow these steps:
Ensure Docker is Running: Make sure Docker Desktop is active or that the Docker daemon is running on your system.
Build the Docker Container: Navigate to the project’s root directory and build the Docker container by running:
This command builds the containerized environment for the Strapi backend. The process may take a few minutes, especially if it’s the first time.
Start the Strapi Server: After building the container, start the Strapi server using:
The server will automatically reload when you make changes to the project files, eliminating the need to restart the container manually.
Restart the Server if the Container Stops: If the Docker container goes down or needs to be restarted, run:
Note: Rebuilding the container (using make build-docker
) is only necessary if significant changes are made to the configuration.
Authentication
Strapi APIs are secured by default. To interact with protected routes, users or developers need to authenticate using JSON Web Tokens (JWT). Authentication tokens are generated upon successful login and are required to access most API endpoints.
Public Endpoints: Can be accessed without authentication (if configured).
Protected Endpoints: Require valid JWT tokens.
Login Endpoint: Use this endpoint to authenticate and obtain a JWT:
Response:
Using REST APIs
Strapi's REST APIs allow developers to interact with content types using standard HTTP methods:
GET: Retrieve content.
POST: Create new entries.
PUT: Update existing entries.
DELETE: Remove entries.
Example REST API Endpoints:
Get All Entries for a Collection:
Example:
Get a Single Entry by ID:
Example:
Create a New Entry:
Update an Existing Entry:
Delete an Entry:
The Development Process at DevLaunchers outlines the standardized workflow, tools, and best practices developers follow to build, test, and deploy features or fixes on the platform. This structured approach ensures consistency, high-quality code, and efficient collaboration within the team. The process emphasizes key aspects such as local development, version control, automated testing, and code reviews, all designed to streamline development and maintain platform reliability.
Setting Up the Environment:
Developers start by configuring their local environment. This includes setting up Strapi, running necessary dependencies, and initializing the local database. Tools such as Node.js, Docker, and npm
commands are essential for the setup process.
Feature Development: Each developer works on a specific feature, bug fix, or enhancement by writing code locally. This is done in alignment with the project’s requirements and acceptance criteria as defined in tickets or documentation.
Testing Locally: Code is tested locally to ensure it works as intended and does not introduce regressions. Developers leverage tools such as Postman (for API testing), Strapi's built-in testing environment, or mock data to simulate real-world scenarios.
Branching:
Once local testing is complete, developers create a new branch in the GitHub repository to isolate their changes. The branch name should follow a predefined naming convention, such as: username/<feature-name>
After completing their work in the branch, developers push their code to the remote GitHub repository.
They then create a Pull Request (PR).
The PR title and description should include relevant details, such as the purpose of the changes, the issue or feature being addressed, and any dependencies or testing instructions.
The PR serves as the primary way for the team to collaborate on and discuss proposed changes before merging them into the main codebase.
GitHub Actions Integration: Submitting a PR triggers automated testing workflows via GitHub Actions. These workflows run predefined test suites to validate the code.
Test Results: If the code fails any of the automated tests, the PR will be marked as failing, and the developer must fix the issues before proceeding. Only PRs with passing tests are eligible for review.
Collaborative Review: Once the automated tests pass, the PR is reviewed by both peers or team leads.
Reviewers examine the code for:
Adherence to coding standards.
Code readability, maintainability, and performance.
Proper handling of edge cases and errors.
Security concerns and best practices.
Feedback and Iteration: Reviewers may provide feedback or request changes. The developer revises the code accordingly and updates the PR until all comments are resolved.
Approval and Merge: Once the code passes both automated tests and manual code reviews, it is approved for merging.
Developers merge the branch into the main branch (staging branch).
Deployment to Staging: The merged code is automatically deployed to the staging environment. This allows the team to perform final testing and validation before deploying it to production in the next release.
Once the code has been validated in staging, it can be deployed to the production environment. This deployment process require manual triggers by pushing the code to the release branch (production branch).
1. Version Control
DevLaunchers uses Git for version control, hosted on GitHub.
Developers follow a branching strategy to manage feature development, bug fixes, and releases.
2. Environment Types
The development pipeline includes multiple environments to ensure code quality and stability:
Local Environment: Where developers write and test code on their machines.
Staging Environment: A replica of production used for final testing.
Production Environment: The live application used by end-users.
3. Source Version Manager (SVM)
GitHub is the primary SVM used to manage the source code repository.
Developers interact with the repository using Git commands and PR workflows.
Access the Strapi Admin Panel: Once the server is running, access the Strapi Admin interface by navigating to in your browser. Use the following credentials to log in: