File: README.md
ACI: Open-Source Infra to Power Unified MCP Servers and VibeOps
[!NOTE]
This repo is for the ACI.dev platform. If you're looking for the Unified MCP server built with ACI.dev, see aci-mcp.
ACI.dev is the open-source tool-calling platform that hooks up 600+ tools into any agentic IDE or custom AI agent. It gives agents intent-aware access to tools with multi-tenant auth, granular permissions, and dynamic tool discoveryโexposed as either direct function calls or through a Unified Model-Context-Protocol (MCP) server.
Examples: Instead of writing separate OAuth flows and API clients for Google Calendar, Slack, and more, use ACI.dev to manage authentication and provide AI agents with unified, secure function calls. Access these capabilities through our Unified MCP server or via our lightweight Python SDK, compatible with any LLM framework.
Supercharge vibe coding and automate devOps by adding a single unified MCP server to your favourite agentic IDE. Configure the MCP with Vercel, Supabase, Cloudflare, and other platforms. Let AI handle provisioning, deployment, database configs, and debugging to turn a vibe coded prototype into a live product.
๐บ Demo Video
ACI.dev Unified MCP Server Demo
โจ Key Features
- 600+ Pre-built Integrations: Connect to popular services and apps in minutes.
- Flexible Access Methods: Use our unified MCP server or our lightweight SDK for direct function calling.
- Multi-tenant Authentication: Built-in OAuth flows and secrets management for both developers and end-users.
- Enhanced Agent Reliability: Natural language permission boundaries and dynamic tool discovery.
- Framework & Model Agnostic: Works with any LLM framework and agent architecture.
- 100% Open Source: Everything released under Apache 2.0 (backend, dev portal, integrations).
๐ก Why Use ACI.dev?
ACI.dev improves tool-calling reliability and accountability:
- Authentication at Scale: Connect multiple users to multiple services securely.
- Discovery Without Overload: Find and use the right tools without overwhelming LLM context windows.
- Natural Language Permissions: Control agent capabilities with human-readable boundaries.
- Tool-use Logging: See how your agent called tools and the issues it ran into.
- Build Once, Run Anywhere: No vendor lock-in with our open source, framework-agnostic approach.
๐งฐ Common Use Cases
- VibeOps: Automate devOps by letting your agentic IDE access Vercel, Supabase, Cloudflare, Sentry and more to ship live products.
- Personal Assistant Chatbots: Build chatbots that can search the web, manage calendars, send emails, interact with SaaS tools, etc.
- Research Agent: Conducts research on specific topics and syncs results to other apps (e.g., Notion, Google Sheets).
- Outbound Sales Agent: Automates lead generation, email outreach, and CRM updates.
- Customer Support Agent: Provides answers, manages tickets, and performs actions based on customer queries.
๐ Quick Links
- Managed Service: aci.dev
- Documentation: aci.dev/docs
- Available Tools List: aci.dev/tools
- Python SDK: github.com/aipotheosis-labs/aci-python-sdk
- Typescript SDK: github.com/aipotheosis-labs/aci-typescript-sdk
- Unified MCP Server: github.com/aipotheosis-labs/aci-mcp
- Agent Examples Built with ACI.dev: github.com/aipotheosis-labs/aci-agents
- Blog: aci.dev/blog
- Community: Discord | Twitter/X | LinkedIn
๐ป Getting Started: Local Development
To run the full ACI.dev platform (backend server and frontend portal) locally, follow the individual README files for each component:
- Backend: backend/README.md
- Frontend: frontend/README.md
๐ Contributing
We welcome contributions! Please see our CONTRIBUTING.md for more information.
Integration Requests
Missing any integrations (apps or functions) you need? Please see our Integration Request Template and submit an integration request! Or, if you're feeling adventurous, you can submit a PR to add the integration yourself!
Star History
File: backend/deployment/README.md
Welcome to your CDK Python project!
This is a blank project for CDK development with Python.
The cdk.json file tells the CDK Toolkit how to execute your app.
This project is set up like a standard Python project. The initialization
process also creates a virtualenv within this project, stored under the .venv
directory. To create the virtualenv it assumes that there is a python3
(or python for Windows) executable in your path with access to the venv
package. If for any reason the automatic creation of the virtualenv fails,
you can create the virtualenv manually.
To manually create a virtualenv on MacOS and Linux:
$ python3 -m venv .venvAfter the init process completes and the virtualenv is created, you can use the following
step to activate your virtualenv.
$ source .venv/bin/activateIf you are a Windows platform, you would activate the virtualenv like this:
% .venv\Scripts\activate.batOnce the virtualenv is activated, you can install the required dependencies.
$ pip install -r requirements.txtAt this point you can now synthesize the CloudFormation template for this code.
$ cdk synthTo add additional dependencies, for example other CDK libraries, just add
them to your setup.py file and rerun the pip install -r requirements.txt
command.
Useful commands
cdk lslist all stacks in the appcdk synthemits the synthesized CloudFormation templatecdk deploydeploy this stack to your default AWS account/regioncdk diffcompare deployed stack with current statecdk docsopen CDK documentation
Enjoy!
File: backend/README.md
ACI.dev Backend
Overview
The backend component of ACI.dev provides the server infrastructure, API endpoints, database models, and integration libraries that enable over 600+ tool integrations with multi-tenant authentication and granular permissions.
Code Structure
The backend consists of several main components:
- Server: FastAPI application handling API requests, authentication, and tool executions
- Database: PostgreSQL with pgvector for vector similarity search
- CLI: Command-line interface for local testing and development
- Common: Shared code and utilities used across components
Development Setup
Prerequisites
- Python 3.12+
- Docker and Docker Compose
uvpackage manager
Code Style
We follow strict code quality standards:
- Formatting & Linting: We use
rufffor code formatting and linting - Type Checking: We use
mypyfor static type checking - Pre-commit Hooks: Install with
pre-commit install
IDE Configuration
For VS Code users, configure Ruff formatter:
{
"[python]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.codeActionsOnSave": {
"source.organizeImports.ruff": "always"
}
}
}Getting Started
Clone the repository:
bashgit clone https://github.com/aipotheosis-labs/aci.git cd aci/backendInstall dependencies and activate virtual environment:
bashuv sync source .venv/bin/activateInstall
pre-commithooks:bashpre-commit installSet up environment variables for local development:
bashcp .env.example .env.localMost sensitive variables and dummy values are already defined in
.env.example, so you only need to set the following env vars in.env.local:SERVER_OPENAI_API_KEY: Use your own OpenAI API keyCLI_OPENAI_API_KEY: Use your own OpenAI API key (can be the same asSERVER_OPENAI_API_KEY)
Start services with Docker Compose:
bashdocker compose up --buildThis will start:
server: Backend API servicedb: PostgreSQL databaseaws: LocalStack for mocking AWS servicesrunner: Container for running commands like pytest, cli commands or scripts
Seed the database with sample data:
bashdocker compose exec runner ./scripts/seed_db.shThe script will seed the database with below dummy data for local end-to-end development.
- A default project and agent (with an API key)
- Sample Apps and their functions
Brave SearchHacker NewsGmail(with dummy OAuth2 credentials)
The script will output an API key like below that you can use on the swagger UI, SDK, or
sending HTTP requests to the local backend server directly.text{ 'Project Id': '65cf26b9-a919-4008-85de-ecb850c3fc36', 'Agent Id': '74273ac1-f68e-4314-b8be-fee4a5855d8a', 'API Key': '88c55e31e817bd2d48aa455e94b61e766fb6e6610c97abe6f724733bf222e3e0' }[!NOTE]
If you want to seed the database with all available apps, run the script with the--allflag.
But you'll have to manually create a secrets file.app.secrets.json
for each app that has OAuth2 scheme and put the OAuth2 credentials in that file, and the
insertion process might take a while.
See the example secrets file below for theGMAILapp.Alternatively, you can use the
--all --mockflags together to seed all apps with mock OAuth2 credentials.
This is useful for development and testing when you don't need real OAuth2 authentication.
The mock values will be used instead of requiring.app.secrets.jsonfiles.bash# put this in a file called .app.secrets.json under ./apps/gmail/ { "AIPOLABS_GMAIL_CLIENT_ID": "<your_google_oauth2_client_id>", "AIPOLABS_GMAIL_CLIENT_SECRET": "<your_google_oauth2_client_secret>" }(Optional) If you want to seed the database with specific
AppsandFunctions, use the cli command directly.[!NOTE]
Add the--skip-dry-runflag to the commands below to actually insert the data into the database.bash# create app (--secrets-file is only needed for apps that have OAuth2 scheme) docker compose exec runner python -m aci.cli upsert-app --app-file ./apps/gmail/app.json --secrets-file ./apps/gmail/.app.secrets.json # create functions docker compose exec runner python -m aci.cli upsert-functions --functions-file ./apps/gmail/functions.json(Optional) Connect to the database using a GUI client (e.g.,
DBeaver)- Parameters for the db connection can be found in the
.env.localfile you created in step 4.
- Parameters for the db connection can be found in the
Access the API documentation at:
bashhttp://localhost:8000/v1/notforhuman-docs(Optional) If you are developing the dev portal, follow the instructions on frontend README to start the dev portal.
(Optional) If you are developing Stripe related billing features, follow the
Stripe Webhooks section.
Running Tests
docker compose exec test-runner pytestDatabase Management
Working with Migrations
When making changes to database models:
Check for detected changes:
bashdocker compose exec runner alembic checkGenerate a migration:
bashdocker compose exec runner alembic revision --autogenerate -m "description of changes"Manually review and edit the generated file in
database/alembic/versions/if needed to add custom changes, e.g.,:- pgvector library imports
- Index creation/deletion
- Vector extension setup
- Other database-specific operations
Apply the migration (to the local db):
bashdocker compose exec runner alembic upgrade headTo revert the latest migration:
bashdocker compose exec runner alembic downgrade -1
PropelAuth Configuration
[!NOTE]
This section is only required if you need to develop features that integrate with PropelAuth.
When developing the dev portal, you'll need an actual user and organization in PropelAuth's test environment, along with a default project and agent in your local database. This section guides you through setting up these connections.
Values to be filled
You would need to replace a few dummy values with real values in .env.local:
SERVER_PROPELAUTH_AUTH_URL- The authentication URL from PropelAuthSERVER_PROPELAUTH_API_KEY- Your PropelAuth API keySERVER_SVIX_SIGNING_SECRET- The signing secret for webhooks
Setup Steps
Follow these steps to configure PropelAuth for local development:
1. Set Up Ngrok
Ngrok creates a public URL for your local server, allowing PropelAuth webhooks to reach your machine:
- Install ngrok from the getting started guide
- Start a tunnel to your local server:bash
ngrok http http://localhost:8000 - Copy the generated public endpoint (e.g.,
https://7c4c-2a06-5904-1e06-6a00-ddc6-68ce-ffae-8783.ngrok-free.app) - Optional: View traffic logs in the ngrok dashboard
2. Configure PropelAuth Settings
Navigate to the PropelAuth dashboard
If needed, switch to the
aipolabs localorganization by clicking your account name and selecting Switch to aipolabs localIn the Users and Organizations tabs:
- Remove any previously created test users and organizations
In the Frontend Integrations tab:
- Locate and copy the Auth URL
- Use this URL for both:
SERVER_PROPELAUTH_AUTH_URLin backend's.env.localNEXT_PUBLIC_AUTH_URLin frontend's.env
In the Backend Integration tab (if you need a new API key):
- Click Create New API Key
- Name it
<Your name> Local Testing - Copy the key and set it as
SERVER_PROPELAUTH_API_KEYin.env.local
3. Set Up Webhooks
- Navigate to Integrations โ Webhooks in the dashboard
- Click Set Up Webhooks for the TEST ENV
- On the Svix endpoints page:
- Click Add Endpoint
- For the endpoint URL, enter your ngrok URL followed by the path:text
<your-ngrok-url>/v1/webhooks/auth/user-created - Subscribe to the
user.createdevent - Click Create
- After creation:
- Find and copy the Signing Secret
- Set it as
SERVER_SVIX_SIGNING_SECRETin.env.local
4. Update Docker Configuration
- Edit
backend/compose.ymlto comment out the PropelAuth mock service:- In the
serverservice section, comment out:yaml# - ./mock/propelauth_fastapi_mock.py:/workdir/.venv/lib/python3.12/site-packages/propelauth_fastapi/__init__.py - In the
runnerservice section, comment out:yaml# - ./mock/propelauth_fastapi_mock.py:/workdir/.venv/lib/python3.12/site-packages/propelauth_fastapi/__init__.py
- In the
5. Restart the Docker container
6. Verify Your Setup
Test your configuration by:
- Visiting your frontend application (typically at
http://localhost:3000) - Creating a new account or logging in
- When successful, the webhook should trigger and automatically create the organization and project
Stripe Webhooks
[!NOTE]
This is only needed if you need to develop the stripe billing features.
Download the Stripe CLI
Log into our Stripe Sandbox with the CLI
shellstripe loginSet up webhooks with the Stripe CLI and get the webhook signing secret. By default,
all events in the Sandbox will be forwarded to the local webhook endpoint. You can also
use--eventflag to filter the set of events you want to listen to.shellstripe listen --forward-to localhost:8000/v1/billing/webhook > Ready! You are using Stripe API Version [2025-02-24.acacia]. Your webhook signing secret is whsec_3b397734bb0362eac34a9611cc842f4a8cfb8f0e38eccf7ee666b09ac3aeec52Set the following two env vars in
.env.local:SERVER_STRIPE_SECRET_KEY: get it from the Stripe dashboardSERVER_STRIPE_WEBHOOK_SIGNING_SECRET: get it from the output of thestripe listencommand you just executed
Admin CLI
The CLI module is an internal admin tool for ACI to manage apps, functions, users, etc.
For local development, the commands can be executed via the runner container.
To see all available commands and their usage, run:
docker compose exec runner python -m aci.cli --helpExample output:
Usage: python -m aci.cli [OPTIONS] COMMAND [ARGS]...
AIPO CLI Tool
Options:
-h, --help Show this message and exit.
Commands:
create-agent Create an agent in db.
create-project Create a project in db.
create-random-api-key Create a random test api key for local...
delete-app Delete an app and all its references...
fuzzy-test-function-execution Test function execution with...
get-app Get an app by name from the database.
rename-app Rename an app and update all related...
update-agent Update an existing agent in db.
upsert-app Insert or update an App in the DB from a...
upsert-functions Upsert functions in the DB from a JSON...To create a new app, run:
docker compose exec runner python -m aci.cli create-app --app-file ./apps/brave_search/app.json --secrets-file ./apps/brave_search/.app.secrets.jsonRunning Evaluations
You will need to set up the following environment variables:
EVALS_SERVER_URL=<your_server_url_typically_http://localhost:8000>
EVALS_ACI_API_KEY=<your_api_key_for_the_server_returned_from_seed_db_script>
EVALS_OPENAI_KEY=<your_openai_api_key>
EVALS_WANDB_KEY=<your_wandb_api_key>The evaluation results will be logged to Weights & Biases where you can track metrics, view experiment configurations, and analyze the results.
Then, seed the database with all apps and mock credentials:
docker compose exec runner ./scripts/seed_db.sh --all --mockRunning the Evaluation Pipeline
To run the complete evaluation pipeline with different modes:
# Generate synthetic intents and evaluate them
docker compose exec runner python -m evals.evaluation_pipeline --mode generate-and-evaluate
# Only generate synthetic intent data
docker compose exec runner python -m evals.evaluation_pipeline --mode generate-only
# Only evaluate using existing dataset
docker compose exec runner python -m evals.evaluation_pipeline --mode evaluate-onlyAdditional flags:
# Specify a custom dataset artifact name (default: "synthetic_intent_dataset")
docker compose exec runner python -m evals.evaluation_pipeline --mode evaluate-only --dataset-artifact my_custom_artifact
# Specify the filename saved on the dataset artifact
docker compose exec runner python -m evals.evaluation_pipeline --mode evaluate-only --dataset-filename my_custom_dataset.csv
# Limit the number of samples to generate
docker compose exec runner python -m evals.evaluation_pipeline --mode generate-only --generation-limit 50
# Limit the number of samples to evaluate
docker compose exec runner python -m evals.evaluation_pipeline --mode evaluate-only --evaluation-samples 25[!NOTE]
If you use thegenerate-and-evaluatemode, the pipeline will use the freshly generated dataset directly
without having to reload it from Weights & Biases, which is more efficient.
Contributing
Please refer to the Contributing Guide for details on making contributions to this project.
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
File: frontend/src/components/ui-extensions/enhanced-data-table/README.md
EnhancedDataTable Component Documentation
The EnhancedDataTable is a data table component built on TanStack Table (React Table), providing advanced features such as sorting, filtering, searching, and row selection. This documentation will help you quickly understand and effectively use this component.
Table of Contents
- Basic Usage
- Column Definitions
- Search and Filtering
- Sorting Functionality
- Row Selection
- Custom Column Styling and Actions
- Practical Application Examples
Basic Usage
To use the EnhancedDataTable, you need to provide two basic parameters: columns (column definitions) and data (data source).
import { EnhancedDataTable } from "@/components/ui-extensions/enhanced-data-table/data-table";
import { useMyTableColumns } from "./useMyTableColumns";
export function MyTable({ data }) {
// Use custom hook to get column definitions
const columns = useMyTableColumns();
return (
<EnhancedDataTable
columns={columns}
data={data}
searchBarProps={{ placeholder: "Search..." }}
/>
);
}Column Definitions
It's recommended to create column definition hooks in separate files using createColumnHelper to get better type support.
Creating Basic Column Definition Files
// useMyTableColumns.tsx
import { useMemo } from "react";
import { createColumnHelper, type ColumnDef } from "@tanstack/react-table";
import { MyDataType } from "@/lib/types/myDataType";
const columnHelper = createColumnHelper<MyDataType>();
export const useMyTableColumns = (): ColumnDef<MyDataType>[] => {
return useMemo(
() => [
columnHelper.accessor("name", {
header: "Name",
cell: (info) => info.getValue(),
enableGlobalFilter: true,
}),
columnHelper.accessor("description", {
header: "Description",
cell: (info) => info.getValue(),
enableGlobalFilter: true,
}),
],
[],
);
};Column Properties Explained
header: Column title, can be a string or React componentcell: Cell rendering functionenableGlobalFilter: Whether to include this column in global searchenableColumnFilter: Whether to enable column filteringfilterFn: Filter function type, e.g., "arrIncludes" for array fieldsid: Custom column ID, required when using accessor functionmeta: Used to set default sorting and other metadata
Creating Sortable Columns
columnHelper.accessor("name", {
header: ({ column }) => (
column.toggleSorting(column.getIsSorted() === "asc")}
className="w-full justify-start px-0"
>
Name
<ArrowUpDown className="h-4 w-4" />
),
cell: (info) => info.getValue(),
enableGlobalFilter: true,
// Set as default sort column
meta: {
defaultSort: true,
defaultSortDesc: false,
},
});Search and Filtering
Enabling Global Search
Provide the searchBarProps parameter and ensure relevant columns have enableGlobalFilter: true:
<EnhancedDataTable
columns={columns}
data={data}
searchBarProps={{ placeholder: "Search..." }}
/>Column Filtering Functionality
EnhancedDataTable provides singleโvalue dropdown filtering for arrayโtype columns. :
- Set
enableColumnFilter: true - Set
filterFn: "arrIncludes"
Enabling Dropdown Filtering for Array Type Columns
// Using dropdown filtering for tag arrays
columnHelper.accessor("tags", {
header: "Tags",
cell: (info) => (
{info.getValue().map((tag) => (
{tag}
))}
),
enableGlobalFilter: true,
enableColumnFilter: true, // Enable column filtering
filterFn: "arrIncludes", // Specify array filtering function
});Handling Arrays from Non-Standard Data Sources
For array data not in default fields, you can use custom accessors:
// Handling nested objects or transforming data
columnHelper.accessor(
(row) => row.metadata?.categories || [], // Extract array from nested object
{
id: "categoriesDisplay", // Must provide unique ID
header: "Categories",
cell: (info) => (
{info.getValue().map((category) => (
{category}
))}
),
enableColumnFilter: true,
filterFn: "arrIncludes",
},
);Automatic Filter UI Generation
When the following conditions are met, the table will automatically generate dropdown filter menus for columns:
- Column has
enableColumnFilter: true - Column uses
filterFn: "arrIncludes"
Filters will be displayed in the top toolbar of the table, allowing users to select multiple values for filtering.
Sorting Functionality
Setting Default Sorting
You can set default sorting in two ways:
- Using the
metaproperty in column definition:
columnHelper.accessor("createdAt", {
header: "Created At",
cell: (info) => new Date(info.getValue()).toLocaleString(),
id: "createdAt",
meta: {
defaultSort: true,
defaultSortDesc: true, // Default descending order
},
});- Through the component's
defaultSortingproperty:
<EnhancedDataTable
columns={columns}
data={data}
defaultSorting={[
{
id: "createdAt",
desc: true,
},
]}
/>Row Selection
To enable row selection functionality, you need to provide rowSelectionProps:
const [rowSelection, setRowSelection] = useState({});
<EnhancedDataTable
columns={columns}
data={data}
rowSelectionProps={{
rowSelection,
onRowSelectionChange: setRowSelection,
getRowId: (row) => row.id,
}}
/>;This will add a selection checkbox column to the left of the table, allowing users to select multiple rows of data.
Custom Column Styling and Actions
Image and Text Combination Column
columnHelper.accessor("app_name", {
header: "App Name",
cell: (info) => {
const appName = info.getValue();
return (
{appsMap[appName]?.logo && (
)}
);
},
enableGlobalFilter: true,
});Tag Rendering
columnHelper.accessor("tags", {
header: "Tags",
cell: (info) => (
{(info.getValue() || []).map((tag) => (
{tag}
))}
),
enableGlobalFilter: true,
enableColumnFilter: true,
filterFn: "arrIncludes",
});Custom Action Buttons Column
columnHelper.accessor(
(row) => row, // Get entire row data
{
id: "actions",
header: "",
cell: (info) => {
const item = info.getValue();
return (
<Link href={`/items/${item.id}`}>
Open
</Link>
<GoTrash />
);
},
enableGlobalFilter: false,
},
);Editable Cells
columnHelper.accessor("name", {
header: "Name",
cell: (ctx) => {
const item = ctx.row.original;
return (
<EditableCell
initialValue={item.name}
fieldName="name"
itemId={item.id}
onUpdate={handleUpdate}
/>
);
},
enableGlobalFilter: true,
});Pagination
EnhancedDataTable supports client-side pagination using TanStack Tableโs built-in getPaginationRowModel().
To enable pagination, pass the paginationOptions prop:
<EnhancedDataTable
columns={columns}
data={data}
paginationOptions={{
initialPageIndex: 0, // Default to first page (0-based)
initialPageSize: 10, // Number of entries per page
}}
/>Practical Application Examples
App Configuration Table (with Icons, Category Filtering, and Toggle Switch)
// In page component
import { EnhancedDataTable } from "@/components/ui-extensions/enhanced-data-table/data-table";
import { useAppConfigsTableColumns } from "./useAppConfigsTableColumns";
export function AppConfigsPage() {
const [appConfigs, setAppConfigs] = useState<AppConfig[]>([]);
// ...other states and logic
const appConfigsColumns = useAppConfigsTableColumns({
linkedAccountsCountMap,
appsMap,
updateAppConfigs: loadAllData,
});
return (
<EnhancedDataTable
data={appConfigs}
columns={appConfigsColumns}
searchBarProps={{ placeholder: "Search apps..." }}
/>
);
}Agents Table (with Editable Cells and Custom Actions)
// In page component
import { EnhancedDataTable } from "@/components/ui-extensions/enhanced-data-table/data-table";
import { useAgentsTableColumns } from "./useAgentsTableColumns";
export function AgentsPage() {
const [agents, setAgents] = useState<Agent[]>([]);
// ...other states and logic
const columns = useAgentsTableColumns(
projectId,
handleDeleteAgent,
reloadAgents,
handleInstructionsSave,
);
return (
<EnhancedDataTable
data={agents}
columns={columns}
searchBarProps={{ placeholder: "Search agents..." }}
/>
);
}File: frontend/README.md
Aipolabs Developer Portal
The developer portal for Aipolabs, a platform for developers to manage and configure the apps and functions used by their agents.
Table of Contents
Description
The Dev Portal enables developers to create and manage their projects efficiently. It provides the following key pages for comprehensive project management:
- Projects Settings
- Home Page
- App Store Page
- App Configurations Page
- Linked Accounts Page
- Agent Playground Page
- Account Settings
Development Setup
Bring up backend in docker compose:
Refer to the backend README to set it up. Make sure you
complete the Webhooks section of the setup.Make sure you are in the frontend directory
Install dependencies:
If you're using npm:bashnpm install --legacy-peer-deps(Note: This repo uses Next.js 15, which requires React 19 that is
stabilized in Dec 05, 2024.
Some libraries are still upgrading to React 19, so we need to use the--legacy-peer-depsflag in the mean time.)Configure Environment Variables: Copy
.env.exampleto.envbashcp .env.example .envStart the application:
bashnpm run devSign up on the local dev portal:
After signup, a new user will be created in the PropelAuth local dev org's test
environment. PropelAuth will also call the user-created webhook, which will create a
test project and agent in your local DB for you to use.
Linting & Testing
This repo uses prettier for formatting, next lint for linting, and vitest for unit tests.
Format code:
bashnpm run formatRun linters:
bashnpm run lintRun vitest in watch mode:
bashnpm run testGet test coverage:
bashnpm run test:coverage
You can also setup pre-commit hook to run format, lint, and tests when you
commit your code by running (make sure you have pre-commit installed):
pre-commit installDirectory Structure
src
โโโ app (Next.js App Router folder)
โ โโโ ... (different pages of the dev portal)
โโโ components
โ โโโ ... (components we created for use in the pages of dev portal)
โ โโโ ui (shadcn/ui components we installed)
โโโ hooks
โ โโโ use-mobile.tsx
โโโ lib
โ โโโ api (functions for interacting with the Aipolabs backend API)
โ โโโ types (types of the Aipolabs backend API response)
โ โโโ utils.ts
โโโ __test__ (test files, the structure of this folder should be the same as the structure of the src/app folder)
โโโ apps
โโโ linked-accounts
โโโ project-setting
โโโ ...Conventions
- All functions calling the backend API directly should be put in the src/lib/api folder.
Deployment
The Dev Portal is deployed on Vercel: obnoxiousproxys-projects/aci-dev-portal
The environment variables need to be set correctly on Vercel: https://vercel.com/obnoxiousproxys-projects/aci-dev-portal/settings/environment-variables.
For example, for the Vercel production environment, we set the following environment variables:
NEXT_PUBLIC_API_URL=https://api.aci.dev
NEXT_PUBLIC_DEV_PORTAL_URL=https://platform.aci.dev
NEXT_PUBLIC_ENVIRONMENT=production
NEXT_PUBLIC_AUTH_URL=<actual_production_propelauth_endpoint>