refactor: simplify link-as-an-app template and migrate 24 existing apps (#27215)

* refactor: simplify link-as-an-app template to config.json only

- Remove api/, components/, index.ts, package.json from link-as-an-app template
- Add externalLink field to AppMetaSchema for external URL configuration
- Update API handler to dynamically create handlers for external link apps
- External link apps no longer create credentials (just redirect to URL)
- Update CLI to handle externalLinkUrl field for link-as-an-app template
- CLI now skips package.json update for apps without package.json

Co-Authored-By: peer@cal.com <peer@cal.com>

* fix: simplify external link handler to bypass credential creation

External link apps now directly return the redirect URL without going
through the AppDeclarativeHandler type, avoiding type conflicts with
the createCredential return type requirement.

Co-Authored-By: peer@cal.com <peer@cal.com>

* refactor: migrate 24 external link apps to simplified structure

Migrated the following apps to use config.json with externalLink field
instead of api/add.ts handlers:

- amie, autocheckin, baa-for-hipaa, bolna, chatbase, clic, cron, deel
- elevenlabs, fonio-ai, framer, granola, greetmate-ai, lindy, millis-ai
- monobot, n8n, pipedream, raycast, retell-ai, synthflow, telli, vimcal
- wordpress

Each app now only contains: config.json, DESCRIPTION.md, static/
Removed: api/, components/, index.ts, package.json

Co-Authored-By: peer@cal.com <peer@cal.com>

* nit

* Fix merge conflict issue

* refactor: generate REDIRECT_APPS dynamically during app-store build

- Add logic to build.ts to detect apps with externalLink field
- Generate redirect-apps.generated.ts with list of redirect app slugs
- Update redirectApps.ts to import from generated file
- Revert [...]args].ts to original state (Flow 1 is preferred)

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* fix: cast REDIRECT_APPS to readonly string[] for includes check

Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com>

* Fix error with React

* Take exteral link URL as input

* deleted bun.lockb

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Hariom Balhara <hariombalhara@gmail.com>
This commit is contained in:
authored and GitHub committed 2026-02-06 12:28:11 +00:00
1 parent 54da93ab02
commit 4a6d608b19
159 files changed
+327 -1020

No files matched your search

+13
View File
@@ -487,6 +487,18 @@ function generateFiles() {
videoOutput.push(...videoAdapters);
}
// Generate redirect apps list (apps with externalLink in their config, excluding templates)
const redirectAppsOutput: string[] = [];
const redirectAppSlugs: string[] = [];
forEachAppDir((app) => {
// Exclude templates - they are not actual apps
if (app.externalLink && !app.path.startsWith("templates/")) {
redirectAppSlugs.push(app.name);
}
});
redirectAppsOutput.push(`export const REDIRECT_APPS = ${JSON.stringify(redirectAppSlugs)} as const;`);
redirectAppsOutput.push(`export type RedirectApp = typeof REDIRECT_APPS[number];`);
const banner = `/**
This file is autogenerated using the command \`yarn app-store:build --watch\`.
Don't modify this file manually.
@@ -504,6 +516,7 @@ function generateFiles() {
["calendar.services.generated.ts", calendarOutput],
["payment.services.generated.ts", paymentOutput],
["video.adapters.generated.ts", videoOutput],
["redirect-apps.generated.ts", redirectAppsOutput],
];
filesToGenerate.forEach(([fileName, output]) => {
const filePath = path.join(APP_STORE_PATH, fileName);
@@ -30,6 +30,7 @@ export const AppForm = ({
category: "",
publisher: "",
email: "",
externalLinkUrl: "",
};
const [app] = useState(() => getApp(givenSlug, isTemplate));
@@ -43,8 +44,9 @@ export const AppForm = ({
...config,
category: config.categories[0],
template: config.__template,
externalLinkUrl: config.externalLink?.url || "",
};
} catch (_e) {}
} catch (_e) { }
const fields = [
{
@@ -68,13 +70,13 @@ export const AppForm = ({
cliTemplate || isEditAction
? null
: {
label: "Choose a base Template",
name: "template",
type: "select",
options: Templates,
optional: false,
defaultValue: "",
},
label: "Choose a base Template",
name: "template",
type: "select",
options: Templates,
optional: false,
defaultValue: "",
},
{
optional: false,
label: "Category of App",
@@ -113,16 +115,35 @@ export const AppForm = ({
defaultValue: "email@example.com",
},
].filter((f) => f);
const [appInputData, setAppInputData] = useState(initialConfig);
const [inputIndex, setInputIndex] = useState(0);
const [slugFinalized, setSlugFinalized] = useState(false);
// Add external link URL field for link-as-an-app template
// Must use appInputData.template (not initialConfig.template) to react to user's interactive selection
const templateForFields = appInputData.template || cliTemplate;
if (templateForFields === "link-as-an-app") {
const categoryIndex = fields.findIndex((f) => f?.name === "category");
const hasExternalLinkField = fields.some((f) => f?.name === "externalLinkUrl");
if (categoryIndex !== -1 && !hasExternalLinkField) {
fields.splice(categoryIndex + 1, 0, {
optional: false,
label: "External Link URL",
name: "externalLinkUrl",
type: "text",
explainer: "The URL users will be redirected to when they install this app (e.g., https://example.com/signup)",
defaultValue: "https://example.com",
});
}
}
const field = fields[inputIndex];
const fieldLabel = field?.label || "";
const fieldName = field?.name || "";
let fieldValue = appInputData[fieldName as keyof typeof appInputData] || "";
let validationResult: Parameters<typeof Message>[0]["message"] | null = null;
const { name, category, description, publisher, email, template } = appInputData;
const { name, category, description, publisher, email, template, externalLinkUrl } = appInputData;
const [status, setStatus] = useState<"inProgress" | "done">("inProgress");
const formCompleted = inputIndex === fields.length;
@@ -147,6 +168,7 @@ export const AppForm = ({
editMode: isEditAction,
isTemplate,
oldSlug: givenSlug,
externalLinkUrl,
});
await generateAppFiles();
@@ -168,6 +190,7 @@ export const AppForm = ({
publisher,
slug,
template,
externalLinkUrl,
]);
if (action === "edit" || action === "edit-template") {
@@ -202,9 +225,8 @@ export const AppForm = ({
message={{
text: isEditAction
? `Editing app with slug ${slug}`
: `Creating ${
action === "create-template" ? "template" : "app"
} with name '${name}' categorized in '${category}' using template '${template}'`,
: `Creating ${action === "create-template" ? "template" : "app"
} with name '${name}' categorized in '${category}' using template '${template}'`,
type: "info",
showInProgressIndicator: true,
}}
@@ -269,9 +291,8 @@ export const AppForm = ({
}
if (slug && slug !== givenSlug && fs.existsSync(getAppDirPath(slug, isTemplate))) {
validationResult = {
text: `${
action === "create" ? "App" : "Template"
} with slug ${slug} already exists. If you want to edit it, use edit command`,
text: `${action === "create" ? "App" : "Template"
} with slug ${slug} already exists. If you want to edit it, use edit command`,
type: "error",
};
@@ -293,9 +314,8 @@ export const AppForm = ({
) : (
<Message
message={{
text: `\nLet's create your ${
isTemplate ? "Template" : "App"
}! Start by providing the information that's asked\n`,
text: `\nLet's create your ${isTemplate ? "Template" : "App"
}! Start by providing the information that's asked\n`,
}}
/>
)}
+21 -3
View File
@@ -33,11 +33,16 @@ const updatePackageJson = ({
appDescription: string;
appDirPath: string;
}) => {
const packageJsonConfig = JSON.parse(fs.readFileSync(`${appDirPath}/package.json`).toString());
const packageJsonPath = `${appDirPath}/package.json`;
// Skip if package.json doesn't exist (e.g., for simplified link-as-an-app template)
if (!fs.existsSync(packageJsonPath)) {
return;
}
const packageJsonConfig = JSON.parse(fs.readFileSync(packageJsonPath).toString());
packageJsonConfig.name = `@calcom/${slug}`;
packageJsonConfig.description = appDescription;
// packageJsonConfig.description = `@calcom/${appName}`;
fs.writeFileSync(`${appDirPath}/package.json`, JSON.stringify(packageJsonConfig, null, 2));
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJsonConfig, null, 2));
};
const _workspaceDir = path.resolve(__dirname, "..", "..", "..");
@@ -54,6 +59,7 @@ export const BaseAppFork = {
template,
isTemplate,
oldSlug,
externalLinkUrl,
}: {
category: string;
editMode?: boolean;
@@ -65,6 +71,7 @@ export const BaseAppFork = {
template: string;
isTemplate: boolean;
oldSlug?: string;
externalLinkUrl?: string;
}) => {
const appDirPath = getAppDirPath(slug, isTemplate);
if (!editMode) {
@@ -93,7 +100,7 @@ export const BaseAppFork = {
video: "conferencing",
};
let config = {
let config: Record<string, unknown> = {
name: name,
// Plan to remove it. DB already has it and name of dir is also the same.
slug: slug,
@@ -115,6 +122,17 @@ export const BaseAppFork = {
...currentConfig,
...config,
};
// For link-as-an-app template, update the externalLink URL
if (template === "link-as-an-app" && externalLinkUrl) {
config.externalLink = {
url: externalLinkUrl,
newTab: true,
};
// Also update the legacy url field for backwards compatibility
config.url = externalLinkUrl;
}
fs.writeFileSync(`${appDirPath}/config.json`, JSON.stringify(config, null, 2));
fs.writeFileSync(
`${appDirPath}/DESCRIPTION.md`,
+1 -1
View File
@@ -2,7 +2,7 @@
"compilerOptions": {
"strict": true,
"module": "commonjs",
"jsx": "react",
"jsx": "react-jsx",
"esModuleInterop": true,
"outDir": "dist",
"noEmitOnError": false,
+4 -22
View File
@@ -1,25 +1,7 @@
export const REDIRECT_APPS = [
"amie",
"autocheckin",
"bolna",
"chatbase",
"clic",
"deel",
"elevenlabs",
"granola",
"greetmate-ai",
"lindy",
"linear",
"millis-ai",
"monobot",
"retell-ai",
"synthflow",
"telli",
"vimcal",
"wordpress",
"zapier",
];
import { REDIRECT_APPS } from "../redirect-apps.generated";
export { REDIRECT_APPS };
export const isRedirectApp = (slug: string): boolean => {
return REDIRECT_APPS.includes(slug);
return (REDIRECT_APPS as readonly string[]).includes(slug);
};
-20
View File
@@ -1,20 +0,0 @@
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import { createDefaultInstallation } from "../../_utils/installation";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://amie.so/signup",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+11 -3
View File
@@ -6,12 +6,20 @@
"logo": "icon.svg",
"url": "https://cal.com",
"variant": "other",
"categories": ["calendar"],
"categories": [
"calendar"
],
"publisher": "Cal.com, Inc.",
"email": "support@cal.com",
"description": "The joyful productivity app\r\r",
"__createdUsingCli": true,
"dependencies": ["google-calendar"],
"dependencies": [
"google-calendar"
],
"dirName": "amie",
"isOAuth": false
"isOAuth": false,
"externalLink": {
"url": "https://amie.so/signup",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/amie",
"version": "0.0.0",
"main": "./index.ts",
"description": "The joyful productivity app\r\r",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
}
}
@@ -4,43 +4,30 @@
**/
export const apiHandlers = {
alby: import("./alby/api"),
amie: import("./amie/api"),
applecalendar: import("./applecalendar/api"),
attio: import("./attio/api"),
autocheckin: import("./autocheckin/api"),
"baa-for-hipaa": import("./baa-for-hipaa/api"),
basecamp3: import("./basecamp3/api"),
bolna: import("./bolna/api"),
btcpayserver: import("./btcpayserver/api"),
caldavcalendar: import("./caldavcalendar/api"),
campfire: import("./campfire/api"),
chatbase: import("./chatbase/api"),
clic: import("./clic/api"),
closecom: import("./closecom/api"),
cron: import("./cron/api"),
databuddy: import("./databuddy/api"),
deel: import("./deel/api"),
demodesk: import("./demodesk/api"),
dialpad: import("./dialpad/api"),
discord: import("./discord/api"),
dub: import("./dub/api"),
eightxeight: import("./eightxeight/api"),
"element-call": import("./element-call/api"),
elevenlabs: import("./elevenlabs/api"),
exchange2013calendar: import("./exchange2013calendar/api"),
exchange2016calendar: import("./exchange2016calendar/api"),
exchangecalendar: import("./exchangecalendar/api"),
facetime: import("./facetime/api"),
fathom: import("./fathom/api"),
feishucalendar: import("./feishucalendar/api"),
"fonio-ai": import("./fonio-ai/api"),
framer: import("./framer/api"),
ga4: import("./ga4/api"),
giphy: import("./giphy/api"),
googlecalendar: import("./googlecalendar/api"),
googlevideo: import("./googlevideo/api"),
granola: import("./granola/api"),
"greetmate-ai": import("./greetmate-ai/api"),
gtm: import("./gtm/api"),
hitpay: import("./hitpay/api"),
"horizon-workrooms": import("./horizon-workrooms/api"),
@@ -52,28 +39,21 @@ export const apiHandlers = {
jelly: import("./jelly/api"),
jitsivideo: import("./jitsivideo/api"),
larkcalendar: import("./larkcalendar/api"),
lindy: import("./lindy/api"),
linear: import("./linear/api"),
make: import("./make/api"),
matomo: import("./matomo/api"),
metapixel: import("./metapixel/api"),
"millis-ai": import("./millis-ai/api"),
mirotalk: import("./mirotalk/api"),
"mock-payment-app": import("./mock-payment-app/api"),
monobot: import("./monobot/api"),
n8n: import("./n8n/api"),
nextcloudtalk: import("./nextcloudtalk/api"),
office365calendar: import("./office365calendar/api"),
office365video: import("./office365video/api"),
paypal: import("./paypal/api"),
ping: import("./ping/api"),
pipedream: import("./pipedream/api"),
"pipedrive-crm": import("./pipedrive-crm/api"),
plausible: import("./plausible/api"),
posthog: import("./posthog/api"),
qr_code: import("./qr_code/api"),
raycast: import("./raycast/api"),
"retell-ai": import("./retell-ai/api"),
riverside: import("./riverside/api"),
roam: import("./roam/api"),
"routing-forms": import("./routing-forms/api"),
@@ -86,26 +66,21 @@ export const apiHandlers = {
skype: import("./skype/api"),
stripepayment: import("./stripepayment/api"),
sylapsvideo: import("./sylapsvideo/api"),
synthflow: import("./synthflow/api"),
tandemvideo: import("./tandemvideo/api"),
telegram: import("./telegram/api"),
telli: import("./telli/api"),
basic: import("./templates/basic/api"),
"booking-pages-tag": import("./templates/booking-pages-tag/api"),
"event-type-app-card": import("./templates/event-type-app-card/api"),
"event-type-location-video-static": import("./templates/event-type-location-video-static/api"),
"general-app-settings": import("./templates/general-app-settings/api"),
"link-as-an-app": import("./templates/link-as-an-app/api"),
twipla: import("./twipla/api"),
umami: import("./umami/api"),
vimcal: import("./vimcal/api"),
vital: import("./vital/api"),
weather_in_your_calendar: import("./weather_in_your_calendar/api"),
webex: import("./webex/api"),
whatsapp: import("./whatsapp/api"),
whereby: import("./whereby/api"),
wipemycalother: import("./wipemycalother/api"),
wordpress: import("./wordpress/api"),
zapier: import("./zapier/api"),
"zoho-bigin": import("./zoho-bigin/api"),
zohocalendar: import("./zohocalendar/api"),
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://autocheckin.app",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon.svg",
"url": "https://autocheckin.app",
"variant": "automation",
"categories": ["automation"],
"categories": [
"automation"
],
"publisher": "Patrick Goeler von Ravensburg",
"email": "patrickvongoeler@gmail.com",
"description": "You simply paste a [Cal.com](https://cal.com) link of someone, select a frequency and we will take care of the scheduling for you.\r\r",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://autocheckin.app",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/autocheckin",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "You simply paste a Cal.com link of someone, select a frequency and we will take care of the scheduling for you.\r\r"
}
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://cal.com/BAA",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+7 -1
View File
@@ -6,7 +6,9 @@
"logo": "icon.svg",
"url": "https://cal.com/BAA",
"variant": "other",
"categories": ["other"],
"categories": [
"other"
],
"publisher": "Cal.com, Inc.",
"email": "support@cal.com",
"description": "Request a signed Business Associate Agreement for your HIPAA compliance records",
@@ -16,5 +18,9 @@
"paid": {
"priceInUsd": 300,
"mode": "subscription"
},
"externalLink": {
"url": "https://cal.com/BAA",
"newTab": true
}
}
@@ -1 +0,0 @@
export * as api from "./api";
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/baa-for-hipaa",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "Request a signed Business Associate Agreement for your HIPAA compliance records"
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://playground.bolna.dev/auth/calcom",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon-primary.svg",
"url": "https://playground.bolna.dev/auth/calcom",
"variant": "automation",
"categories": ["automation"],
"categories": [
"automation"
],
"publisher": "Bolna",
"email": "founders@bolna.dev",
"description": "24x7 AI receptionists to answer all inbound calls",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://playground.bolna.dev/auth/calcom",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/bolna",
"version": "0.0.1",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "24x7 AI receptionists to answer all inbound calls"
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://www.chatbase.co/guide/cal",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon-dark.svg",
"url": "https://www.chatbase.co/guide/cal",
"variant": "other",
"categories": ["other"],
"categories": [
"other"
],
"publisher": "Chatbase",
"email": "sandra@chatbase.co",
"description": "Add [Cal.com](https://cal.com/) to your Chatbase AI Chatbot and accept bookings right inside chat.",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://www.chatbase.co/guide/cal",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/chatbase",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "Add Cal.com to your Chatbase AI Chatbot and accept bookings right inside chat."
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://clicis.vercel.app",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon.svg",
"url": "https://clicis.vercel.app",
"variant": "automation",
"categories": ["automation"],
"categories": [
"automation"
],
"publisher": "Chris Pacheco",
"email": "chrispacheco430@gmail.com",
"description": "Create, List and Interact with Your Cal.com links and connections easily.\r\r",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://clicis.vercel.app",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/clic",
"version": "0.1.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "Create, List and Interact with Your Cal.com links and connections easily."
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://cron.com",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+11 -3
View File
@@ -6,13 +6,21 @@
"logo": "logo.png",
"url": "https://github.com/miguelnietoa",
"variant": "calendar",
"categories": ["calendar"],
"categories": [
"calendar"
],
"publisher": "Miguel Nieto",
"email": "support@cal.com",
"description": "All of your commitments, now in one place.",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app",
"dependencies": ["google-calendar"],
"isOAuth": false
"dependencies": [
"google-calendar"
],
"isOAuth": false,
"externalLink": {
"url": "https://cron.com",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/cron",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "All of your commitments, now in one place."
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://go.cal.com/deel",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,12 +6,18 @@
"logo": "icon.svg",
"url": "https://go.cal.com/deel",
"variant": "other",
"categories": ["other"],
"categories": [
"other"
],
"publisher": "Deel.com",
"email": "support@deel.com",
"description": "Integrate Deel with your Calendar and get automatic updates on key employee dates like PTO, start days, public holidays, and birthdays. No manual entry. No errors. Just a calendar that's always in sync with your team.",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app",
"dirName": "deel"
"dirName": "deel",
"externalLink": {
"url": "https://go.cal.com/deel",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/deel",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "Integrate Deel with your Calendar and get automatic updates on key employee dates like PTO, start days, public holidays, and birthdays. No manual entry. No errors. Just a calendar that's always in sync with your team."
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://elevenlabs.io/docs/conversational-ai/guides/integrations/cal-com",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon-dark.svg",
"url": "https://elevenlabs.io/docs/conversational-ai/guides/integrations/cal-com",
"variant": "automation",
"categories": ["automation"],
"categories": [
"automation"
],
"publisher": "ElevenLabs",
"email": "support@elevenlabs.io",
"description": "Create the most realistic speech with our AI audio platform",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://elevenlabs.io/docs/conversational-ai/guides/integrations/cal-com",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/elevenlabs",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "Create the most realistic speech with our AI audio platform"
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://docs.fonio.ai/Tools/Terminbuchung",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon.png",
"url": "https://docs.fonio.ai/Tools/Terminbuchung",
"variant": "automation",
"categories": ["automation"],
"categories": [
"automation"
],
"publisher": "fonio GmbH",
"email": "info@fonio.ai",
"description": "Der KI-Telefonassistent auf Deutsch\r",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://docs.fonio.ai/Tools/Terminbuchung",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/fonio-ai",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "*"
},
"devDependencies": {
"@calcom/types": "*"
},
"description": "Der KI-Telefonassistent auf Deutsch\r"
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://www.framer.com/updates/cal-com",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon-dark.svg",
"url": "https://www.framer.com/updates/cal-com",
"variant": "other",
"categories": ["other"],
"categories": [
"other"
],
"publisher": "Framer B.V.",
"email": "benjamin@framer.com",
"description": "Add Cal.com to Framer, the design tool for websites. Design freely, publish fast, and scale with CMS, SEO, analytics, and more.",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://www.framer.com/updates/cal-com",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/framer",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "Add Cal.com to Framer, the design tool for websites. Design freely, publish fast, and scale with CMS, SEO, analytics, and more.\r\r\r\r"
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://go.cal.com/granola",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon.svg",
"url": "https://go.cal.com/granola",
"variant": "other",
"categories": ["other"],
"categories": [
"other"
],
"publisher": "Granola inc",
"email": "hey@granola.so",
"description": "The AI notepad for people in back-to-back meetings for MacOS",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://go.cal.com/granola",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/granola",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "The AI notepad for people in back-to-back meetings for MacOS"
}
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://www.greetmate.com/dashboard",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon-dark.svg",
"url": "https://www.greetmate.ai",
"variant": "automation",
"categories": ["automation"],
"categories": [
"automation"
],
"publisher": "Greetmate Inc.",
"email": "support@greetmate.ai",
"description": "Connect [Cal.com](https://cal.com/) to [Greetmate.ai](https://www.greetmate.ai/) and enable appointment scheduling for your AI agents.",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://www.greetmate.com/dashboard",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/greetmate-ai",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "Connect Cal.com to Greetmate.ai and enable appointment scheduling for your AI agents."
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://www.lindy.ai/integrations/cal-com",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon-dark.svg",
"url": "https://www.lindy.ai/integrations/cal-com",
"variant": "automation",
"categories": ["automation"],
"categories": [
"automation"
],
"publisher": "Lindy",
"email": "flo@lindy.ai",
"description": "Build AI agents in minutes to automate workflows, save time and grow your business",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://www.lindy.ai/integrations/cal-com",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/lindy",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "Build AI agents in minutes to automate workflows, save time and grow your business"
}
+5 -1
View File
@@ -13,5 +13,9 @@
"isTemplate": false,
"__createdUsingCli": true,
"dependencies": ["google-calendar"],
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://linear.app/settings/integrations/google-calendar",
"newTab": true
}
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://www.millis.ai/integrations/cal-com",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon.png",
"url": "https://docs.millis.ai/tutorials/create-voice-agent-for-appointment-scheduling",
"variant": "automation",
"categories": ["automation"],
"categories": [
"automation"
],
"publisher": "Millis AI",
"email": "thach@millis.ai",
"description": "Build next-gen voice agents with 500ms latency\r",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://www.millis.ai/integrations/cal-com",
"newTab": true
}
}
-1
View File
@@ -1 +0,0 @@
export * as api from "./api";
-14
View File
@@ -1,14 +0,0 @@
{
"$schema": "https://json.schemastore.org/package.json",
"private": true,
"name": "@calcom/millis-ai",
"version": "0.0.0",
"main": "./index.ts",
"dependencies": {
"@calcom/lib": "workspace:*"
},
"devDependencies": {
"@calcom/types": "workspace:*"
},
"description": "Build next-gen voice agents with 500ms latency\r"
}
-20
View File
@@ -1,20 +0,0 @@
import { createDefaultInstallation } from "@calcom/app-store/_utils/installation";
import type { AppDeclarativeHandler } from "@calcom/types/AppHandler";
import appConfig from "../config.json";
const handler: AppDeclarativeHandler = {
appType: appConfig.type,
variant: appConfig.variant,
slug: appConfig.slug,
supportsMultipleInstalls: false,
handlerType: "add",
redirect: {
newTab: true,
url: "https://monobot.ai/?ref=cal.com",
},
createCredential: ({ appType, user, slug, teamId }) =>
createDefaultInstallation({ appType, user: user, slug, key: {}, teamId }),
};
export default handler;
-1
View File
@@ -1 +0,0 @@
export { default as add } from "./add";
Whitespace-only changes.
+8 -2
View File
@@ -6,11 +6,17 @@
"logo": "icon.svg",
"url": "https://monobot.ai/?ref=cal.com",
"variant": "automation",
"categories": ["automation"],
"categories": [
"automation"
],
"publisher": "Monobot CX",
"email": "contact@monobot.ai",
"description": "Crafting your personalized AI-driven assistant is easy and fast.",
"isTemplate": false,
"__createdUsingCli": true,
"__template": "link-as-an-app"
"__template": "link-as-an-app",
"externalLink": {
"url": "https://monobot.ai/?ref=cal.com",
"newTab": true
}
}
Loaded 100 of 159 files, more files were not shown because too many files have changed in this diff. Show more