Data fetching in '/apps/[appName]' route in open source ACI.dev platform.
In this article, we are going to review API layer in /apps/GITHUB route in ACI.dev platform. We will look at:
-
Locating the /apps/GITHUB route
-
apps/GITHUB folder
-
API Layer in apps/GITHUB/page.tsx
This /apps/GITHUB route loads a page that looks like below:

ACI.dev is the open source platform that connects your AI agents to 600+ tool integrations with multi-tenant auth, granular permissions, and access through direct function calling or a unified MCP server.
Locating the /apps/GITHUB route
ACI.dev is open source, you can find their code at aipotheosis-labs/aci. This codebase has the below project structure:
-
apps
-
backend
-
frontend
frontend
ACI.dev is built using Next.js, I usually confirm this by looking for next.config.ts at the root of the frontend folder.
And there is a src folder and app folder inside this src folder. This means this project is built using app router.
From here on, it makes it super easy to locate /apps/GITHUB route since this is going to be a folder, according to how app router works in Next.js

You will find the apps/[appName] folder in the above image. [appName] here indicates that this is dynamic route. There won’t be any GITHUB folder, instead this is a param accessible in apps/[appName]/page.tsx
apps/[appName] folder
apps folder has the below structure:
- page.tsx- file
It contains only 1 file, page.tsx.
API layer in apps/[appName]
This below code is picked from aci.dev/frontend/…/apps/[appName]/page.tsx.
useEffect(() => { async function loadData() { try { const apiKey = getApiKey(activeProject); const app = await getApp(appName, apiKey); setApp(app); const functions = await getFunctionsForApp(appName, apiKey); setFunctions(functions); const appConfig = await getAppConfig(appName, apiKey); setAppConfig(appConfig); } catch (error) { console.error("Error fetching app data:", error); } } loadData(); }, [appName, activeProject]);
getApiKey:
This below code is imported from /lib/util.ts
import { Project } from "@/lib/types/project"; export function getApiKey(project: Project, agentId?: string): string { if ( !project || !project.agents || project.agents.length === 0 || !project.agents[0].api_keys || project.agents[0].api_keys.length === 0 ) { throw new Error( `No API key available in project: ${project.id} ${project.name}`, ); } if (agentId) { const agent = project.agents.find((agent) => agent.id === agentId); if (!agent) { throw new Error(`Agent ${agentId} not found in project ${project.id}`); } return agent.api_keys[0].key; } return project.agents[0].api_keys[0].key; }
getApp
getApp is defined as shown below:
export async function getApp( appName: string, apiKey: string, ): Promise<App | null> { const apps = await getApps([appName], apiKey); return apps.length > 0 ? apps[0] : null; }
getFunctionsForApp
export async function getFunctionsForApp( appName: string, apiKey: string, ): Promise<AppFunction[]> { const params = new URLSearchParams(); params.append("app_names", appName); const response = await fetch( `${process.env.NEXT_PUBLIC_API_URL}/v1/functions?${params.toString()}`, { method: "GET", headers: { "X-API-KEY": apiKey, }, }, ); if (!response.ok) { throw new Error( `Failed to fetch functions: ${response.status} ${response.statusText}`, ); } const functions = await response.json(); return functions; }
This above code is picked from frontend/lib/api/appFunction.ts.
About me:
Hey, my name is Ramu Narasinga. Email: ramu.narasinga@gmail.com
Tired of AI-generated code that works but nobody understands?
I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built an open source tool that reviews your PR against your existing codebase patterns.
Your codebase. Your patterns. Enforced.
