These integration guides are not official documentation and the Strapi Support Team will not provide assistance with them.
What Is Phoenix?
Phoenix serves as an excellent foundation for headless CMS integration due to its unique architecture and performance characteristics. Built with Elixir on the Erlang Virtual Machine, this web framework delivers exceptional scalability and fault-tolerance that traditional frameworks can't match. Understanding the difference between a headless vs traditional CMS helps appreciate Phoenix's strengths in modern web architectures.
The framework's real-time capabilities through channels and presence features set it apart for content-driven applications. By integrating Phoenix with Strapi, you get two-way communication between servers and clients, enabling live updates and collaborative features that boost user engagement. For a quick headless CMS overview, it's useful to understand how this separation of backend and frontend enhances flexibility and performance.
Following MVC architecture while using Elixir's actor model, Phoenix runs each connection in its own lightweight process. This design enables applications to handle millions of concurrent connections while consuming significantly less memory and CPU compared to conventional alternatives.
These characteristics make Phoenix particularly well-suited for integrating with Strapi in headless CMS implementations where performance and real-time functionality matter most. Content changes appear instantly through real-time updates while maintaining the scalability needed for growing content libraries and expanding user bases.
Why Integrate Phoenix with Strapi
Combining Strapi with Phoenix creates a powerful development stack that plays to both technologies' strengths. Strapi functions as a headless CMS, providing comprehensive content management capabilities through API endpoints rather than serving content directly to end users. This approach pairs perfectly with Phoenix's scalability and real-time capabilities.
With Strapi, you get several key features that streamline development for Phoenix applications. The platform offers a customizable API that adapts to your specific needs, letting you define content structures that match your application's requirements. Whether you're building a simple blog or a complex eCommerce platform, Strapi for eCommerce offers flexibility to tailor the CMS to your needs. Content creators and editors get an intuitive interface that removes the technical barriers often found in content management systems.
On the security front, Strapi provides solid authentication and authorization out of the box. The built-in RBAC in Strapi lets you define specific permissions for different user types, ensuring content creators, editors, and administrators have appropriate access. The i18n in Strapi support helps you manage multilingual content efficiently—crucial for applications serving global audiences.
Integrating Phoenix with Strapi creates a clean separation of concerns that improves both workflow and architecture. Phoenix handles application logic, real-time features, and performance-critical operations, while Strapi manages content creation, editing, and organization. When choosing a headless CMS, factors like flexibility, security, and ease of use are essential, making Strapi a compelling option. This division allows your team to use specialized tools for each domain—content managers focus on creating and organizing content through Strapi's user-friendly interface, while developers build robust, scalable features using Phoenix's powerful framework.
This API-based architecture fits perfectly with modern development practices, supporting headless CMS for developers and JAMstack approaches that continue to gain popularity. Strapi's automatically generated REST and GraphQL APIs provide flexible data access patterns that Phoenix applications can consume efficiently. Understanding the differences between REST vs GraphQL can help you choose the best approach for your application's data needs. For a GraphQL overview, learning about its benefits over traditional REST APIs can aid in designing efficient data queries.
Strapi supports various frontend frameworks for Strapi, including popular JavaScript frameworks, allowing developers to choose the best tools for their projects.
Enhanced deployment options include cloud solutions for quick deployment and hosting, making it easier to get your integrated application running in production. Whether you choose traditional hosting servers, preferred hosting providers, or cloud solutions, the deployment process remains streamlined and developer-friendly.
Keep in touch with the latest Strapi and Phoenix updates
How to Integrate Phoenix with Strapi
Integrating Phoenix with Strapi creates a powerful combination where you can use flexible content management alongside Phoenix's performance and real-time features. In this guide, we'll walk you through the complete integration process, from initial setup to advanced configuration.
Prerequisites and Technical Requirements
Before starting, you'll need to ensure you have the right tools: Elixir ≥ 1.14, Phoenix ≥ 1.7, Node.js ≥ 16, and PostgreSQL ≥ 12 for best compatibility. These versions give you access to the latest features and security updates essential for a solid integration.
For your database, PostgreSQL works best in production. You'll need to set up several environment variables including DATABASE_HOST
, DATABASE_PORT
, DATABASE_NAME
, DATABASE_USERNAME
, and DATABASE_PASSWORD
. The connection URL typically looks like: postgres://admin:password@dpg-abcdefghij.com:5432/dbname
.
Setting Up Your Environment
You can organize your project in different ways. Choose between a mono-repo approach with both Phoenix and Strapi in the same repository, or keep separate repositories for each service. Separate repositories often work better for larger teams since they allow independent deployment and scaling.
Setting Up Your Content Management System
To get started, create your Strapi project with the official installer:
npm create strapi-app@latest my-project
After installation, launch the admin panel and create your content types. Define the data models for your Phoenix application, such as articles, users, or products. Set up fields, relationships, and validation rules based on what your application needs.
API token configuration is essential for secure communication. Go to Settings → API Tokens in your dashboard, create a new token with the right access levels, and store it safely as you'll only see it once. Also configure permissions in Settings → Roles and Permissions, enabling access for required endpoints for either "Public" or "Authenticated" roles.
Setting Up Phoenix
For your Phoenix application, you'll need an HTTP client to consume the Strapi API. Numerous API development tools are available, including Tesla, HTTPoison, and Finch, each with different strengths. Tesla, HTTPoison, and Finch are popular options, each with different strengths. Tesla offers excellent middleware support, making it ideal for extensible integrations.
Here's a practical implementation using Tesla:
1defmodule MyApp.CMSClient do
2 use Tesla
3
4 plug Tesla.Middleware.BaseUrl, "https://my-cms-instance.com/api"
5 plug Tesla.Middleware.Headers, [{"Authorization", "Bearer #{System.get_env("CMS_JWT_TOKEN")}"}]
6 plug Tesla.Middleware.JSON
7
8 def get_content_type(content_type) do
9 get("/#{content_type}")
10 end
11end
To render content in your Phoenix controllers:
1defmodule MyAppWeb.ContentController do
2 use MyAppWeb, :controller
3
4 def index(conn, _params) do
5 with {:ok, %{body: body}} <- MyApp.CMS.get_content_type("articles") do
6 render(conn, "index.html", articles: body.data)
7 end
8 end
9end
Integration Approaches
The headless CMS approach gives you a clean separation of concerns, letting you use specialized tools for content management while benefiting from Phoenix's performance advantages. This architecture works well with modern development practices and allows teams to work independently on content management and application logic.
For API-based integration, you'll need to implement JWT authentication to secure API access. Configure CORS settings in both applications to enable cross-origin requests. In your Strapi configuration, add your Phoenix server's domain to the allowed origins.
Deploy your Strapi instance, explore community resources, or try demo implementations to see the integration in action.
Real-time Updates with Webhooks
Real-time synchronization between Strapi and Phoenix works beautifully using Strapi webhooks combined with Phoenix Channels. This ensures your Phoenix application shows content changes immediately without manual refreshes or polling.
To get started, set up webhooks in your Strapi admin panel. Go to Settings → Webhooks and create a new webhook pointing to your Phoenix application endpoint. Select which events should trigger notifications: content creation, updates, or deletions. Test your setup using the built-in "Trigger" button to verify everything connects properly.
Create a webhook receiver in your Phoenix application:
1defmodule MyAppWeb.WebhooksController do
2 use MyAppWeb, :controller
3
4 def handle_cms(conn, params) do
5 event_type = get_in(params, ["event"])
6 entry = get_in(params, ["entry"])
7
8 case event_type do
9 "entry.create" -> handle_creation(entry)
10 "entry.update" -> handle_update(entry)
11 "entry.delete" -> handle_deletion(entry)
12 _ -> :ok
13 end
14
15 conn |> put_status(200) |> json(%{received: true})
16 end
17
18 defp handle_creation(entry) do
19 MyAppWeb.Endpoint.broadcast!("content_updates", "creation", %{entry: entry})
20 end
21end
Implement Phoenix Channels to broadcast webhook events to connected clients. Create a channel module that handles real-time communication and broadcasts content updates to subscribed users. This enables features like live content previews and instant notifications when content changes.
Advanced webhook security implementations can include signature verification to ensure webhook authenticity, preventing unauthorized requests from reaching your application.
Security Best Practices
Securing your Phoenix-Strapi integration requires multiple layers of protection. Start with robust authentication strategies by configuring JWT authentication with proper token expiration and refresh mechanisms. Store tokens securely and never hard-code API keys or credentials in your code.
Implement CMS security best practices such as regular security audits and dependency updates to keep your integration secure. Monitor authentication failures, authorization violations, and unusual access patterns. Implement thorough logging and set up alerts for suspicious activities to catch potential security issues early. Applying headless CMS security measures ensures that your content management system is protected against threats.
Implement Role-Based Access Control (RBAC) systems to define specific permissions for different user types. Create custom roles beyond the default ones and assign specific permissions for each content type and endpoint. Verify these permissions on both the Phoenix and Strapi sides for complete protection.
Secure communication is non-negotiable—always use HTTPS for all API communications and configure proper CORS policies. Avoid overly permissive settings like Access-Control-Allow-Origin: *
for authenticated APIs, instead specifying exact domains that should have access.
For webhook security, implement signature verification to ensure requests truly come from Strapi:
1defp verify_cms_signature(conn) do
2 signature = get_req_header(conn, "cms-signature") |> List.first()
3 body = conn.assigns[:raw_body]
4 secret = Application.get_env(:my_app, :cms_webhook_secret)
5
6 expected = :crypto.hmac(:sha256, secret, body) |> Base.encode16(case: :lower)
7 Plug.Crypto.secure_compare(expected, signature)
8end
Regular security audits and dependency updates keep your integration secure. Monitor authentication failures, authorization violations, and unusual access patterns. Implement thorough logging and set up alerts for suspicious activities to catch potential security issues early.
Keep in touch with the latest Strapi and Phoenix updates
Project Example: Build a News Publishing Platform with Phoenix and Strapi
This news publishing platform shows how integrating Phoenix with Strapi works in the real world. Content editors manage articles through the Strapi admin interface while readers access content through a Phoenix frontend that delivers sub-100ms response times.
The architecture completely separates content management from presentation logic. Editors work independently in Strapi while developers optimize performance and user experience in Phoenix. No conflicts, no stepping on toes.
The Phoenix application consumes the Strapi REST API using Tesla as the HTTP client. The CMSClient
module handles all API interactions using the adapter pattern—you could swap Strapi for another headless solution later without touching your business logic. JWT authentication manages API access, with Phoenix storing tokens securely and refreshing them automatically. The client includes error handling for network failures and implements caching to reduce API calls during traffic spikes.
Real-time updates happen through the webhook system. When editors publish new articles or update existing content, Strapi sends webhook notifications to a dedicated Phoenix controller. This controller processes the webhook payload and broadcasts changes through Phoenix Channels, updating connected readers' browsers instantly—no page refreshes needed.
The repository follows Phoenix conventions with additional modules for external API integration. The lib/my_app/cms/
directory contains the client implementation, while lib/my_app_web/live/
holds LiveView components that subscribe to real-time updates. Environment-specific configurations for both development and production live in the config/
directory.
Security includes webhook signature verification to ensure requests genuinely come from Strapi, similar to how Stripe webhooks are handled in Phoenix. The application implements proper CORS configuration and uses environment variables for sensitive data like API tokens and database credentials.
Clone the repository, configure environment variables, and run both applications simultaneously. The project includes Docker Compose configuration for easy local development, with both Phoenix and Strapi running in containers sharing a PostgreSQL database.
Key learning points include proper error handling when consuming external APIs, implementing real-time updates for improved user experience, and robust security measures. The example demonstrates how content API integration best practices apply in real-world scenarios, particularly around environment configuration and API security.
This project serves as a foundation you can extend with user authentication, comment systems, or multi-language support while maintaining clean separation between content management and application logic.
Project Example: Build a News Publishing Platform with Strapi and Phoenix
Let's explore how to build a real-time news publishing platform using Strapi and Phoenix. This example demonstrates the power of combining these technologies for content-intensive applications that need both editorial workflows and immediate content delivery through dynamic content management.
In this architecture, Strapi serves as your content hub where journalists and editors create, review, and publish news articles. The platform manages content types including articles, categories, media assets, and author profiles. Editors benefit from Strapi's intuitive interface to organize breaking news, feature stories, and topic-based content collections.
Phoenix powers the consumer-facing application, handling:
Real-time news delivery: When editors publish breaking news in Strapi, Phoenix channels push updates to all connected readers instantly, without requiring page refreshes.
Personalized news feeds: Phoenix processes user preferences and reading history to customize content delivery, with presence tracking showing which stories are trending in real-time.
Interactive elements: Comment sections and reaction systems leverage Phoenix's concurrency model to handle thousands of simultaneous user interactions.
To build this platform:
First, set up your Strapi instance with content types for articles, categories, media, and author profiles. Configure workflows that allow for draft creation, editorial review, and scheduled publishing.
Develop your Phoenix application with proper API consumption patterns. Create GenServers to poll for content updates or implement webhooks from Strapi to notify Phoenix of new content.
Design your Phoenix channels infrastructure for real-time delivery. For example:
1defmodule NewsPortalWeb.NewsChannel do 2 use NewsPortalWeb, :channel 3 4 def join("news:breaking", _params, socket) do 5 send(self(), :after_join) 6 {:ok, socket} 7 end 8 9 def handle_info(:after_join, socket) do 10 # Fetch latest breaking news from cache 11 breaking_news = NewsPortal.Content.get_breaking_news() 12 push(socket, "breaking_news", %{articles: breaking_news}) 13 {:noreply, socket} 14 end 15 16 # Handle new breaking news publications 17 def handle_in("new_article", %{"id" => article_id}, socket) do 18 article = NewsPortal.Content.get_article!(article_id) 19 broadcast!(socket, "new_article", %{article: article}) 20 {:reply, :ok, socket} 21 end 22end
Implement a caching layer using Phoenix's ETS tables or Redis to ensure consistently fast content delivery while minimizing database load:
1defmodule NewsPortal.ContentCache do 2 use GenServer 3 4 # Cache initialization and refresh logic 5 def init(_) do 6 # Initial cache population 7 articles = fetch_articles_from_strapi() 8 schedule_refresh() 9 {:ok, %{articles: articles, last_updated: DateTime.utc_now()}} 10 end 11 12 defp schedule_refresh do 13 # Refresh cache every minute 14 Process.send_after(self(), :refresh, 60_000) 15 end 16 17 def handle_info(:refresh, state) do 18 articles = fetch_articles_from_strapi() 19 schedule_refresh() 20 {:noreply, %{state | articles: articles, last_updated: DateTime.utc_now()}} 21 end 22 23 defp fetch_articles_from_strapi do 24 # API call to fetch latest articles from Strapi 25 end 26end
For analytics, leverage Phoenix's lightweight processes to track reader engagement without impacting performance:
1defmodule NewsPortal.Analytics do 2 def track_article_view(article_id, user_id) do 3 # Spawn a process to handle analytics without blocking the main request 4 Task.start(fn -> 5 # Record view in database 6 # Update trending articles in real-time 7 NewsPortalWeb.Endpoint.broadcast!("analytics:trending", "update", 8 %{article_id: article_id}) 9 end) 10 end 11end
This architecture allows your news platform to handle both predictable traffic patterns and sudden spikes during breaking news events. Content editors work with Strapi's familiar interface while readers benefit from Phoenix's real-time capabilities and performance under load.
Ready to dive in? Deploy your integrated Phoenix application today, check out our demo implementations, or join our developer community to connect with others building similar solutions.
Strapi Open Office Hours
If you have any questions about Strapi 5 or just would like to stop by and say hi, you can join us at Strapi's Discord Open Office Hours Monday through Friday at 12:30 pm – 1:30 pm CST.
For more details, visit the Strapi documentation and Phoenix documentation.