<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Choreo Tech Blog - Medium]]></title>
        <description><![CDATA[A collection of tutorials and insightful blogs crafted for the Choreo community. - Medium]]></description>
        <link>https://medium.com/choreo-tech-blog?source=rss----a7ca74741cb8---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>Choreo Tech Blog - Medium</title>
            <link>https://medium.com/choreo-tech-blog?source=rss----a7ca74741cb8---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 04 Nov 2026 23:36:46 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/choreo-tech-blog" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[From Azure DevOps to Cloud with Choreo: 5 Steps]]></title>
            <link>https://medium.com/choreo-tech-blog/from-azure-devops-source-to-cloud-with-choreo-in-5-steps-087039ddef01?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/087039ddef01</guid>
            <dc:creator><![CDATA[Yashodha Samarawickrama]]></dc:creator>
            <pubDate>Tue, 16 Dec 2025 07:19:13 GMT</pubDate>
            <atom:updated>2025-12-16T07:19:11.994Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DqhoJqT6j0DqXsV08aYK8Q.png" /></figure><h3>Introduction</h3><p>Azure DevOps is a robust platform for source code management, CI/CD pipelines, and project planning. In this article, we’ll show you how to <strong>connect your Azure DevOps repository to </strong><a href="https://choreo.dev/"><strong>Choreo</strong></a>, build a service from that repository, and deploy it to the cloud using automated workflows.</p><p>Whether you are onboarding an existing application or deploying a new service, this integration streamlines deployments directly from your Azure DevOps Git repository.</p><h3>Prerequisites</h3><p>Before you begin, make sure you have:</p><ol><li>A <a href="https://choreo.dev/"><strong>Choreo</strong></a> account</li><li>An <a href="https://dev.azure.com/"><strong>Azure DevOps</strong></a><strong> organization and project</strong></li><li>A <strong>repository in Azure DevOps</strong> containing your application source code</li></ol><p><strong>Step 1 — Generate a Personal Access Token (PAT) in Azure DevOps</strong></p><ul><li>Sign in to <strong>Azure DevOps</strong> (dev.azure.com).</li><li>In the top-right corner, next to your profile picture → <strong>User Settings</strong>.</li><li>Select <strong>Personal access tokens</strong> → <strong>New Token</strong>.</li><li>Give the token a name like <em>ChoreoAccessToken</em>.</li><li>Select <strong>Scopes</strong>: <strong>Code (Read)</strong>, <strong>Project (Read) and Team (Read)</strong></li><li>Set the expiration and create the token.</li><li>Copy the generated token and store it securely, as it cannot be viewed again.</li></ul><p><strong>Step 2 — Add Azure DevOps Credentials in Choreo</strong></p><ol><li>Log in to the <a href="https://choreo.dev/"><strong>Choreo</strong></a><strong> Console</strong>.</li><li>Open your organization from the sidebar.</li><li>Navigate to <strong>Settings → Credentials</strong>.</li><li>Click <strong>+ Add Credentials</strong>.</li><li>Fill in:</li></ol><ul><li><em>Credential Name</em>: e.g., AzureDevOpsCred</li><li><em>Service Provider</em>: <strong>Azure DevOps</strong></li><li><em>Access Token</em>: Paste the PAT generated earlier</li></ul><p>6. Click <strong>Save</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-1BKCvTmtS_3IHTjC8j6Ew.png" /></figure><p>You should now see your Azure DevOps credential listed in Choreo.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*z6nOZK50ZfHbWzklmpfGaw.png" /></figure><p><strong>Step 3 — Create a New Component Using Your Azure DevOps Repository</strong></p><ul><li>Navigate back to your Choreo Organization homepage.</li><li>Click <strong>+ Create Project</strong> and enter a project name.</li><li>Within the project, select <strong>a Component Type </strong>card.</li><li>Select ‘Try a Different Git Provider’ -&gt; Select ‘<strong>Authorize with</strong> <strong>Azure DevOps’</strong> and select the previously created credential.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/863/1*RUa9_tLZbJOtZJn34O3RfQ.png" /></figure><ul><li>Select: <em>Project, Repository and Branch</em></li><li>Enter the directory path</li><li>Choose the corresponding build preset</li><li>Click on Create and Deploy</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fhdju8yjiDZpZ1J5yV1APQ.png" /></figure><p><strong>Step 4 — Build the Component</strong></p><ul><li>When the component creation is successful, you will be redirected into the Component Overview page.</li><li>Navigate to the <strong>Build</strong> page from the left navigation menu.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zXVmwqt_XXrAgYPL9X32NA.png" /></figure><ul><li>Once you are in the Build page, Click on <strong>Build Latest (to build the latest commit) </strong>or select <strong>Show Commits -&gt; Select a commit from the commit list </strong>to start building your source code.</li><li>You will be able to see the status of the build once it is in-progress.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6UO2ipNJTuMyFtonII_V4Q.png" /></figure><p>Once the build is successful, navigate to the <strong>‘Deploy’</strong> page from the left menu.</p><p><strong>Step 5 — Deploy to Production</strong></p><ul><li>Click on ‘Configure &amp; Deploy’ in the Set Up card to deploy to your first environment.</li><li>To promote this service to the production environment, click <strong>‘Promote’</strong> and select the ‘<strong>Use Development configuration</strong>’ or <strong>‘Add New Configurations’</strong> option from the right drawer.</li></ul><p>Your source code should now be in production!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*3Wgi4XfKqXQygrg37Sl7yQ.png" /></figure><p>To test the application, navigate to the <strong>Test</strong> -&gt; <strong>Console </strong>page from the left menu.</p><p><strong>Summary</strong></p><p>This article explains how to take your code from Azure DevOps to the cloud using Choreo. It covers generating a PAT, adding Azure DevOps credentials in Choreo, creating a component from your repo, building the service, and deploying it to production — all in a streamlined, automated workflow.</p><p><a href="https://choreo.dev/?utm_source=me&amp;utm_medium=orgpost&amp;utm_campaign=me_orgpost_gitlab_240812">Sign up to Choreo </a>for free to explore more cool features.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=087039ddef01" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/from-azure-devops-source-to-cloud-with-choreo-in-5-steps-087039ddef01">From Azure DevOps to Cloud with Choreo: 5 Steps</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deploy Blazor Web Apps on Choreo]]></title>
            <link>https://medium.com/choreo-tech-blog/deploy-blazor-web-apps-on-choreo-62090034f9a8?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/62090034f9a8</guid>
            <category><![CDATA[blazor-webassembly]]></category>
            <category><![CDATA[c-sharp-programming]]></category>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[dotnet]]></category>
            <dc:creator><![CDATA[Suvin]]></dc:creator>
            <pubDate>Mon, 15 Dec 2025 07:39:17 GMT</pubDate>
            <atom:updated>2025-12-15T07:38:52.632Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rT2nDACpOTDlDDXhQaTd8w.png" /><figcaption>Your Blazor apps deserve a better deployment experience</figcaption></figure><p>Blazor has changed the game for web developers who prefer C# over JavaScript. If you’re looking to get your Blazor app to the cloud, Choreo’s Bring Your Own Container (BYOC) feature makes the process straightforward.</p><p>In this tutorial, you’ll learn how to set up a sample Blazor project and prepare it for deployment on <a href="https://console.choreo.dev/">Choreo</a>.</p><h3>What You’ll Learn</h3><p>By the end of this guide, you’ll learn to:</p><ul><li>Set up a sample Blazor Web App project</li><li>Create a production-ready Dockerfile for your Blazor application</li><li>Prepare and deploy the application on Choreo</li></ul><h3>Prerequisites</h3><p>Before you begin, make sure you have:</p><ul><li>A Choreo Account (Sign up for free at <a href="https://console.choreo.dev/signup">https://console.choreo.dev/signup</a>)</li><li>.NET 9.0 SDK installed</li><li>Docker installed (for local testing)</li><li>A GitHub account</li><li>Basic familiarity with Blazor and containerization concepts</li></ul><p>Let’s write some code!</p><h3>Step 1: Setting Up the Sample Project</h3><p>We’ll use the official Blazor Web App Movies sample from Microsoft’s <a href="https://github.com/dotnet/blazor-samples">blazor-samples repository</a>. This sample contains a full-featured Blazor web application with database connectivity and CRUD operations.</p><h4>Fork the Repository</h4><p>First, navigate to the <a href="https://github.com/dotnet/blazor-samples">official Blazor samples repository</a> and fork it to your GitHub account. This will allow you to make modifications and connect it to Choreo later.</p><h4>Clone Your Fork</h4><p>Once you’ve forked the repository, clone it to your local machine:</p><pre>git clone https://github.com/&lt;YOUR_USERNAME&gt;/blazor-samples.git<br>cd blazor-samples/9.0/BlazorWebAppMovies</pre><h4>Test the Application Locally</h4><p>Before containerizing the app, verify that it runs correctly on your local machine. This app requires an MSSQL database to run properly. If you don’t have one set up locally, you can either:</p><ul><li>Install MSSQL Server locally</li><li>Use a Docker container for MSSQL</li></ul><p>Once your database is available, update the connection string in appsettings.json or set it as an environment variable, then run:</p><pre>dotnet restore<br>dotnet run</pre><p>Open your browser and navigate to the URL displayed in the terminal (typically <a href="http://localhost:5216/">http://localhost:5216</a>). You should see the Movies application, allowing you to create, edit, and delete movie records.</p><h3>Step 2: Creating the Dockerfile</h3><p>This is the most important step — creating a Dockerfile that packages your Blazor app for deployment on Choreo.</p><p>Create a new file called Dockerfile in the root of your BlazorWebAppMovies project directory.</p><p>Here’s what your Dockerfile should look like:</p><pre># Build stage - Use the .NET SDK to build the application<br>FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build<br>ARG BUILD_CONFIGURATION=Release<br>WORKDIR /src</pre><pre># IMPORTANT FOR CHOREO: Create non-root user<br># Choreo requires containers to run as non-root users for security<br>RUN groupadd -g 10014 choreo &amp;&amp; \<br>    useradd --no-create-home --uid 10014 --gid 10014 choreouser</pre><pre># Copy project file and restore dependencies<br>COPY . .<br>RUN dotnet restore &quot;BlazorWebAppMovies.csproj&quot;</pre><pre># Build the project<br>RUN dotnet build &quot;BlazorWebAppMovies.csproj&quot; -c $BUILD_CONFIGURATION -o /app/build</pre><pre># Publish stage - Create the final published output<br>FROM build AS publish<br>ARG BUILD_CONFIGURATION=Release<br>RUN dotnet publish &quot;BlazorWebAppMovies.csproj&quot; -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false</pre><pre># Runtime stage - Use the ASP.NET Core runtime for the final image<br>FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS final<br>WORKDIR /app</pre><pre># Use the non-root user ID<br>USER 10014</pre><pre># Copy the published application from the publish stage<br>COPY --from=publish /app/publish .</pre><pre># Expose ports<br>EXPOSE 8080<br>EXPOSE 8081</pre><pre># Configure ASP.NET Core to listen on port 8080<br>ENV ASPNETCORE_URLS=http://+:8080</pre><pre># Set the entry point to run the application<br>ENTRYPOINT [&quot;dotnet&quot;, &quot;BlazorWebAppMovies.dll&quot;]</pre><p>Let’s break down what each section does:</p><p><strong>Build Stage:</strong></p><ul><li>Uses the official .NET 9.0 SDK image as the build environment</li><li>Copies the project file first to leverage Docker layer caching</li><li>Restores NuGet packages</li><li>Copies all source files and builds the application in Release mode</li></ul><p><strong>Publish Stage:</strong></p><ul><li>Publishes the application, creating optimized assemblies for production</li><li>Removes unnecessary build artifacts and prepares the application for deployment</li></ul><p><strong>Runtime Stage:</strong></p><ul><li>Uses the lightweight ASP.NET Core runtime image</li><li>Sets USER<strong> </strong>10014. This is critical for Choreo deployment as it requires non-root users for security</li><li>Configures the application to listen on port 8080/81</li><li>Sets up the entry point to run your Blazor application</li></ul><h3>Step 3: Testing Your Docker Image Locally</h3><p>Before deploying to Choreo, test the container locally.</p><pre># Build the Docker image<br>docker build -t blazor-movies-app .</pre><pre># Run the container with your database connection string<br>docker run -p 8080:8080 \<br>  -e ConnectionStrings__BlazorWebAppMoviesContext=&quot;Host=your-db-host;Port=1433;Database=BlazorWebAppMovies;Username=sa;Password=YourPassword;TrustServerCertificate=true&quot; \<br>  blazor-movies-app</pre><p>Make sure to replace the connection string with your actual MSSQL database details. If you don’t have a database set up for testing, you can skip this step and test once deployed on Choreo.</p><p>Open your browser and navigate to http://localhost:8080 to verify that your containerized application works correctly.</p><h3>Step 4: Commit and Push Your Changes</h3><p>Once you’ve created and tested your Dockerfile, commit it to your forked repository.</p><h3>Step 6: Deploying to Choreo</h3><p>Now that your application is containerized and pushed to GitHub, you’re ready to deploy it on Choreo using the BYOC (Bring Your Own Container) approach.</p><p><strong>[Important] Database Setup</strong></p><p>This app needs an MSSQL database. You’ll need to add the connection string as an environment variable in Choreo. It should look something like this:</p><pre>ConnectionStrings__BlazorWebAppMoviesContext=Host=mssql-host.com;Port=16638;Database=BlazorWebAppMovies;Username=sa;Password=super$tr0ngPassword;SslMode=Require;TrustServerCertificate=true</pre><p>Refer to Choreo’s <a href="https://wso2.com/choreo/docs/devops-and-ci-cd/manage-configurations-and-secrets/">Manage Configurations and Secrets</a> documentation on how to add environment variables.</p><h4>The Deployment Process</h4><p>Here’s what you’ll do in Choreo:</p><ul><li>Create a Web Application component</li><li>Connect your GitHub repository</li><li>Select “Dockerfile” as the build preset</li><li>Set the Dockerfile path (./Dockerfile)</li><li>Configure the build context (usually the project root)</li><li>Set your environment variables (like that database connection string)</li><li>Build and deploy to your selected environment</li></ul><p>Choreo handles the heavy lifting automatically! Choreo will:</p><ul><li>Build your Docker image from the Dockerfile</li><li>Scan for security vulnerabilities</li><li>Deploy to Kubernetes</li><li>Set up CI/CD pipelines for automatic deployments on code changes</li></ul><p>For detailed instructions, check out the Choreo <a href="https://wso2.com/choreo/docs/develop-components/deploy-a-containerized-application/">container deployment documentation</a>.</p><h3>Wrapping Up</h3><p>And that’s it! You’ve successfully containerized a Blazor application and deployed it on Choreo using BYOC.</p><p>Happy Coding!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=62090034f9a8" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/deploy-blazor-web-apps-on-choreo-62090034f9a8">Deploy Blazor Web Apps on Choreo</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How We Used an AI Agent to Skip the DevOps Grind]]></title>
            <link>https://medium.com/choreo-tech-blog/how-we-used-an-ai-agent-to-skip-the-devops-grind-e54bc0bd491a?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/e54bc0bd491a</guid>
            <category><![CDATA[llm-agent]]></category>
            <category><![CDATA[vibe-code]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[cursor]]></category>
            <category><![CDATA[model-context-protocol]]></category>
            <dc:creator><![CDATA[Isala Piyarisi]]></dc:creator>
            <pubDate>Mon, 25 Aug 2025 08:37:18 GMT</pubDate>
            <atom:updated>2025-08-25T08:37:18.737Z</atom:updated>
            <content:encoded><![CDATA[<p>When I read Andrej Karpathy’s post on <a href="https://karpathy.bearblog.dev/vibe-coding-menugen/">building MenuGen</a>, what stood out was the all-too-familiar arc, the initial joy of spinning up a quick prototype, followed by the slow grind of making it production-ready. The creative sprint gives way to a marathon of plumbing, wiring up APIs, juggling secret keys, wrestling with deployment quirks, and stitching together services just to make sure the app doesn’t vanish when you hit refresh.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/562/1*gBvTY_Gj1iy9W2NBhsArJw.png" /><figcaption>The two phases of every software project</figcaption></figure><p>That experience sparked a question: could we keep the creative, vibe-coding flow while automating all the plumbing? We set out to find the answer by rebuilding MenuGen, combining a simple product brief from a large model with an implementation agent in VS Code. But we almost hit the same wall Karpathy did. Our agent could dream up the code, but it was like an architect who’d never seen the building site, it was completely blind to our actual infrastructure.</p><p>The breakthrough for us was finding a way to give the agent a pair of eyes. We used <a href="https://choreo.dev/">WSO2’s Choreo platform</a>, whose <a href="https://medium.com/choreo-tech-blog/enhancing-developer-workflows-with-mcp-support-in-choreo-cli-b1acab1b3fd3">Model Context Protocol (MCP) server</a> acted as that crucial link, giving our AI a real-time “cheat sheet” to our services, APIs, and deployment targets.</p><h3>From Idea to Local App</h3><p>Like the original project, ours began with a clear idea. We used Gemini 2.5 Pro within VSCode to produce a concise Software Design Document (SDD) outlining the core components:</p><ul><li>An OCR step to extract menu items.</li><li>An image generation step to visualize them.</li><li>A simple web UI.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sZAsvQ-Q-69ja2gvgQ7tfw.png" /><figcaption>A simple prompt for Gemini 2.5 Pro in VS Code is all it takes for the AI agent to generate a complete Software Design Document, laying the technical groundwork for the MenuGen app (Exact prompt: see end of article).</figcaption></figure><p>With that Software Design Document in hand, we handed it to a <strong>Claude Sonnet 4.0 </strong>agent in VS Code with a single, crucial instruction.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/695/1*stVw4aOBITQ9AzWQUtfagQ.png" /><figcaption>Prompt: “Can you implement this app and double check external API integrations with third-party services using the Choreo Marketplace?”</figcaption></figure><p>This prompt contains two key instructions. The first, “<strong>implement this app</strong>” is the straightforward task of code generation. The second part, however, is what sets this process apart and directly addresses the “painful slog” of productionizing a prototype: <strong>“using the Choreo Marketplace.”</strong></p><p>By instructing the agent to use the <a href="https://wso2.com/library/blogs/introducing-choreo-marketplace-and-connections/">marketplace</a> as its source of truth for APIs, we preemptively solve the problem of hunting for endpoints, wrestling with deprecated docs, and manually managing secret keys. This is the bridge between intent and infrastructure that will be critical later on.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*D0d2fSI2W7PdgHXCAHdqCw.png" /><figcaption>The agent uses the Choreo Marketplace as a source of truth, automatically fetching API specs and correcting the code to align with the live service, avoiding errors from outdated documentation</figcaption></figure><p>This automated correction is a key part of the process. Armed with the correct-by-definition API specs from the marketplace, the agent didn’t just write code, it wrote the <strong>right</strong> code. It then proceeded to translate the entire design document into a working local repository.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lQTmzsDEOR0kp_XxbPEF2g.png" /><figcaption>The agent translates the design document into a working local repository. It scaffolds the full project, writes initial code, and outlines its implementation plan in the chat, confirming that all required services and database schemas are ready.</figcaption></figure><p>The agent delivered a complete repository with a React frontend and a Go backend. It included a detailed README.md with clear instructions for local setup, from the docker run commands to the required .env configuration. This provided all the basic plumbing to iterate quickly on a laptop. This brings you to that exhilarating ‘<strong>80% done</strong>’ feeling that Karpathy described, the fun part of the project.</p><h3>Automating the “Painful Slog” of Integration</h3><p>The initial prototype is the fun part where you feel 80% done. The remaining 20%, as Karpathy noted, is often a “painful slog” of wrestling with deprecated APIs and out-of-date docs. This is where our path diverged sharply from the original. For us, this entire step was automated because we instructed the agent to use the <strong>Choreo Marketplace.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/490/1*0eVvRCo_Oe0Eh8QHMBv-mw.png" /><figcaption>Why wrestle with the plumbing when you can just… ask?</figcaption></figure><p>An AI agent’s code is only as reliable as its knowledge, which can be months or years out of date. This is why it might generate calls to endpoints that no longer exist. The marketplace solves this by acting as a live, guaranteed source of truth.</p><p>It contains connectors for common public APIs like OpenAI, but critically, it also allows you to <a href="https://console.choreo.dev/organizations/choreopmm/resources/third-party-services">register your own</a> internal or third-party services. We had already registered <strong>Replicate</strong> this way, making its API discoverable and standardized for our agent.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dJThkjlHSUiuwta2uFWKTw.png" /><figcaption>The Choreo Marketplace provides a trusted catalog of both public (OpenAI) and organization-specific (Replicate) services, giving the AI agent a single, reliable place to find up-to-date connection details.</figcaption></figure><p>Instead of hallucinating API calls, the agent queried this marketplace. It received the up-to-date OpenAPI specs and direct references to secrets managed within Choreo, and used this correct-by-definition information to automatically wire both integrations into the Go backend. No more hunting for endpoints or pasting stale code snippets.</p><h3>From Laptop to Live in One Go</h3><p>With the code working locally, we arrived at the final headache: deployment. For this, we gave the agent a simple, conversational prompt: ”C<strong>an you deploy this on Choreo?</strong>” What followed was an intelligent, multi-step process orchestrated entirely by the agent and Choreo’s MCP server. It was like watching an expert DevOps engineer work at machine speed.</p><p><strong>1. Analyze and Plan</strong><br>First, the agent analyzed the entire project repository, the Go backend and the React frontend to understand the application’s structure and dependencies. This initial reconnaissance was crucial for formulating a deployment strategy.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ubVOZztgfH9ygU0nckUyyg.png" /><figcaption><em>The AI agent begins the deployment process by analyzing the project’s repository to understand its structure and dependencies.</em></figcaption></figure><p><strong>2. Deploy the Backend</strong></p><p>Based on its analysis, the agent generated a component.yaml manifest file defining a backend component. It then built and deployed the initial version of the backend service to Choreo. Getting the API live first is a critical step in a modern deployment workflow.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6QYY3XYmKVYsrCRIrDqVDg.png" /><figcaption><em>The agent generates the necessary component.yaml manifest and uses Git to push the configuration, initiating the backend service deployment on Choreo.</em></figcaption></figure><p><strong>3. Provision and Publish the Database</strong></p><p>Next, the agent requested a managed PostgreSQL database from Choreo. Once provisioned, it immediately published the new database as a service in the Choreo marketplace, making it a discoverable and connectable resource for other components.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*M7pXtHvYi0v1liW8YS6GsQ.png" /><figcaption>The agent provisions a new PostgreSQL database and publishes it as a service in the Choreo marketplace, making it discoverable for other components.</figcaption></figure><p><strong>4. Wire Up the Backend Connections</strong></p><p>With the database and third-party services available in the marketplace, the agent updated the component.yaml manifest. It added “Choreo Connections” to formally link the backend to the database, OpenAI, and Replicate services, then redeployed the backend with this new, complete configuration.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*On7vD3JCbTSzq_fsLv9qAA.png" /><figcaption>The agent updates the component manifest to formally link the backend to the database and third-party APIs, then redeploys the service with the new configuration.</figcaption></figure><p><strong>5. Implement and Deploy the Frontend with Auth</strong></p><p>The agent then turned its attention to the frontend. It scaffolded sign-in and sign-out buttons in the React UI and wired them to <a href="https://wso2.com/library/blogs/choreos-managed-authentication-for-single-page-web-applications/">Choreo’s managed authentication</a> endpoints. After generating the frontend component definition, it built and deployed the frontend.</p><p><strong>6. Secure the Final Connection</strong></p><p>With both frontend and backend live, the agent made the final crucial link- connecting the web app to the backend. This ensures all communication flows through Choreo’s secure gateway, protecting the API and managing user sessions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PpB8AsXvME7HIiSEwmOCyQ.png" /><figcaption>The agent establishes the final, secure connection between the live frontend and backend through Choreo’s gateway.</figcaption></figure><p><strong>7. Create Test Users</strong></p><p>As a final touch, the agent used Choreo’s Secure Token Service (STS) to automatically create a handful of test users, allowing us to immediately sign in and test the end-to-end flow of the live application.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*inGJ49YozQcpRcjgyw1LKw.png" /><figcaption>As a final step, the agent provides a live URL and test credentials, generated via Choreo’s Secure Token Service, for immediate end-to-end testing.</figcaption></figure><p>In just a few minutes and from a single conversational prompt, the process took the project from a local repository to a fully wired, secure, and live cloud architecture. Suddenly, the abstract components from the initial SDD became tangible, live services, fully interconnected and managed by the Choreo platform.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zMlkwUtSoYRpS6k-a72LcA.png" /><figcaption>Choreo provides a real-time dependency graph, visualizing the complete architecture of the live application — from the frontend through the backend to its connected database and AI services.</figcaption></figure><p>This entire system was automatically assembled and brought to life, culminating in the final, user-facing application.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GG_kMa6MB9XjnU_3Vdf8rw.png" /><figcaption>The final result: a fully deployed, secure, and functional MenuGen application, live and accessible via a Choreo-provided URL.</figcaption></figure><p>What would normally be a multi-hour, error-prone manual task was reduced to an automated, repeatable workflow, orchestrated entirely by the agent.</p><h3>Solving the Hard Problems Automatically</h3><p>This automated flow highlights a fundamental shift. The innovation isn’t just that an AI can write code, it’s that a tight integration between an implementation agent and a deployment platform can automate the vast majority of platform engineering friction. This approach didn’t just save time, it elegantly solved the very problems that made the original MenuGen journey a “painful slog”:</p><ul><li><strong>The Database Problem</strong>: What Karpathy called a source of “more suffering” was reduced to a single request. The agent asked for a database, and Choreo provisioned and connected it, enabling persistence and a robust processing queue.</li><li><strong>The Authentication Maze</strong>: Instead of manual OAuth configuration, the agent leveraged Choreo’s managed auth, injecting credentials at runtime so the same build works across any environment.</li><li><strong>The Secret Key Scavenger Hunt</strong>: The .env.local headache disappeared. All keys were stored in Choreo’s secure vault and injected automatically at runtime. The plumbing just worked.</li></ul><p>This entire end-to-end process, from idea to a live, secure application, started with the same conversational prompt we used to generate the initial design document:</p><pre>I want to create POC for a Menu Visualizer app as follows,<br>- Users photo a restaurant menu for upload<br>- Go (single file) backend extracts menu content with GPT-4o XML structured output and generates dish images using Replicate (polling) API<br>- PostgreSQL DB (with gorm) stores menu text and all image blobs<br>- React (plain css) app displays the results<br><br>Create a complete SDD.md for this app?</pre><p>If you want to explore the final result or reproduce this workflow yourself, all the resources are available:</p><ul><li><strong>Final Application Code</strong>: The complete source code for the MenuGen rebuild is available from,</li></ul><p><a href="https://github.com/isala404/menugen">GitHub - isala404/menugen</a></p><ul><li><strong>Replicate OpenAPI Specification</strong>: To make the Replicate API discoverable in the Choreo Marketplace, we created a custom OpenAPI spec. You can find the <a href="https://github.com/isala404/menugen/blob/main/replicate.yaml">replicate-openapi.yaml</a> file in the project repository.</li><li><strong>Connecting the Dots (Choreo MCP Server)</strong>: This is the secret sauce that makes the agent platform-aware. <a href="https://medium.com/choreo-tech-blog/enhancing-developer-workflows-with-mcp-support-in-choreo-cli-b1acab1b3fd3">This article</a> walks you through how to configure it.</li></ul><p>Karpathy’s experience was a perfect diagnosis of a widespread problem: the operational complexity that smothers creative momentum. By giving the AI agent a reliable, auditable bridge to the underlying infrastructure, the developer stays focused on the product. You get to remain in that exhilarating “vibe coding” moment, while the repetitive, painful plumbing that turns prototypes into production systems is handled for you.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e54bc0bd491a" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/how-we-used-an-ai-agent-to-skip-the-devops-grind-e54bc0bd491a">How We Used an AI Agent to Skip the DevOps Grind</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why OAuth2 for SPAs Is Harder Than the Tutorials Make It Look]]></title>
            <link>https://medium.com/choreo-tech-blog/why-oauth2-for-spas-is-harder-than-the-tutorials-make-it-look-ad1f6578b1ed?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/ad1f6578b1ed</guid>
            <category><![CDATA[internaldeveloperplatform]]></category>
            <category><![CDATA[authentication-solution]]></category>
            <category><![CDATA[choreo]]></category>
            <category><![CDATA[single-page-applications]]></category>
            <category><![CDATA[oauth2]]></category>
            <dc:creator><![CDATA[Senthalan Kanagalingam]]></dc:creator>
            <pubDate>Tue, 08 Jul 2025 04:27:29 GMT</pubDate>
            <atom:updated>2025-07-08T04:27:29.171Z</atom:updated>
            <content:encoded><![CDATA[<p>You’ve probably been there: building a Single Page Application (SPA), needing authentication, and thinking “OAuth2 is a standard, this should be straightforward.” Then you dive into the implementation and realize the tutorials all conveniently skip the hard parts.</p><p>Three weeks later, you’re debugging redirect loops at midnight, questioning your life choices, and wondering why something that’s supposed to be “standard” feels so fragile.</p><p>After years of working on identity solutions and helping teams implement OAuth2 in production SPAs, I can tell you that this frustration is universal. Here’s what those tutorials don’t tell you about OAuth2 in SPAs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HHvzEobFkZsIwkkb" /></figure><p>Over the next few sections, we’ll walk through the specific ways OAuth2 implementations break down in production: the grant type confusion that leads teams astray, the impossible token storage decisions, the refresh token nightmares that cause random logouts, and why even popular SDKs don’t actually solve these fundamental problems. Then we’ll explore a different architectural approach that sidesteps these issues entirely.</p><h3>The Grant Type Maze That No One Explains</h3><p>Every OAuth2 tutorial starts the same way: “First, choose your grant type!” followed by a neat little comparison table. What they don’t mention is that the “right” answer has changed multiple times, and half the information on the internet is outdated.</p><p>In my experience working with identity systems, I’ve seen the same grant type mistakes over and over, often discovered only during security audits or production incidents.</p><h4>The Implicit Grant Legacy Problem</h4><p>Most tutorials from 2018 to 2020 recommended the Implicit grant for SPAs, but the OAuth2 Security Best Current Practices RFC now considers it harmful. As of OAuth 2.1, the Implicit grant has been completely removed from the specification due to security vulnerabilities with tokens exposed in URL fragments. Despite this, outdated blogs and Stack Overflow answers still point developers down this dangerous path.</p><h4>The Client Credentials Confusion</h4><p>Here’s a common developer thought process: “My API is protected and requires a token to invoke it. Let me just use Client Credentials to get a token.” This seems logical at first glance, especially when you’re frustrated with OAuth2 complexity and just want something that works.</p><p>This is fundamentally wrong for SPAs, and I see it more often than you’d expect. Client Credentials is designed for server-to-server communication where you can securely store secrets. In a SPA:</p><ul><li>The client secret is exposed in the JavaScript bundle</li><li>Anyone can extract it and impersonate your application</li><li>You can’t differentiate between users, everyone has the same permissions</li></ul><p>I’ve encountered production applications doing exactly this during security reviews. The conversation usually starts with “why is your client secret visible in your JavaScript bundle?” and ends with emergency remediation work.</p><h4>Authorization Code + PKCE: The “Current” Recommendation</h4><p>So you switch to the Authorization Code flow with PKCE because that’s what the security best practices recommend. But here’s the thing: these recommendations keep evolving, and what’s “secure” today might be deprecated tomorrow.</p><p><strong>The Moving Target Problem</strong>: OAuth 2.0 originally recommended Implicit flow for SPAs. Tutorials, Stack Overflow answers, and official documentation all said it was the right choice for browser-based applications. Then security researchers found issues, and suddenly everyone’s telling you to use PKCE instead. Now OAuth 2.1 mandates PKCE for all clients and removes the Implicit flow entirely.</p><p>What’s next? Will there be OAuth 2.2 with new mandatory requirements? Will PKCE be replaced by something else? You’re not just implementing authentication, you’re constantly chasing evolving security standards, refactoring working code, and explaining to stakeholders why the “best practice” from six months ago is now considered harmful.</p><p>From an identity provider’s perspective, I’ve watched teams spend more time maintaining auth code than building the features their users actually want.</p><h3>Token Storage: The Problem No One Wants to Talk About</h3><p>The tutorials make token storage look simple: “Just store the token!” But each browser storage option comes with security trade-offs and implementation headaches.</p><h4>Cookies vs. HTML5 Storage: Pick Your Security Risk</h4><p><strong>Cookies</strong> are familiar but vulnerable to both XSS and CSRF attacks. Regular cookies can be accessed by any JavaScript on your page. HttpOnly cookies solve the XSS problem but create a new one: your SPA can’t access them via JavaScript, so you need to build and maintain your own backend proxy for every API call.</p><p><strong>localStorage and sessionStorage</strong> seem like obvious choices for SPAs. They’re easy to use and don’t get sent with every request. But they can be accessed via JavaScript, making them vulnerable to XSS attacks. Any script running on your page can read localStorage.getItem(‘access_token’). This includes third-party analytics scripts, compromised CDN resources, malicious browser extensions, and any XSS vulnerability in your application.</p><h4>Browser Memory vs. Web Workers: UX vs. Complexity</h4><p><strong>Storing tokens only in JavaScript memory</strong> sounds secure: no persistence, no cross-tab access, harder for attackers to reach. But the user experience is terrible. You lose your session every time you refresh the page, navigate to another site and come back, or experience any JavaScript error that reloads the page.</p><p><strong>Web Workers</strong> run in a separate context, making tokens inaccessible to the main thread. But they create debugging complexity, multi-tab synchronization issues, and still don’t solve persistence problems.</p><p>Every storage option forces you to choose between exposing tokens to XSS attacks, losing user sessions on page refresh, or building complex authentication infrastructure that you’ll spend months debugging.</p><h3>Token Refresh: Where Everything Falls Apart</h3><p>Token refresh is where most OAuth2 implementations completely break down in production. The tutorials show the happy path, “just use the refresh token to get a new access token”, but production is full of edge cases.</p><h4>The Multi-tab Synchronization Nightmare</h4><p>Modern OAuth security best practices require refresh token rotation, issuing a new refresh token each time an access token is refreshed and immediately invalidating the previous one. Each browser tab runs independently, but they all start with the same refresh token. When one tab refreshes and gets new tokens, the other tabs are left holding invalidated refresh tokens. Users get randomly logged out of some tabs but not others.</p><h4>The Concurrent Request Problem</h4><p>Here’s a scenario I’ve debugged multiple times: A dashboard makes multiple API calls on page load. When tokens expire, all calls fail simultaneously and trigger concurrent refresh attempts. The first refresh succeeds and invalidates the refresh token. The remaining attempts fail, causing the auth server to revoke all tokens. Users get logged out unexpectedly.</p><p>The race condition questions multiply: Do you trigger multiple refresh attempts? Queue the failed requests? How do you prevent the second refresh request from using an already-invalidated token? Most teams don’t handle this correctly.</p><p>Token refresh turns from a simple “get new token” operation into a complex distributed systems problem with race conditions and state synchronization issues.</p><h3>The SDK Trap: Hiding Complexity, Not Solving It</h3><p>At this point, many developers turn to OAuth2 SDKs. “Don’t reinvent the wheel”, so you pick a popular library and dive into the configuration.</p><p>The problem with SDKs isn’t that they’re hard to use, it’s that they make you think you’ve solved OAuth2, when really you’ve just hidden the complexity behind an API.</p><h4>The False Security of Abstraction</h4><p>SDKs abstract away the implementation details, but all those OAuth2 problems we just discussed? They’re still there:</p><p><strong>Token storage dilemma</strong>: The default storage method may vary, and you have to configure it correctly to balance between UX and security, you’re still vulnerable to XSS attacks, you just don’t realize it. The security risk doesn’t disappear because it’s hidden behind auth.getToken().</p><p><strong>Token refresh nightmares</strong>: The SDK handles refresh automatically, until it doesn’t work across multiple tabs and users get randomly logged out. Now you’re debugging someone else’s refresh logic instead of your own.</p><p><strong>Configuration complexity</strong>: Your auth config file still grows into a monster with dozens of options, and the documentation assumes you already know which ones you need. You still need to become an OAuth2 expert to configure the SDK correctly.</p><p>SDK updates break things regularly. I’ve seen teams stuck with libraries they picked six months ago that now require refactoring half their auth code to upgrade. You think you’ve solved OAuth2, but you’ve just moved the problems into a black box that breaks in production.</p><h3>The Real-World Consequences</h3><p>But the frustration goes beyond just technical complexity. These OAuth2 implementation challenges create real business impact:</p><p><strong>Security incidents and compliance violations</strong>: Token leakage through browser storage, session hijacking, and privilege escalation require incident response and expensive remediation. Auditors flag tokens in browser storage as security risks, triggering months of compliance work.</p><p><strong>Development velocity suffers</strong>: Teams spend 30–40% of their sprint capacity on auth-related fixes instead of building features. Product roadmaps slip because you’re constantly firefighting authentication issues instead of delivering value.</p><p>The cost isn’t just technical debt, it’s real business impact that compounds over time.</p><h3>The Fundamental Problem: Tokens Don’t Belong in Browsers</h3><p>Looking at all these problems together reveals a pattern: we kept trying to solve the wrong problem.</p><p>We keep trying to make browser-based token management secure, but browsers are fundamentally insecure environments. Think about it — you’re putting sensitive credentials in a runtime that executes arbitrary JavaScript from multiple sources, where any XSS vulnerability or malicious script can access your tokens. Every “solution” just shuffles the same security risks around while creating new problems.</p><p>Store tokens securely? Users lose sessions on page refresh. Make the UX smooth? You’re back to XSS vulnerabilities. Use complex SDKs? Now you’re debugging someone else’s authentication logic. Roll your own? You’ve just signed up to become an OAuth2 expert and maintain complex security code forever.</p><p><strong>The core insight:</strong></p><blockquote>“Tokens don’t need to exist in browser JavaScript at all”</blockquote><p>The industry is quietly moving toward Backend-for-Frontend (BFF) architectures for exactly these reasons. Your SPA makes API calls through a BFF layer that handles OAuth complexity and securely forwards requests to your APIs. The browser never sees an access token, refresh token, or any OAuth complexity.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oaUJhQBIhT0knt9X" /></figure><p>This isn’t a new pattern — it’s how server-rendered applications have worked forever. We just got distracted by the “single page” part and forgot that SPAs can still have backends. Instead of browser-based token management, the BFF handles OAuth2 flows, manages tokens securely, and proxies API requests. The browser only needs to make normal HTTP requests.</p><h3>A Different Approach: Platform-Managed Authentication</h3><p>This is exactly why we built managed authentication into Choreo. After watching countless teams struggle with OAuth2 complexity, the pattern became clear — developers kept saying the same thing: “We just want authentication that works reliably without becoming OAuth2 experts.”</p><p>Rather than asking teams to become OAuth2 experts or build their own BFF layers, we implemented the BFF pattern at the platform level. This eliminates the burden of implementing OAuth/OIDC requirements and removes the need for applications to manage tokens issued by identity providers.</p><h4>Enable Authentication with One Toggle</h4><p>Teams enable <a href="https://wso2.com/choreo/docs/authentication-and-authorization/secure-web-applications-with-managed-authentication/">Choreo’s managed authentication</a> and follow clear guides on which grant types to enable, without having to manage tokens, handle refresh logic, or deal with the complex state synchronization issues we discussed earlier. Teams can easily connect with any OIDC-compliant identity provider directly from the Choreo console.</p><h4>Add a Login Button That’s Surprisingly Simple</h4><p>To allow Choreo to manage sign-in functionality, teams implement a simple authentication flow:</p><pre>// Sign in<br>&lt;button onClick={() =&gt; window.location.href = &#39;/auth/login&#39;}&gt;<br>  Sign In<br>&lt;/button&gt;<br><br>// Sign out<br>&lt;button onClick={() =&gt; window.location.href = &#39;/auth/logout&#39;}&gt;<br>  Sign Out<br>&lt;/button&gt;<br><br>// Check if logged in<br>fetch(&#39;/auth/userinfo&#39;)<br>  .then(response =&gt; response.ok ? response.json() : null)<br>  .then(user =&gt; console.log(user?.name || &#39;Not logged in&#39;));</pre><h4>API Calls Without Token Management</h4><p>For APIs deployed in Choreo, invocations work relative to the app URL. APIs are invoked via &lt;app-url&gt;/choreo-apis/&lt;api-path&gt;. The authenticated session details are used during API invocation to enforce access control automatically.</p><p>No manual token attachment, no refresh logic, no concurrent request handling:</p><pre>// Just call APIs normally<br>fetch(&#39;/choreo-apis/orders&#39;)<br>  .then(response =&gt; response.json())<br>  .then(data =&gt; setOrders(data));</pre><h3>Stop Fighting OAuth2, Start Shipping Features</h3><p>Your users don’t care about OAuth2 implementation details. They want your application to work reliably. Every hour you spend debugging token refresh logic is time you’re not spending on features that matter to your business.</p><p>When you’re staring at browser network tabs at 2 AM wondering why tokens work in Chrome but fail in Safari, or explaining to stakeholders why the security best practice from six months ago is now considered harmful, remember: this problem is already solved.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sQ6tpA4D1FdYuxg2" /></figure><p>Next time you’re planning authentication for a production SPA, ask yourself: Do you want to spend the next month becoming an OAuth2 expert, or do you want to ship features your users actually care about?</p><p><strong>Ready to skip the OAuth2 complexity?</strong> Try <a href="https://choreo.dev/">Choreo’s</a> managed authentication — it’s free to get started, and your future self will thank you when you’re shipping features instead of debugging token refresh race conditions.</p><blockquote><em>OAuth2 doesn’t have to be the hardest part of your SPA development. Sometimes the best code is the code you don’t have to write.</em></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ad1f6578b1ed" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/why-oauth2-for-spas-is-harder-than-the-tutorials-make-it-look-ad1f6578b1ed">Why OAuth2 for SPAs Is Harder Than the Tutorials Make It Look</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Enhancing Developer Workflows with MCP Support in Choreo CLI]]></title>
            <link>https://medium.com/choreo-tech-blog/enhancing-developer-workflows-with-mcp-support-in-choreo-cli-b1acab1b3fd3?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/b1acab1b3fd3</guid>
            <category><![CDATA[choreo]]></category>
            <category><![CDATA[ai-agent]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[model-context-protocol]]></category>
            <category><![CDATA[mcp-server]]></category>
            <dc:creator><![CDATA[Charith Rajitha]]></dc:creator>
            <pubDate>Tue, 17 Jun 2025 05:01:12 GMT</pubDate>
            <atom:updated>2025-06-17T05:01:12.583Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*s3oG8fNW4lDf91yNEsLRXg.jpeg" /></figure><p>AI agents are quickly becoming indispensable in modern software development. From generating code and managing builds to handling deployments and debugging, these agents streamline day-to-day engineering tasks. However, for AI agents to truly operate effectively in real-world environments, they need access to context — structured, dynamic, and actionable information about your code, tools, and systems.This is where the Model Context Protocol (MCP) comes in.</p><h3>What is MCP?</h3><p>Model Context Protocol (MCP) is a standard for exposing structured context to language model agents. MCP acts as a bridge between your tools (like IDEs, CLIs, or APIs) and the AI agents interacting with them. It allows models to understand and act on the current state of your projects, environments, and components through a unified protocol.</p><h4>Why MCP Matters for Choreo</h4><p>Choreo, an internal developer platform for building, deploying, and managing cloud-native applications, now supports MCP via the Choreo CLI. This opens the door for powerful AI-assisted operations — right from your code editor (VS Code, Cursor, etc.).</p><p>With Choreo’s MCP integration, AI agents can:</p><ul><li>Understand the current structure of your Choreo projects</li><li>Create or modify components</li><li>Trigger builds and deployments</li><li>Retrieve and analyze logs</li><li>All through natural language interactions</li></ul><h3>Getting Started</h3><ol><li>Install Choreo CLI</li></ol><p><strong>For Linux and Mac OS</strong></p><blockquote>curl -o- <a href="https://cli.choreo.dev/install.sh">https://cli.choreo.dev/install.sh</a> | bash</blockquote><p><strong>For Windows(via PowerShell)</strong></p><blockquote>iwr <a href="https://cli.choreo.dev/install.ps1">https://cli.choreo.dev/install.ps1</a> -useb | iex</blockquote><p>After installing you can verify your installation by running <strong>choreo -v</strong></p><p>2. Follow the steps below to use Choreo MCP with your preferred code editor</p><ul><li><a href="https://code.visualstudio.com/docs/copilot/chat/mcp-servers"><strong>VS Code</strong></a></li></ul><pre>&quot;mcp&quot;: {<br>       &quot;inputs&quot;: [],<br>       &quot;servers&quot;: {<br>           &quot;mcp-choreo&quot;: {<br>               &quot;command&quot;: &quot;choreo&quot;,<br>               &quot;args&quot;: [<br>                   &quot;start-mcp-server&quot;<br>               ],<br>               &quot;env&quot;: {}<br>           }<br>       }<br>   },</pre><ul><li><a href="https://docs.cursor.com/context/model-context-protocol#model-context-protocol"><strong>Cursor</strong></a></li></ul><pre>{<br> &quot;mcpServers&quot;: {<br>   &quot;choreo&quot;: {<br>     &quot;type&quot;: &quot;stdio&quot;,<br>     &quot;command&quot;: &quot;choreo&quot;,<br>     &quot;args&quot;: [<br>         &quot;start-mcp-server&quot;<br>     ]<br> }<br>}</pre><p>3. The Choreo MCP server does not implement authentication via chat interfaces. Therefore, users must login to choreo using the Choreo CLI using the following command.</p><blockquote>choreo login</blockquote><p>This authenticates the CLI and establishes the context for AI-driven operations via MCP.</p><h3>Choreo MCP in Action: How I vibe deployed a service in Choreo</h3><p>With the recent introduction of MCP support for the Choreo CLI, I decided to explore whether I could build and deploy a simple backend service entirely through <em>prompt-driven development</em> — no manual code writing, no clicking through UIs. Just prompts.</p><h3>The Plan</h3><p>I wanted to create a minimal Express.js service to manage a collection of books. The requirements were simple:</p><p>A REST API with the following endpoints:</p><ul><li>POST /books — Add a new book</li><li>GET /books — Retrieve all books</li><li>GET /books/{id} — Retrieve a book by ID</li></ul><p>Each book should have:</p><ul><li>name</li><li>author</li><li>An auto-generated id</li></ul><h3>Prompt-Driven Development</h3><p>So I kicked things off with a simple prompt:</p><pre>Create an Express.js service which does the following: &quot;Book manager&quot;<br> It has the following endpoints:<br> POST /books – add a book to the bookstore<br> GET /books – get all the books<br> GET /books/{id} – get specific book by id<br> The book object contains: name, author. An id will be automatically created when adding the book.</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*F1oriCDFRedLmTc_" /></figure><p>With the help of GitHub Copilot and some quick API testing via prompts like:</p><pre>Start the server<br>Test the API</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Dwt8Ks4RagTybK-g" /></figure><p>I was able to verify that the service worked as expected.</p><p>Next, I moved to deployment. I used the following prompt to initialize and push my code to GitHub:</p><pre>Create a GitHub repository &quot;choreo-mcp-demo&quot; and push this service to the repo</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*RerRphslACgJmOfV" /></figure><p>Then, I created a Choreo component using the CLI with this prompt:</p><pre>Create the book-manager component in Choreo<br>Endpoint type: REST</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*wTaUGNF0SeaLXK9N" /></figure><pre>Create a build from latest commit</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CzzyxJ2CYg_wyccJ" /></figure><pre>Check the build status</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*X2sallP6KGe8hfVo" /></figure><pre>Get the deployment status of the component</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ZnCtI1RBI2QGKwF_" /></figure><p>I tested the API using following prompts</p><pre>Invoke the /books endpoint</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*nia3JWDZllnpsnWH" /></figure><pre>Generate a test key for the development environment</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bdufuKMkndO61vMi" /></figure><pre>Create a curl command to invoke the api with the token</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zhvIqE2IvXIpzPaH" /></figure><p>In just a few steps — all prompt-driven — the service was deployed and live on Choreo. No UI interaction needed, just pure prompts.</p><p>This experiment demonstrated how <em>vibe coding</em> — building entirely through AI-assisted prompts combined with Choreo’s new MCP capabilities can deliver a seamless developer experience from ideation to deployment. It’s fast, efficient, and surprisingly empowering.</p><p>Whether you’re a solo developer prototyping an idea or part of a team delivering production services, Choreo MCP makes the deployment pipeline effortless.</p><p>Ready to try it yourself? Try out into <a href="https://choreo.dev/">Choreo</a> today, and explore how Choreo MCP can revolutionize your development and deployment workflow. Check out the <a href="https://wso2.com/choreo/docs/">official documentation</a> to get started, and see just how far you can go with only a few well-crafted prompts.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b1acab1b3fd3" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/enhancing-developer-workflows-with-mcp-support-in-choreo-cli-b1acab1b3fd3">Enhancing Developer Workflows with MCP Support in Choreo CLI</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a simple AI-Integrated Food Ordering App with Next.js, GPT and Choreo]]></title>
            <link>https://medium.com/choreo-tech-blog/building-a-simple-ai-integrated-food-ordering-app-with-next-js-gpt-and-choreo-737e446289f0?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/737e446289f0</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[choreo]]></category>
            <category><![CDATA[wso2]]></category>
            <category><![CDATA[internaldeveloperplatform]]></category>
            <category><![CDATA[nextjs]]></category>
            <dc:creator><![CDATA[Lakshan Sivagnanasothy]]></dc:creator>
            <pubDate>Mon, 16 Jun 2025 12:02:23 GMT</pubDate>
            <atom:updated>2025-06-16T12:02:23.225Z</atom:updated>
            <content:encoded><![CDATA[<h3>Building an AI-Integrated Food Ordering App with Next.js, GPT and Choreo</h3><p>In today’s world, AI is no longer a buzzword — it’s an integral part of how modern apps are built. From chatbots to personalized recommendations, AI is quietly transforming user experiences. As a developer, learning how to blend AI with app development is not just exciting — it’s essential.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xQ6gEEAQ1cPbP7daVHNZUg.png" /><figcaption>QuickEats app running live on Choreo</figcaption></figure><p>In this blog, we’ll explore <strong>QuickEats</strong>, a simple AI-Integrated food ordering app. If you already have a full-stack app running in production, this will give you practical ideas on how to seamlessly integrate AI into your existing architecture. Whether you’re a student, a junior developer, or a curious learner, this app will spark ideas on integrating AI into real-world scenarios and building intelligent applications from end to end. By the end of this blog, you’ll have deployed it on <a href="https://choreo.dev/"><strong>Choreo</strong></a>, seeing how it simplifies taking your code to production in 5 minutes!</p><h3>QuickEats</h3><p><strong>QuickEats</strong> is a food ordering app which lets users browse a curated menu, add items to their cart, and place orders through a simple checkout flow. To make the experience smarter and more interactive, we’ve integrated AI in key parts of the user journey. Here are the three powerful AI features built into this app:</p><ol><li><strong>Food Assistant Chatbot</strong></li></ol><p>This intelligent chatbot can answer questions about the menu, suggest dishes based on your cravings, or even help you customize your order with natural, conversational interactions.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/328/1*fgs6jWRTFhDS2teoNgKPKg.png" /></figure><p><strong>2. Smart Order Summary Generator</strong><br>To make your experience unique, once your order is placed, this feature leverages GPT to craft a <em>fun, personalized message</em> that intelligently summarizes your order details, providing a delightful and accurate confirmation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/514/1*Bq4ILJdkmq3-CPoR-dBdyA.png" /></figure><p><strong>3. Personalized Food Recommendations</strong><br>Based on previous orders or food preferences, it gives tailored dish suggestions that you’re highly likely to love, ensuring you always find something satisfying.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*pnaFvOigA4nnWHE91ymkAQ.png" /></figure><h3>Tech Stack</h3><ul><li><a href="https://nextjs.org/"><strong>Next.js</strong></a><strong> — </strong>For the frontend, we opted for Next.js,<strong> </strong>a powerful React framework. Beyond speed, it provides an exceptional developer experience with features like API routes, routing, and image optimization built-in, making it a robust choice for scalable applications.</li><li><a href="https://platform.openai.com/docs/overview"><strong>OpenAI GPT</strong></a><strong> — </strong>This is the core of QuickEats’ AI capabilities (Chatbot, smart order summary and recommendation). GPT models excel at understanding complex human language and generating coherent, contextually relevant, and even creative text.</li><li><a href="https://wso2.com/choreo/docs/what-is-choreo/"><strong>Choreo</strong></a><strong> — </strong>An AI-native Internal Developer Platform (IDP) which simplifies a developer’s journey from code to production. You can connect your Git repo, build, deploy (across multiple environments), manage and monitor cloud-native applications in real time (with AI guiding you every step of the way).</li></ul><h3>AI Features in QuickEats</h3><p>All 3 AI features in QuickEats — food assistant chatbot, smart order summary generator and personalized food recommendations — are implemented using simple prompt engineering. We use simple, effective prompts that include relevant context, tone, constraints (like word count), and user data.</p><p>Here’s how we implement <strong>Personalized Food Recommendations</strong> using simple prompting:</p><pre>const previous = lastOrder?.map((item) =&gt; item.name).join(&quot;, &quot;) || &quot;no previous orders&quot;;<br>const menuList = menuItems<br>  .map((item) =&gt; `${item.name}: ${item.description}`)<br>  .join(&quot;\n&quot;);<br><br>const prompt = `<br>You are a food assistant for an app. Based on this past order: ${previous}, suggest 1–2 new items from the menu below.<br><br>Menu:<br>${menuList}<br><br>Respond with a short and friendly message under 30 words.<br>`;</pre><p>This prompt is passed into the OpenAI API like this:</p><pre>const chatResponse = await openai.chat.completions.create({<br>  messages: [<br>    {<br>      role: &quot;system&quot;,<br>      content: &quot;You are a helpful food recommendation assistant.&quot;,<br>    },<br>    {<br>      role: &quot;user&quot;,<br>      content: prompt,<br>    },<br>  ],<br>  model: &quot;gpt-4.1&quot;,<br>});</pre><p>The model uses the provided context to generate short, friendly suggestions based on past user preferences. Similar approaches are used for generating natural-sounding order summaries and answering menu-related questions via the chatbot.</p><p>While this demo uses simple prompting, there’s a lot of room to improve. For production-grade applications, adopting <strong>self-hosted or fine-tuned language models</strong> offers greater control, improved performance, and compliance with internal data governance policies. Beyond basic prompting, mature AI implementations typically rely on techniques such as like <strong>few-shot prompting</strong>, <strong>retrieval-augmented generation (RAG)</strong>, and <strong>structured output formatting</strong> to ensure responses are context-aware, accurate, and aligned with business logic. Frameworks like <a href="https://www.langchain.com/"><strong>LangChain</strong></a> or <a href="https://learn.microsoft.com/en-us/semantic-kernel/overview/"><strong>Semantic Kernel</strong></a> can orchestrate complex, multi-step workflows, while <strong>vector databases</strong> (e.g., Pinecone, Weaviate, or Chroma) enhance personalization by enabling semantic search over user behavior or domain-specific knowledge. Together, these components form the foundation for building scalable, intelligent systems that go far beyond simple API calls — making AI a core, reliable part of production software.</p><h3>Source Code</h3><p>If you’re curious about how this demo app is built, feel free to dive into the code. <a href="https://github.com/LakshanSS/quickeats">https://github.com/LakshanSS/quickeats</a></p><h3>Ship to Production in 5 Minutes with Choreo</h3><p>You can take this app from<strong> code to live production in under 5 minutes</strong> using Choreo. No manual infrastructure setup, no complex CI/CD — just connect your GitHub repo, and Choreo takes care of the rest. <strong>It’s the fastest way to launch, scale, and show off QuickEats in production!</strong></p><ol><li>Login to <a href="https://choreo.dev/"><strong>Choreo</strong></a>.</li><li>Create a new <strong>Project</strong> and add a <strong>Component</strong> (Web Application).</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-AwFYVG5qfbWrYoMx1e7Zw.png" /></figure><p>3. Connect the <a href="https://github.com/LakshanSS/quickeats">GitHub repo</a> and choose:</p><ul><li><strong>Build Preset:</strong> NodeJS</li><li><strong>Language Version:</strong> 20.x.x</li><li><strong>Port:</strong> 8080</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-dfj4ef1vwK1m6ax0SvaUQ.png" /></figure><p>4. <strong>Add Environment Variable:</strong></p><ul><li>Go to <strong>DevOps → Configs &amp; Secrets</strong></li><li>Add: OPENAI_API_KEY -&gt; <a href="https://platform.openai.com/api-keys">your actual ke</a>y (mark as secret)</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gFoV12tuulPfi9vBWFHYRg.png" /></figure><p>5. <strong>Trigger a Build</strong> and ensure it completes successfully.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XrPJIL8yuh57jVceg-qSmw.png" /></figure><p>6. <strong>Deploy </strong>to<strong> Development </strong>Environment, test it using the Web App URL.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*OsyAHf7sw9tSZhCslPc3Sw.png" /></figure><p>7. Promote to <strong>Production </strong>Environment. You can also optionally create a short URL for your Web App.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*71TAg36f1Quk_1QuqUAJHg.png" /></figure><h3>The Road Ahead: Scaling QuickEats for Real-World Use with Choreo</h3><p>This is a very simple AI-Integrated app. To make it production-ready and scalable for a real-world scenario, we need to move beyond this simple demo. This involves enhancing the architecture, data management and AI strategy. <strong>The good news?</strong> <a href="https://choreo.dev/">Choreo</a> is perfectly suited to facilitate this evolution.</p><ol><li><strong>Dedicated backend services</strong></li></ol><p>Break down the application into dedicated microservices — for order processing, chatbot interactions, recommendations, payments, and delivery tracking etc. <strong>Choreo makes it easy</strong> to develop, deploy, observe, and manage these <a href="https://wso2.com/choreo/docs/develop-components/develop-services/service-component-overview/">service components</a> independently. This modular design improves scalability, maintainability, and team collaboration.</p><p><strong>2. Database Integration</strong></p><p>Any real-world food ordering app needs a reliable data layer. <strong>Choreo simplifies database integration </strong>by offering native support for connecting to <a href="https://wso2.com/choreo/docs/manage-databases-and-caches/choreo-managed-databases-and-caches/">managed cloud databases</a> or external data sources. Whether you’re storing orders, user profiles, or menu metadata, it’s easy to plug in a robust backend.</p><p><strong>3. Automate Repetitive Backend Workflows</strong></p><p>In a real-world food ordering app like QuickEats, there are several repetitive backend operations such as sending daily order summaries to restaurant partners, purging abandoned carts overnight to keep the system clean, syncing menu data from external vendors each morning, or updating popular item rankings based on order trends. Choreo’s <a href="https://wso2.com/choreo/docs/develop-components/develop-integrations/develop-a-scheduled-task/"><strong>Scheduled Tasks</strong></a> make it easy to automate routine backend operations by running code at defined intervals.</p><p><strong>4. Advanced AI Strategies</strong></p><p>For production-grade AI features, especially in enterprise environments, relying solely on external APIs may not always be ideal due to latency, cost, or data privacy concerns. Instead, you can deploy <strong>self-hosted or fine-tuned models. </strong>You can modularize AI features — such as recommendation engines, dynamic menu generators, or feedback summarizers — into standalone <a href="https://wso2.com/choreo/docs/develop-components/develop-services/develop-a-service/">services</a> in Choreo. Techniques like <strong>few-shot prompting</strong>, <strong>retrieval-augmented generation (RAG)</strong>, <strong>function calling</strong>, and <strong>structured output formatting</strong> allow your app to generate more accurate, personalized, and context-aware responses. Tools like <strong>LangChain</strong> can be used to orchestrate multi-step AI workflows, while <strong>vector databases</strong> enable semantic search and contextual retrieval for more intelligent, data-driven interactions.</p><p><strong>5. Authentication and Authorization</strong><br> Secure access is non-negotiable for real-world apps. Choreo provides built-in support for OAuth2, JWT, and third-party identity providers, making it easy to protect APIs and restrict access based on user roles. You can enable user authentication and enforce fine-grained authorization policies with minimal configuration.</p><p><strong>6. Event-Driven Architecture</strong><br>In a food ordering app like QuickEats, features such as real-time order status updates, delivery notifications, and automated actions triggered by events like payment completion are essential for delivering a responsive user experience. <strong>Choreo makes it easy</strong> to build these event-driven workflows by supporting asynchronous communication between services using <a href="https://wso2.com/choreo/docs/develop-components/develop-a-webhook/"><strong>Webhooks</strong></a>, <a href="https://wso2.com/choreo/docs/manage-message-brokers/create-choreo-managed-kafka-services/"><strong>Kafka</strong></a>, or other event sources.</p><p><strong>7. Auto Scaling and Resource Optimization</strong><br>During peak hours like lunch or dinner time, your app may experience sudden traffic spikes. Choreo’s built-in auto-scaling ensures your services adjust dynamically based on real-time load. You don’t need to manually manage replicas or worry about over-provisioning; <strong>Choreo intelligently scales resources up or down</strong> to maintain high availability and <a href="https://wso2.com/choreo/docs/monitoring-and-insights/cost-optimization/"><strong>optimize cost</strong></a>.</p><p>These are just a few examples of how you can scale and evolve QuickEats into a production-grade AI-powered app. With Choreo’s comprehensive platform, <strong>the possibilities are endless!</strong> — it supports you every step of the way!</p><h3>What’s Next?</h3><p>I encourage you to <strong>fork the </strong><a href="https://github.com/LakshanSS/quickeats"><strong>GitHub Repo</strong></a><strong> </strong>and experiment with QuickEats yourself. Deploy it in<strong> </strong><a href="https://choreo.dev/"><strong>Choreo</strong></a>, try out the AI features, and then challenge yourself to implement some of the production-ready improvements we discussed.</p><p>To dive deeper, explore the comprehensive <a href="https://wso2.com/choreo/docs/"><strong>Choreo Documentation</strong></a>. If you encounter any issues or have questions, don’t hesitate to join th<strong>e </strong><a href="https://discord.com/channels/955510916064092180/1027661953335820379"><strong>Choreo Discord channel</strong></a><strong>. </strong>It’s a great place to get support, discuss ideas, and connect with the community as you continue your development journey!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=737e446289f0" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/building-a-simple-ai-integrated-food-ordering-app-with-next-js-gpt-and-choreo-737e446289f0">Building a simple AI-Integrated Food Ordering App with Next.js, GPT and Choreo</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I Created and Deployed an Exchange Rate Dashboard App in 21 Minutes with Choreo]]></title>
            <link>https://medium.com/choreo-tech-blog/how-i-created-and-deployed-an-exchange-rate-dashboard-app-in-21-minutes-with-choreo-4d3a04ebb3a6?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/4d3a04ebb3a6</guid>
            <category><![CDATA[wso2]]></category>
            <category><![CDATA[react]]></category>
            <category><![CDATA[choreo]]></category>
            <category><![CDATA[mongodb]]></category>
            <category><![CDATA[go]]></category>
            <dc:creator><![CDATA[Chameera Rupasinghe]]></dc:creator>
            <pubDate>Mon, 19 May 2025 06:07:01 GMT</pubDate>
            <atom:updated>2025-06-17T07:28:53.959Z</atom:updated>
            <content:encoded><![CDATA[<h4>7 minutes thinking, 7 minutes coding, 7 minutes deploying. Full-stack apps shouldn’t be rocket science.</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*skMVMj5BKgYtN8Jh1CvR2g.png" /><figcaption>Generated by ChatGPT</figcaption></figure><p>A few months ago, I built a simple backend service in <a href="https://choreo.dev/">WSO2 Choreo</a> to scrape and return the daily USD to LKR exchange rate from a local bank’s website. The goal? Pure convenience. I was tired of clicking through layers of menus just to find the rate.</p><p>I deployed the service on Choreo and started using it myself. A few co-workers got wind of it and began using it too. Everything was chill — until one of them pinged me:</p><blockquote>“Hey, this is awesome, but can we see the past few days’ trends as well? It’s hard to get context from just today’s rate, especially with all the fluctuations lately.”</blockquote><p>That hit a nerve. Around the same time, the exchange rate was bouncing due to new tariff talks, and suddenly this weekend project felt… valuable.</p><p>I decided to evolve it — into a full-fledged, full-stack dashboard that not only fetches today’s exchange rate but also displays historical data in a sleek UI. I wanted this to be a complete product. And most importantly — I wanted it all live, in minutes, not hours.</p><h3>The Stack: Keep It Simple, Keep It Clean</h3><p>This is what I went with:</p><ul><li><strong>Frontend:</strong> React + Chart.js (Hosted as a Web App in Choreo)</li><li><strong>Backend:</strong> Go service exposing an API to fetch data from MongoDB (Hosted as a Service in Choreo)</li><li><strong>Job Service:</strong> Go job scheduled to fetch rates from the bank’s site periodically (Runs as a Scheduled Job in Choreo)</li><li><strong>Database:</strong> MongoDB Atlas (external, not hosted within Choreo)</li></ul><p>The frontend, backend, and job are all deployed as <strong>separate components in Choreo</strong>, communicating securely via environment-based connections.</p><h3>Why Choreo?</h3><p>I could’ve gone with Vercel for frontend and maybe Fly.io or AWS Lambda for backend and cron — but I didn’t want to:</p><ul><li>Glue services together manually.</li><li>Set up CI/CD pipelines for each part.</li><li>Think about API Gateways, Secrets, Scaling.</li></ul><p>Instead, with Choreo:</p><ul><li><strong>No platform concerns</strong> — I never touched Kubernetes or Docker.</li><li><strong>Secure connections</strong> — My services talk to each other without writing a line of auth/config code.</li><li><strong>Secrets management</strong> — Database credentials, API keys, all handled with a click.</li><li><strong>Dev → Prod</strong> — Environments supported out-of-the-box.</li><li><strong>Monitoring &amp; Logs</strong> — Without any extra setup.</li></ul><p>The killer feature? Connecting the frontend to the backend was just a matter of setting a connection from the UI. Done.</p><h3>Architecture</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kX23dlNlwV-j-OjfkIEhMg.png" /><figcaption>High level architecture</figcaption></figure><h3>The 21-Minute Breakdown</h3><p><strong>🧠 7 Minutes: Ideation</strong></p><ul><li>Got the idea to visualize exchange rate trends.</li><li>Decided to go full-stack.</li><li>Sketched component boundaries: job → DB → API → frontend.</li></ul><p><strong>👨‍💻 7 Minutes: Coding (with a little help from ChatGPT)</strong></p><ul><li>Wrote the cron job in Go to fetch exchange rate.</li><li>Built backend API in Go to serve the stored data.</li><li>Created a minimal React UI with a line chart.</li></ul><p><strong>🚀 7 Minutes: Deployment with Choreo</strong></p><ul><li>Pushed code to GitHub.</li><li>Created 3 components in Choreo (webapp, service, job).</li><li>Set up secrets and environment variables.</li><li>Defined a cron schedule for the job.</li><li>Connected components via the UI.</li><li>Hit Deploy. Everything just worked.</li></ul><h3>Code Sample: Fetching the Rate</h3><pre>req, _ := http.NewRequest(&quot;GET&quot;, &quot;https://www.sampath.lk/api/exchange-rates&quot;, nil)<br>req.Header.Set(&quot;User-Agent&quot;, &quot;My Custom Agent&quot;)<br>resp, _ := http.DefaultClient.Do(req)<br>// Parse USD rate, insert into MongoDB</pre><h3>Code Sample: Frontend Fetch</h3><pre>const res = await axios.get&lt;ExchangeRate&gt;(`${CHOREO_CONNECTION_URL}/latest-rate`);<br></pre><h3>Full Code</h3><p>👉 GitHub Repo: <a href="https://github.com/chameerar/usd-lkr-exchange-rate-dashboard">github.com/chameerar/usd-lkr-exchange-rate-dashboard</a></p><h3>Final Thoughts</h3><p>This project reminded me how much productivity skyrockets when the platform doesn’t get in the way. With Choreo, I didn’t need to <em>fight</em> the cloud to bring an idea to life.</p><p>Whether you’re a solo dev hacking on a weekend project or a team evaluating microservice-friendly platforms — give Choreo a shot. It’s the platform that lets you forget about the platform.</p><p>✍️ <em>Built with Choreo. Inspired by curiosity. Powered by caffeine.</em></p><h3>References</h3><ul><li><a href="https://choreo.dev/">You Code, We Orchestrate</a></li><li><a href="https://www.mongodb.com/products/platform/atlas-database?tck=exp-815">Atlas Database</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4d3a04ebb3a6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/how-i-created-and-deployed-an-exchange-rate-dashboard-app-in-21-minutes-with-choreo-4d3a04ebb3a6">How I Created and Deployed an Exchange Rate Dashboard App in 21 Minutes with Choreo</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Chat With Your PDFs — Deploying a Simple RAG Application with Langchain, OpenAI and Choreo]]></title>
            <link>https://medium.com/choreo-tech-blog/chat-with-your-pdfs-deploying-a-simple-rag-application-with-langchain-openai-and-choreo-913b924d6784?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/913b924d6784</guid>
            <category><![CDATA[choreo]]></category>
            <category><![CDATA[rags]]></category>
            <category><![CDATA[chatgpt]]></category>
            <category><![CDATA[openai]]></category>
            <category><![CDATA[llm]]></category>
            <dc:creator><![CDATA[Rashmin Mudunkotuwa]]></dc:creator>
            <pubDate>Fri, 07 Feb 2025 11:18:24 GMT</pubDate>
            <atom:updated>2025-02-07T11:18:24.032Z</atom:updated>
            <content:encoded><![CDATA[<h3>Chat With Your PDFs — Deploying a Simple RAG Application with Langchain, OpenAI and Choreo</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2UfyjR-ZxvCNHpZx1pKqYA.png" /></figure><p>Large Language Models have turned the technology world upside down in the past two years and continue to disrupt the technology landscape. What ChatGPT started has been supported by other technology giants with the creation of LLMs like Claude, Gemini, and Llama. Both tech-savvy individuals and those less familiar with technology have integrated LLMs into their daily lives.</p><p>One caveat of LLMs can be said as not have enough context about our own data or custom information. LLMs are trained on a specific data set and able to answer almost all the questions we ask using their language skills. But if we want to ask it about a specific custom piece of data, which is outside of its knowledge base, it would struggle and hallucinate. RAG or Retrieval-Augmented Generation, is a type of application that is designed to overcome this challenge. This combines a custom knowledge-base of our own and a LLMs language ability to refine the output of the LLM and make it answer queries about custom/specific scenarios more accurately.</p><p>A birds-eye view of a RAG system can be shown below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*WbeD2azuXBnWZi9sh6RMtA.png" /><figcaption>Birds-eye-view of a RAG Application</figcaption></figure><p>In simple terms, when a user asks a query, a RAG application queries the connected knowledge base for relevant context and bundles that context with the user&#39;s query, and sends it to the LLM. LLM then processes the data and provides an appropriate answer.</p><h3>Steps of Creating a RAG Application</h3><p>We can divide the creation of a simple RAG application into 3 parts.</p><ol><li>Data Collection &amp; Preparation</li><li>Embedding and indexing data</li><li>Retrieving indexed data and quarrying the LLM.</li></ol><p>Let&#39;s look at the 3 steps in detail below.</p><h4>Data Collection and Preparation</h4><p>In this step, all relevant data must be collected and pre-processed if necessary. These data can be PDFs, Markdown files, Text files and even Plain Text.</p><h4>Embedding and indexing data</h4><p>In this step, we send the collected data to, what we call an “Embedding Model” and it returns a vector representation, a numerical model, of the provided data. Those “vector embeddings” are then stored in a “Vector Database”. Vector database is a database that stores mathematical representations of structured and unstructured data.</p><h4>Retrieving data embeddings and Quarrying the LLM</h4><p>When a prompt is provided, the vector database is queried to find relevant data context to the prompt, and the found context is sent along with the prompt to a LLM, which in turn takes the prompt and the provided data into account and responds with a relevant answer.</p><p>As the title already says, in this article let&#39;s see how we can create a RAG application to ask questions about a PDF file we provide. In a sense, we could “chat” with our PDF file by utilizing this application.</p><p>To create the RAG application we use Langchain, which is a popular Python framework for creating RAG applications. As the underlying models, we are utilizing OpenAIs GPT models and embedding models. As for the knowledge base, we are using “Pinecorne” which is a popular vector database that you can try online for free. Even after all these, we would need to expose our application to the internet for it to be useful, for this, we use WSO2’s state-of-the-art integration platform as a service, Choreo. We would deploy our Python/Langchain application on Choreo and expose it as an API anyone can invoke.</p><p>Overall our tech-stack would look like the following.</p><ol><li><a href="https://www.langchain.com/"><strong>Langchain</strong></a> — For creating the RAG application</li><li><a href="https://platform.openai.com/"><strong>OpenAI Embedding Model </strong></a>— Embedding data</li><li><a href="https://www.pinecone.io/"><strong>Pinecorne</strong></a> — Storing vector embeddings</li><li><a href="https://platform.openai.com/"><strong>OpenAI GPT</strong></a><strong> </strong>— LLM</li><li><a href="https://console.choreo.dev/"><strong>WSO2 Choreo</strong></a><strong> </strong>— Building, Deploying, and Exposing our application to the public.</li></ol><h4>Simple RAG Architecture</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bTlE6lghgX7Ko6VJXRrB0A.png" /></figure><h3>Let&#39;s get coding!</h3><p>Before we start coding our application, you would need to create three accounts.</p><ol><li><a href="https://console.choreo.dev/">Choreo</a> Account — able to build and deploy your application</li><li><a href="https://platform.openai.com/">OpenAI Platform Account</a> — allows you to access OpenAI APIs</li><li><a href="https://www.pinecone.io/">Pinecone Account</a> — allows you to access the Pinecone serverless vector database.</li></ol><p>Then you need to get two API keys for OpenAPI and Pinecone</p><ol><li>OpenAI — Go to <a href="https://platform.openai.com/api-keys">https://platform.openai.com/api-keys</a> and create a new secret key. Copy and save it in a safe location.</li><li>Pinecone — Left Side Pane → Manage → API Keys → Create API Key. Copy and save it.</li></ol><p>I am using Python 3.11 and PyCharm IDE to develop this project.</p><p>First, you need to create a new project in PyCharm ( or your preferred IDE ) and add the following requirements.txt .</p><pre>langchain~=0.1.12<br>langchain-community<br>pinecone-client<br>langchain-openai<br>openai<br>langchain_pinecone<br>uvicorn~=0.30.5<br>fastapi~=0.112.0<br>pydantic~=1.10.17<br>pypdf</pre><p>Then add your Pinecone API Key and OpenAI API key to a .env file. Make sure <em>NEVER</em> to push this file to git!</p><pre>OPENAI_API_KEY=&quot;&quot;<br>PINECONE_API_KEY=&quot;&quot;</pre><p>After that copy <a href="https://github.com/rashm1n/RAG101/blob/master/dark-energy.pdf">this</a> PDF I’ve exacted from NASA [1], about dark matter, to your directory. After this, your directory would look like this</p><pre>.<br>├── .env<br>├── dark-energy.pdf<br>└── requirements.txt</pre><p>If you refer to our first step of creating a RAG application, the data collection (i.e. the pdf) and the setting up of the project is done. Next, we have to create the embeddings and store them in Pinecone. Let&#39;s create a file embed.py for this purpose.</p><pre>import os<br>from langchain_community.document_loaders import PyPDFLoader<br>from langchain_openai import OpenAIEmbeddings<br>from langchain.text_splitter import CharacterTextSplitter<br>from langchain_pinecone import PineconeVectorStore<br>from pinecone import Pinecone, ServerlessSpec<br><br>OPENAI_API_KEY = os.getenv(&quot;OPENAI_API_KEY&quot;)<br>PINECONE_API_KEY = os.getenv(&quot;PINECONE_API_KEY&quot;)<br><br>def create_or_update_index(texts, index_name, embedding):<br>    pc = Pinecone(api_key=os.environ.get(&quot;PINECONE_API_KEY&quot;))<br>    if index_name not in pc.list_indexes().names():<br>        pc.create_index(<br>            name=index_name,<br>            metric=&#39;cosine&#39;,<br>            dimension=1536,<br>            spec=ServerlessSpec(<br>                cloud=&#39;aws&#39;,<br>                region=&#39;us-east-1&#39;<br>            )<br>        )<br>        print(f&quot;Created new index: {index_name}&quot;)<br>        vectorstore = PineconeVectorStore.from_documents(<br>            texts,<br>            embedding=embedding,<br>            index_name=index_name<br>        )<br>    else:<br>        print(f&quot;Index {index_name} already exists&quot;)<br>        vectorstore = PineconeVectorStore.from_existing_index(<br>            index_name=index_name,<br>            embedding=embedding<br>        )<br><br>    return vectorstore<br><br>pdf_path = &quot;dark-energy.pdf&quot;<br>loader = PyPDFLoader(pdf_path)<br>documents = loader.load()<br><br>text_splitter = CharacterTextSplitter(<br>    chunk_size=1000,<br>    chunk_overlap=200<br>)<br><br>texts = text_splitter.split_documents(documents)<br><br>embedding = OpenAIEmbeddings(model=&quot;text-embedding-ada-002&quot;)<br>index_name = &quot;pdf-index&quot;<br><br>vectorstore = create_or_update_index(texts, index_name, embedding)</pre><p>Here we utilize the PyPDFLoader from langchain_community library to load our stored PDF. Then we need to break down our large PDF into small chunks of text, for this purpose we can use CharacterTextSplitter which specifies a chunk_size (maximum size of a chunk) and a chunk_overlap (amount of overlap between two chunks). The following web application <strong>“</strong><a href="https://chunkviz.up.railway.app/"><strong>ChunkViz</strong></a><strong>”</strong> can visualize the chunking and overlapping of chunks in a text neatly.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VUFG8RsG8zq8P3TC5ffhSA.png" /><figcaption>ChunkViz</figcaption></figure><p>The dark green parts are overlapping portions of the chunks.</p><p>After defining the TextSplitter we can input the document to the text splitter and get chunked text.</p><pre>texts = text_splitter.split_documents(documents)</pre><p>After that, next step is the embedding process. We need to send the chunked texts into an embedding model and get vector embeddings for those in return. In this case, we are using the text-embedding-ada-002 model of OpenAI.</p><pre>embedding = OpenAIEmbeddings(model=&quot;text-embedding-ada-002&quot;)</pre><p>After getting the embeddings we can create a new index in Pinecone vector db and store our embeddings using create_or_update_index the method. This method uses pc.create_index the method of Pinecone Python library to send the embeddings to a new index.</p><p>After creating the <a href="http://embed.py">embed.py</a> file, install the dependencies by running,</p><pre>pip install -r requirements.txt</pre><p>Then you can run the embed.py .</p><pre>python3 embed.py</pre><p>This would take some time and if all goes well, you will see the following message.</p><pre>Created new index: pdf-index</pre><p>And now If you go to the Pinecone UI, you’ll see a new index has been created!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Lhwe6GjcuKbKKcXdQ7DoUw.png" /></figure><p>Now, we have to create an API that would allow a user to ask questions about the contents of the PDF. For the creation of the API, we will use <a href="https://fastapi.tiangolo.com/"><strong>FastAPI</strong></a> which is a powerful web framework for Python.</p><p>Create the following api.py file.</p><pre>import os<br>from fastapi import FastAPI<br>from pydantic import BaseModel<br>from langchain_openai import OpenAIEmbeddings, ChatOpenAI<br>from langchain_pinecone import PineconeVectorStore<br>from langchain.chains import RetrievalQA<br>from langchain.prompts import PromptTemplate<br>from pinecone import Pinecone<br><br>app = FastAPI()<br><br>OPENAI_API_KEY = os.getenv(&quot;OPENAI_API_KEY&quot;)<br>PINECONE_API_KEY = os.getenv(&quot;PINECONE_API_KEY&quot;)<br><br># Initialize Pinecone<br>pc = Pinecone(api_key=PINECONE_API_KEY)<br><br>embedding = OpenAIEmbeddings(model=&quot;text-embedding-ada-002&quot;)<br>index_name = &quot;pdf-index&quot;<br><br>vectorstore = PineconeVectorStore.from_existing_index(<br>    index_name=index_name,<br>    embedding=embedding<br>)<br><br># Initialize ChatOpenAI<br>llm = ChatOpenAI(<br>    openai_api_key=OPENAI_API_KEY,<br>    model_name=&#39;gpt-4o&#39;,<br>    temperature=0.0<br>)<br><br># Creating Prompt<br>prompt_template = &quot;&quot;&quot;Use the following pieces of context to answer the question at the end. <br>If you don&#39;t know the answer, just say that you don&#39;t know, don&#39;t try to make up an answer.<br><br>{context}<br><br>Question: {question}<br>Provide a concise answer in 1-4 sentences:&quot;&quot;&quot;<br><br>PROMPT = PromptTemplate(<br>    template=prompt_template, input_variables=[&quot;context&quot;, &quot;question&quot;]<br>)<br><br># Creating a Langchain QA chain<br>qa = RetrievalQA.from_chain_type(<br>    llm=llm,<br>    chain_type=&quot;stuff&quot;,<br>    retriever=vectorstore.as_retriever(),<br>    chain_type_kwargs={&quot;prompt&quot;: PROMPT}<br>)<br><br>class Query(BaseModel):<br>    question: str<br>   <br># Create API Endpoint<br>@app.post(&quot;/ask&quot;)<br>async def ask_question(query: Query):<br>    response = qa.invoke(query.question)<br>    return {&quot;answer&quot;: response[&#39;result&#39;]}<br><br>if __name__ == &quot;__main__&quot;:<br>    import uvicorn<br>    uvicorn.run(app, host=&quot;0.0.0.0&quot;, port=8080)</pre><p>First, we will do the necessary initialization like setting up API Keys, Pinecone connection, and setting up a LLM connection using OpenAI’s gpt-4o model.</p><p>After that, we create a prompt-template which would be sent to the LLM. Here you can see two replaceable parts, {context} and {question} , context is the data we receive from Pinecone regarding the users question. This template would be populated by the original question and the relevant context received from Pinecone and then it would be sent to the LLM.</p><p>Then we need to create a QA (Question Answering) chain using Langchain and provide the created variables. This QA chain will answer questions based on the provided context, using the LLM.</p><p>Now, we can invoke this qa object inside a HTTP resource, /ask to finalize our application.</p><h3>Deploying the RAG Application</h3><p>Now that we have finished developing our application. We need to deploy it. For that, we will use <a href="https://choreo.dev"><strong>Choreo</strong></a>, a Kubernetes-based internal developer platform as a service by WSO2. We can deploy this application as a Python service without having to create any Dockerfiles, images, or Kubernetes configurations, all underlying tinkering would be managed by Choreo.</p><p>First you need to create a Procfile which will instruct how to start the application to a <a href="https://buildpacks.io/">Buildpack</a>.</p><pre>web: uvicorn api:app --host=0.0.0.0 --port=${PORT:-8080}</pre><p>Then create a component-config.yaml file in a .choreo directory. This is a Choreo-specific config that will configure the endpoint which is exposed to the internet.</p><pre>apiVersion: core.choreo.dev/v1beta1<br>kind: ComponentConfig<br>spec:<br>  inbound:<br>    - name: RAG API<br>      port: 8080<br>      type: REST<br>      networkVisibility: Public</pre><p>This would be the final directory structure.</p><pre>.<br>├── .choreo<br>│   └── component-config.yaml<br>├── .env<br>├── .gitignore<br>├── Procfile<br>├── api.py<br>├── dark-energy.pdf<br>├── embed.py<br>└── requirements.txt</pre><p>Now push the code to a GitHub repository. You can find the full application at <a href="https://github.com/rashm1n/RAG101"><strong><em>https://github.com/rashm1n/RAG101</em></strong></a></p><p>Now you are all set to deploy your application. Create a Python service in Choreo following the below steps.</p><ol><li>Create a <a href="http://choreo.dev"><strong>choreo.dev</strong></a> account if you don&#39;t have one already.</li><li>Create a project → Create a new Service and enter the following details.</li></ol><ul><li>Component Display Name — RAGApp</li><li>Public Repository URL — &lt;Your Git repository URL&gt;</li><li>Buildpack — Python</li><li>Python Project Directory — /</li><li>Language Version — 3.11.x</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lrz1amzgbvooPzjFhEiOFg.png" /><figcaption>Create Choreo Service</figcaption></figure><p>And build the service component.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7WmRpjX8iDWANOGRMfOG-A.png" /><figcaption>Build the Choroe Component</figcaption></figure><p>Now navigate to the deploy menu and click Configure &amp; Deploy. Create two Environment Variables (Mark as Secret) and add your API Keys. Choreo will securely store these as Kubernetes Secrets.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tI-32qPCxdQNHzYvujRyXw.png" /><figcaption>Deploy Page</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/586/1*UmUMiiyg_D7DYLza5la_EA.png" /><figcaption>Creating Environmental Varialbles as Sercrets</figcaption></figure><p>Then create next and Deploy the component. The deployed application would look like the following.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F1bwAapwvSD8tdbxke2eRA.png" /><figcaption>Deployed Application</figcaption></figure><p>Let&#39;s navigate to the Choreo Test Console and acquire a Test API Key to invoke our application. Since Choreo applications are protected by OAuth by default, you will need this API Key to test out the API. Copy the invoke-URL as well.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kxwl7oje6wL1Gz5O7mqTbA.png" /></figure><p>Then use the API-Key and Invoke URL as below in a curl and invoke your component.</p><pre>curl --location &#39;https://5d1fa89f-bb68-4cee-a1c9-5ca459e02768-dev.e1-us-cdp-2.choreoapis.dev/springproject/ragapp/v1.0/ask&#39; \<br>--header &#39;accept: */*&#39; \<br>--header &#39;API-Key: &lt;API-Key&gt;&#39;<br>--header &#39;Content-Type: application/json&#39; \<br>--data &#39;{&quot;question&quot;: &quot;What is dark energy?&quot;}&#39;</pre><p>And you will get a response according to your provided data! Within a few minutes, you are able to go from code to cloud and invoke your application over the internet.</p><p>In this article, we discussed about creating and deploying a RAG application which would give the function of asking questions about a PDF document of your choice. This is a very simle example of a RAG application and LLMs but you can make much more complicated applications utilizing these, and use Choreo to deploy them securely.</p><p>Please comment below if you have any questions. See you in another article.</p><h4><strong>Resources</strong></h4><p>[1] — <a href="https://science.nasa.gov/universe/the-universe-is-expanding-faster-these-days-and-dark-energy-is-responsible-so-what-is-dark-energy/">https://science.nasa.gov/universe/the-universe-is-expanding-faster-these-days-and-dark-energy-is-responsible-so-what-is-dark-energy/</a></p><p>[2] — <a href="https://choreo.dev">https://choreo.dev</a></p><p>[3] — <a href="https://python.langchain.com/v0.2/docs/introduction/">https://python.langchain.com/v0.2/docs/introduction/</a></p><p>[4] — <a href="https://platform.openai.com/docs/concepts">https://platform.openai.com/docs/concepts</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=913b924d6784" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/chat-with-your-pdfs-deploying-a-simple-rag-application-with-langchain-openai-and-choreo-913b924d6784">Chat With Your PDFs — Deploying a Simple RAG Application with Langchain, OpenAI and Choreo</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deploying Code from Bitbucket Cloud to Production with Choreo]]></title>
            <link>https://medium.com/choreo-tech-blog/deploying-code-from-bitbucket-cloud-to-production-with-choreo-319887a80fab?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/319887a80fab</guid>
            <dc:creator><![CDATA[Yashodha Samarawickrama]]></dc:creator>
            <pubDate>Thu, 28 Nov 2024 05:59:36 GMT</pubDate>
            <atom:updated>2024-11-28T05:59:36.340Z</atom:updated>
            <content:encoded><![CDATA[<p>Bitbucket stands out as one of the most popular Git providers, embraced by both enterprise organizations and individual developers alike. Choreo enhances this experience by allowing you to effortlessly connect your source repository. With Choreo, you can streamline your deployment process, ensuring that your code moves smoothly from development to production. This integration not only simplifies workflows but also accelerates the delivery of applications, empowering teams to bring their projects to life efficiently.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/433/0*_qCv4F1tXUQjyCHo" /></figure><p>In this article, we will walk you through how we can effectively use <a href="https://choreo.dev/">Choreo</a> to deploy a service written using Flask. We will be using <a href="https://github.com/wso2/choreo-samples/tree/main/python-flask-app">this sample</a> designed to showcase a restaurant reservation system. This API offers users the ability to effectively manage restaurant reservations. It supports various operations like creating, retrieving, updating, and deleting reservation entries.</p><h3>Pre requisites</h3><ol><li>A <a href="https://choreo.dev/">Choreo</a> user account</li><li>A <a href="https://bitbucket.org/">Bitbucket</a> account</li><li>Import this <a href="https://github.com/wso2/choreo-samples">repository</a> to create a new repository in your Bitbucket Workspace.</li></ol><p>Let’s get started with connecting your source code in Bitbucket to Choreo.</p><p><strong>Step 1 — Create a common credential in Choreo</strong></p><p><strong>1. </strong>Login to your Bitbucket account and navigate to <strong>Personal Bitbucket Settings</strong> under the <strong>User Settings </strong>section. From the left menu , select <strong>App passwords </strong>in the Access Management section. Click on <strong>Create App password </strong>and provide the following information.</p><p><strong>Label — </strong>Choreo console<br><strong>Scopes</strong> — <br> Account (Read), <br> Pull requests (Read/Write), <br> Repositories (Read/Write), <br> Webhooks (Read/Write)</p><p>Copy the generated app password and save it securely as you won’t be able to access it again.</p><p>2. Login to <a href="https://choreo.dev">Choreo</a>.</p><p>From the left menu of the Organization home page navigate to <strong>Settings</strong> and then in the ‘Credentials’ tab, click on <strong>+ Add Git Credentials</strong>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bQ2NrCSydmcxV-B2" /></figure><p>Provide the following information to create a new credential and click on save.</p><p><strong>Credential Name</strong> — BitbucketCredentials<br><strong> Service Provider — </strong>Bitbucket<br><strong>Username </strong>— Username of your Bitbucket Account<br><strong>Access Token — </strong>Copy paste the app password generated earlier</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/531/0*uqdMPE5aVCAmZkS4" /></figure><p>The credential you created should be listed under the common credential tab as shown below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bEuunEv-ZCh_6TcO" /></figure><p><strong>Step 2 — Create a component</strong></p><p>From the Organization home page click the <strong>+ Create Project</strong> button to create a new project with the name <strong>‘Reservation Management’</strong>. <br>Once the project is successfully created, navigate to the ‘<strong>Reservation Management’</strong> project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/521/0*wBP11hc7KV8Z_jRt" /></figure><p>Create a Service by providing the following information :<br><strong>Component Name — </strong>ReservationService<br><strong>Source Provider </strong>— Navigate to the Bitbucket tab<br><strong>Authorize with Bitbucket</strong> — Select the credential you created earlier</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*8r5ao6stMVpNGKZ1" /></figure><p><strong>User group — </strong>Select the workspace you created the repository under<br><strong>Repository — </strong>Select ‘choreo-samples’ or the repository name you provided<br><strong>Branch — </strong>Main<br><strong>Buildpack — </strong>Docker<br><strong>Docker Context — </strong>/python-flask-app<br><strong>Dockerfile — </strong>/python-flask-app/Dockerfile</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EUSuGV5Vuu-fYZVN" /></figure><p><strong>Step 3 — Build an image</strong></p><p>Once the component is created, you will be directed to the <strong>Build</strong> page, where the initial build for the latest commit in your repository will be in progress.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Xt_H-aUpCbdotEk0" /></figure><p>Once the build is successful, click on the <strong>‘Deploy’ </strong>link to navigate to the Deploy page.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Or8SvTlDvtisTA_M" /></figure><p><strong>Step 4 — Deploy to production</strong></p><p>Click on ‘Configure &amp; Deploy’ in the Set Up card.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*N4fpIW5fflmCGApC" /></figure><p>The service we just created is now ready to be deployed to the development environment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*6-jafkXO92ARAWiQ" /></figure><p>To promote this service to the production environment, click <strong>‘Promote’</strong> and select the ‘<strong>Use Development configuration</strong>’ option from the right drawer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*JOsUYhJJ5qskC5pj" /></figure><p><strong>Step 5 — Test the service</strong></p><p>Once the service is successfully promoted to production, navigate to the <strong>Test</strong> -&gt; <strong>Console </strong>page from the left menu.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gsnXwkJszKcqkexl" /></figure><p>Click on the <strong>POST</strong> request and enter the following schema to test the service we created.</p><p>{</p><p>“contact”: “011–123–1111”,</p><p>“reservationCreator”: “John Doe”,</p><p>“reservationId”: “1111”</p><p>}</p><p>Click on execute to add this new entry to the reservation management system and check if the response is successful.</p><p>Then, click on <strong>GET</strong> to send a request to retrieve the list of reservations and verify if the new reservation we just added is available.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*0QvXvOJZqSbmG7Vp" /></figure><p>You have successfully created a service and deployed it to production!</p><p><strong>Summary</strong></p><p>In this article, we demonstrated how to deploy a Python-based service for managing a list of reservations using Choreo. The API allows users to create, retrieve, update, and delete reservation entries. The process began with creating a new project in a Bitbucket workspace and connecting it to Choreo by creating a service component. We then built an image from the latest commit , deployed it to the development environment and promoted it to production to make it live. Finally, we tested the service to ensure everything was working as expected. Sign up to <a href="https://choreo.dev/">Choreo</a> for free to explore these features and unlock more possibilities!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=319887a80fab" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/deploying-code-from-bitbucket-cloud-to-production-with-choreo-319887a80fab">Deploying Code from Bitbucket Cloud to Production with Choreo</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Effortless Development of Cloud-Native Applications in Django with Choreo]]></title>
            <link>https://medium.com/choreo-tech-blog/effortless-development-of-cloud-native-applications-in-django-with-choreo-1ca4b349c58c?source=rss----a7ca74741cb8---4</link>
            <guid isPermaLink="false">https://medium.com/p/1ca4b349c58c</guid>
            <category><![CDATA[python]]></category>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[django-framework]]></category>
            <category><![CDATA[django]]></category>
            <category><![CDATA[deploy]]></category>
            <dc:creator><![CDATA[Lahiru De Silva]]></dc:creator>
            <pubDate>Wed, 04 Sep 2024 11:40:29 GMT</pubDate>
            <atom:updated>2024-09-04T11:40:29.729Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*O8pqlGumCRKKqx7ejeO2Ig.jpeg" /><figcaption>Photo by <a href="https://unsplash.com/@faisaldada?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Faisal</a> on <a href="https://unsplash.com/photos/black-and-yellow-box-on-white-table-BI465ksrlWs?utm_content=creditCopyText&amp;utm_medium=referral&amp;utm_source=unsplash">Unsplash</a></figcaption></figure><p>In recent years, Python has seen a surge in popularity for web application development, becoming a go-to language for developers worldwide. This rise can be attributed to Python’s simplicity, readability, and the rich ecosystem of frameworks it supports such as FastAPI, Flask, Django etc. Among these frameworks Django stands out as a comprehensive, “batteries-included” framework as it offers a wide range of features and tools that are ready to use out of the box. This enables developers to focus more time on implementing the actual business logic rather than having to worry about things like authentication and authorization, user management, database integration etc. So with Django, you can rapidly build your applications in no time without much hassle. Once your application is built and ready to launch, you may encounter a new set of challenges such as where to run, how to scale it with increasing traffic, monitoring and troubleshooting etc. This is where <a href="https://choreo.dev/?utm_source=me&amp;utm_medium=link&amp;utm_campaign=me_link_python_django_240904">Choreo</a> comes in.</p><p><a href="https://choreo.dev/?utm_source=me&amp;utm_medium=link&amp;utm_campaign=me_link_python_django_240904"><strong>Choreo</strong></a> is an internal developer platform as a service, which facilitates building, deploying, and running your cloud-native applications in state-of-the-art Kubernetes based environments and provides you with a rich set of tools to monitor and observe your application. Choreo provides a seamless platform to deploy and manage your Django applications, eliminating the complexities of software delivery and infrastructure management.</p><p>Django and Choreo together create a powerful combination, enabling developers to effortlessly build, test, deploy, scale, monitor, and troubleshoot applications reducing the go to market time.</p><p>In this article, we will explore how to develop a simple e-commerce web application using Django and how to deploy, scale and monitor it using Choreo.</p><h3>Setting up the local development environment</h3><p>I will be using python 3.11 to develop the sample e-commerce web application with Django. First let’s create a virtual environment in python using <strong>venv</strong>. This helps to isolate the project dependencies from the global python environment.</p><pre>python3 -m venv ./django</pre><p>Next we will activate the virtual environment created and install the required dependencies.</p><pre>source ./django/bin/activate</pre><p>Use the following command to install django in this virtual environment.</p><pre>pip install django</pre><h3>Bootstrapping a django project using django-admin</h3><p>Execute the following command to bootstrap a django project using django-admin cli.</p><pre>django-admin startproject django_ecommerce</pre><p>Next we need to initialise an app for the ecommerce store. In django, apps are self contained modules that serve a specific purpose within a project. In a typical django project there maybe several apps responsible for different functional aspects of the project. However as this is a sample project, let’s implement all the functionalities in the same app.</p><pre>python manage.py startapp store</pre><h3>Store application implementation</h3><p>Let’s now implement the e-commerce store related functionality in this store app. This will be a simple e-commerce store named Textile Treasures with 4 products namely Silk Brocade, Merino Wool Yarn, Embroidery Hoop Set and Cotton Batik. Customers can view the products, add them to the cart and do a simple checkout without any payment information. The customers also have the option to maintain user accounts and they can view the order history. All these functionality will be implemented in the store app itself.</p><p>While this article is not intended to deeply explain Django itself, it aims to provide a high-level overview of how you can use Django and Choreo together to fast-track your development process. So I will not explain all the implementation in detail. The source code is publicly available and you can explore the implementation by going through the source code. To provide a high level idea about the implementation, I will explain the folder structure of the store app and what goes into each file. The code is available <a href="https://github.com/NomadXD/django-ecommerce">here</a>.</p><pre>store/<br>├── __init__.py<br>├── admin.py<br>├── apps.py<br>├── forms.py<br>├── models.py<br>├── templatetags/<br>│   ├── __init__.py<br>│   └── custom_filters.py<br>├── migrations/<br>│   ├── __init__.py<br>│   └── 0001_initial.py<br>├── fixtures/<br>├── static/<br>│   └── store/<br>│       ├── css/<br>│       │   └── styles.css<br>│       ├── js/<br>│       │   └── scripts.js<br>│       └── images/<br>│           └── logo.png<br>├── templates/<br>│   └── store/<br>│       ├── base.html<br>│       ├── home.html<br>│       ├── product_detail.html<br>│       ├── cart.html<br>│       ├── checkout.html<br>│       ├── order_success.html<br>│       ├── signup.html<br>│       └── order_history.html<br>├── tests.py<br>├── urls.py<br>└── views.py</pre><ul><li><strong>admin.py</strong>: Contains admin site configurations</li><li><strong>apps.py</strong>: Contains app configuration</li><li><strong>forms.py</strong>: Contains form classes</li><li><strong>models.py</strong>: Contains model definitions</li><li><strong>migrations/</strong>: Directory for database migrations</li><li><strong>fixtures/</strong>: Directory for fixture files.</li><li><strong>static/</strong>: Directory for static files.</li><li><strong>templates/</strong>: Directory for HTML templates.</li><li><strong>urls.py</strong>: Contains URL configurations.</li><li><strong>views.py</strong>: Contains view functions.</li></ul><h3>Data models, migrations and seeding</h3><p>Also when we consider the data model, we are going to have 3 tables in the database namely <em>store_product</em>, <em>store_order</em> and <em>store_orderitem</em>. There are 3 models in the <em>models.py</em> to represent each table in the database. Once the models are implemented, you can run the migrations to create the tables.</p><pre>python manage.py makemigrations<br>python manage.py migrate<br>python manage.py createsuperuser</pre><p>The important thing to note here is that you don’t have to worry about things like which ORM to use and which database connector library to use as Django has a built in ORM and has support for a wide range of databases out of the box. For the local development and testing, we will go ahead with the default database which is SQLite.</p><p>Before starting the application locally for testing, we need to seed the database with some sample data. For this purpose you don’t need to write any shell scripts or any python scripts. Django supports database seedings through fixtures. Execute the following command to seed the local SQLite database with the <em>intial_data.json</em> file in the fixtures directory.</p><pre>python manage.py loaddata initial_data.json</pre><p>Now we are all set to test our Textile Treasures e-commerce store locally. Execute the following command to run the application.</p><pre>python manage.py runserver</pre><p>If everything is working as expected, you will see the following output in the terminal and you can click on the development server url to access the e-commerce store.</p><pre>September 02, 2024 - 14:09:31<br>Django version 5.1, using settings &#39;django_ecommerce.settings&#39;<br>Starting development server at http://127.0.0.1:8000/<br>Quit the server with CONTROL-C.</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zIkGNomdn9vE-LK30pwmlQ.png" /><figcaption>e-commerce application up and running locally</figcaption></figure><h3>Deploying the application in Choreo</h3><p>Now we have tested and verified the functionality of the e-commerce store locally and now it’s time to deploy our application in Choreo for production.</p><ol><li>Sign up to <a href="http://console.choreo.dev/?utm_source=me&amp;utm_medium=link&amp;utm_campaign=me_link_python_monitoring_240826"><strong>Choreo</strong></a> and create an account.</li><li>Provide a name and create an organization.</li><li>Go to <em>Dependencies &gt; Databases</em> and create a database server. For this application we will use a PostgreSQL database.</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*UC2VBGoulLjY3J-1gCPyGg.png" /><figcaption>Database successfully created</figcaption></figure><p>4. Execute the database migrations and seeds against the created PostgreSQL database.</p><p>5. Create a project by providing a name and description.</p><p>6. Navigate to Components and Click <strong>+ Create Component.</strong></p><p>7. From the <strong>Create a New Component </strong>menu, select <strong>Web Application</strong> and provide the following details<strong>.</strong></p><pre>Name - Django Ecommerce App<br>Description - Simple e-commerce application implemented using Django framework<br>Repository URL - https://github.com/NomadXD/django-ecommerce<br>Branch - main<br>Buildpack - Python<br>Language version - 3.11.x<br>Python Project Directory - /<br>Port - 8000</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*V9tJM_bjbJ5bmS7CEPrBWA.png" /><figcaption>Create component wizard in Choreo</figcaption></figure><p>8. After creating the component, navigate to the <strong>Build </strong>section from the left sidepane and click <strong>Build Latest Commit</strong>, this would start building a container image using the code provided with a Python Buildpack.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*71RrhUhVuSb00Dy4oHV0_w.png" /><figcaption>Build the e-commerce application to make it deployable in Choreo</figcaption></figure><p>9. After the build is successful, navigate to the <strong>Deploy </strong>section from the left pane, and click <strong>Configure &amp; Build. </strong>Copy the database credentials of the previously created database and provide the DATABASE_URL as a field in the <em>config.json</em>. DATABASE_URL should be in the following format.</p><pre>postgres://&lt;DB_USER&gt;:&lt;DB_PASSWORD&gt;@&lt;DB_HOST&gt;:&lt;DB_PORT&gt;/&lt;DB_NAME&gt;</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CE3xg06YVVMG_39PsHydvA.png" /><figcaption>Configure DATABASE_URL using a config.json</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lAADweFuSFe0eys9EapjvA.png" /><figcaption>e-commerce application up and running in Choreo</figcaption></figure><p>10. You can access the application using the <strong>Web App URL</strong> in the environment card and start using the application.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zIkGNomdn9vE-LK30pwmlQ.png" /><figcaption>e-commerce application up and running in Choreo</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*yD58kAPyXPOw1CISjTrLDw.png" /><figcaption>Click on a product and place the order by adding to the cart</figcaption></figure><p>If you followed the steps correctly, you will have a fully functional application up and running in the Choreo Cloud Dataplane managed Kubernetes cluster with a Choreo managed PostgreSQL database. And just like that, in a few minutes you have a production grade Python application running on state of the art Kubernetes infrastructure! It’s that simple. And the best part is no YAMLs and no Dockerfiles. So how does Choreo containerize your application without a Dockerfile ? Choreo uses cloud native buildpacks to identify and containerize your applications intelligently into kubernetes workloads. If you have gone through the project repository, you would have noticed a Procfile with a single command. This defines the command to execute when the containerized application is started.</p><pre>web: python3 manage.py runserver 0.0.0.0:8000</pre><h3>Monitoring, Scaling and beyond</h3><p>By now you have fully functioning e-commerce application up and running in Choreo. Now you would want to monitor your application for potential issues and troubleshoot them. Choreo offers a unified log analyse view for monitoring and troubleshooting issues. Go to <strong>Observability &gt; Runtime</strong> Logs for accessing the logs.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kCktUl7tC2s7c9tstj50HA.png" /></figure><p>When the actual production traffic comes and more and more users start using your application, you would want to scale your application with the increased demand. Choreo offers autoscaling capabilities and allows you to scale your applications based on CPU, memory and HTTP traffic. Go to <strong>DevOps &gt; Scaling</strong> to configure autoscaling for your applications running in Choreo.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*GETHhOgvpdSxYBDl10Fr-w.png" /></figure><p>Deploying applications in the cloud can be a daunting task given today’s complex technology landscape. However, <a href="https://choreo.dev/?utm_source=me&amp;utm_medium=link&amp;utm_campaign=me_link_python_django_240904">Choreo</a> abstracts away these complexities, providing a developer-friendly platform that makes it effortless to build, deploy, and manage your workloads. We’ve just experienced how easy and efficient this process can be by deploying a Django eCommerce app with Choreo.</p><p><strong>Source code for the sample project available at:</strong> [1] <a href="https://github.com/NomadXD/django-ecommerce">https://github.com/NomadXD/django-ecommerce</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1ca4b349c58c" width="1" height="1" alt=""><hr><p><a href="https://medium.com/choreo-tech-blog/effortless-development-of-cloud-native-applications-in-django-with-choreo-1ca4b349c58c">Effortless Development of Cloud-Native Applications in Django with Choreo</a> was originally published in <a href="https://medium.com/choreo-tech-blog">Choreo Tech Blog</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>