diff --git a/.env.example b/.env.example index 5f948ba787..7c8efb9f9a 100644 --- a/.env.example +++ b/.env.example @@ -7,6 +7,7 @@ PUBLIC_APPWRITE_PROJECT_ID= PUBLIC_APPWRITE_DASHBOARD=https://cloud.appwrite.io PUBLIC_APPWRITE_PROJECT_INIT_ID= PUBLIC_GROWTH_ENDPOINT= +PUBLIC_ARENA_ENDPOINT=https://arena.appwrite.network PUBLIC_POSTHOG_API_KEY= APPWRITE_DB_INIT_ID= APPWRITE_COL_INIT_ID= diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index a92c29c19d..5a708156a3 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -41,6 +41,7 @@ jobs: "PUBLIC_APPWRITE_FN_TLDR_ID=${{ vars.PUBLIC_APPWRITE_FN_TLDR_ID }}" "PUBLIC_APPWRITE_PROJECT_INIT_ID=${{ vars.PUBLIC_APPWRITE_PROJECT_INIT_ID }}" "PUBLIC_GROWTH_ENDPOINT=${{ vars.PUBLIC_GROWTH_ENDPOINT }}" + "PUBLIC_ARENA_ENDPOINT=${{ vars.PUBLIC_ARENA_ENDPOINT }}" "PUBLIC_POSTHOG_API_KEY=${{ vars.PUBLIC_POSTHOG_API_KEY }}" "APPWRITE_DB_INIT_ID=${{ secrets.APPWRITE_DB_INIT_ID }}" "APPWRITE_COL_INIT_ID=${{ secrets.APPWRITE_COL_INIT_ID }}" diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index 17fd24a773..f371bd4bab 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -42,6 +42,7 @@ jobs: "PUBLIC_APPWRITE_FN_TLDR_ID=${{ vars.PUBLIC_APPWRITE_FN_TLDR_ID }}" "PUBLIC_APPWRITE_PROJECT_INIT_ID=${{ vars.PUBLIC_APPWRITE_PROJECT_INIT_ID }}" "PUBLIC_GROWTH_ENDPOINT=${{ vars.PUBLIC_GROWTH_ENDPOINT }}" + "PUBLIC_ARENA_ENDPOINT=${{ vars.PUBLIC_ARENA_ENDPOINT }}" "PUBLIC_POSTHOG_API_KEY=${{ vars.PUBLIC_POSTHOG_API_KEY }}" "APPWRITE_DB_INIT_ID=${{ secrets.APPWRITE_DB_INIT_ID }}" "APPWRITE_COL_INIT_ID=${{ secrets.APPWRITE_COL_INIT_ID }}" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 27ac7b4c77..e8a9cb5b54 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -27,6 +27,7 @@ jobs: PUBLIC_APPWRITE_FN_TLDR_ID: ${{ vars.PUBLIC_APPWRITE_FN_TLDR_ID }} PUBLIC_APPWRITE_PROJECT_INIT_ID: ${{ vars.PUBLIC_APPWRITE_PROJECT_INIT_ID }} PUBLIC_GROWTH_ENDPOINT: ${{ vars.PUBLIC_GROWTH_ENDPOINT }} + PUBLIC_ARENA_ENDPOINT: ${{ vars.PUBLIC_ARENA_ENDPOINT }} PUBLIC_POSTHOG_API_KEY: ${{ vars.PUBLIC_POSTHOG_API_KEY }} APPWRITE_DB_INIT_ID: ${{ secrets.APPWRITE_DB_INIT_ID }} APPWRITE_COL_INIT_ID: ${{ secrets.APPWRITE_COL_INIT_ID }} @@ -70,6 +71,7 @@ jobs: PUBLIC_APPWRITE_FN_TLDR_ID: ${{ vars.PUBLIC_APPWRITE_FN_TLDR_ID }} PUBLIC_APPWRITE_PROJECT_INIT_ID: ${{ vars.PUBLIC_APPWRITE_PROJECT_INIT_ID }} PUBLIC_GROWTH_ENDPOINT: ${{ vars.PUBLIC_GROWTH_ENDPOINT }} + PUBLIC_ARENA_ENDPOINT: ${{ vars.PUBLIC_ARENA_ENDPOINT }} PUBLIC_POSTHOG_API_KEY: ${{ vars.PUBLIC_POSTHOG_API_KEY }} APPWRITE_DB_INIT_ID: ${{ secrets.APPWRITE_DB_INIT_ID }} APPWRITE_COL_INIT_ID: ${{ secrets.APPWRITE_COL_INIT_ID }} @@ -99,6 +101,7 @@ jobs: PUBLIC_APPWRITE_FN_TLDR_ID: ${{ vars.PUBLIC_APPWRITE_FN_TLDR_ID }} PUBLIC_APPWRITE_PROJECT_INIT_ID: ${{ vars.PUBLIC_APPWRITE_PROJECT_INIT_ID }} PUBLIC_GROWTH_ENDPOINT: ${{ vars.PUBLIC_GROWTH_ENDPOINT }} + PUBLIC_ARENA_ENDPOINT: ${{ vars.PUBLIC_ARENA_ENDPOINT }} PUBLIC_POSTHOG_API_KEY: ${{ vars.PUBLIC_POSTHOG_API_KEY }} APPWRITE_DB_INIT_ID: ${{ secrets.APPWRITE_DB_INIT_ID }} APPWRITE_COL_INIT_ID: ${{ secrets.APPWRITE_COL_INIT_ID }} diff --git a/Dockerfile b/Dockerfile index 2745ec5218..0d45ba6019 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,6 +27,9 @@ ENV PUBLIC_APPWRITE_PROJECT_INIT_ID ${PUBLIC_APPWRITE_PROJECT_INIT_ID} ARG PUBLIC_GROWTH_ENDPOINT ENV PUBLIC_GROWTH_ENDPOINT ${PUBLIC_GROWTH_ENDPOINT} +ARG PUBLIC_ARENA_ENDPOINT +ENV PUBLIC_ARENA_ENDPOINT ${PUBLIC_ARENA_ENDPOINT} + ARG PUBLIC_POSTHOG_API_KEY ENV PUBLIC_POSTHOG_API_KEY ${PUBLIC_POSTHOG_API_KEY} diff --git a/src/hooks.server.ts b/src/hooks.server.ts index f3aa1f67b8..20817cfa39 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -108,6 +108,7 @@ const securityheaders: Handle = async ({ event, resolve }) => { "'self'", 'https://*.appwrite.io', 'https://*.appwrite.org', + 'https://*.appwrite.network', 'https://*.posthog.com', 'https://*.sentry.io', 'https://*.plausible.io', diff --git a/src/lib/system.ts b/src/lib/system.ts index d0ecd55fb8..537a0dbc28 100644 --- a/src/lib/system.ts +++ b/src/lib/system.ts @@ -1,8 +1,9 @@ import { dev } from '$app/environment'; -import { PUBLIC_GROWTH_ENDPOINT } from '$env/static/public'; +import { PUBLIC_GROWTH_ENDPOINT, PUBLIC_ARENA_ENDPOINT } from '$env/static/public'; export const VARS = { - GROWTH_ENDPOINT: PUBLIC_GROWTH_ENDPOINT ?? undefined + GROWTH_ENDPOINT: PUBLIC_GROWTH_ENDPOINT ?? undefined, + ARENA_ENDPOINT: PUBLIC_ARENA_ENDPOINT ?? undefined }; export const ENV = { diff --git a/src/routes/(marketing)/(components)/(ai-animations)/mcp.svelte b/src/routes/(marketing)/(components)/(ai-animations)/mcp.svelte new file mode 100644 index 0000000000..9ff54dbe85 --- /dev/null +++ b/src/routes/(marketing)/(components)/(ai-animations)/mcp.svelte @@ -0,0 +1,189 @@ + + +
+ +
+ +
+ {#each Array(3) as _} +
+ {/each} +
+ + +
+ +
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ + +
+ {#each codeLines as line} +
+ {#if line.w !== '0'} +
+ {:else} +
+ {/if} +
+ {/each} +
+ + +
+ + Create a collection for user profiles + + +
+
+ Setting up collection with email and name attributes. +
+ + +
+ {#if typedText}{typedText}{:else}Ask anything...{/if} +
+ + + +
+
+
+
+
+ + +
diff --git a/src/routes/(marketing)/(components)/(ai-animations)/skills.svelte b/src/routes/(marketing)/(components)/(ai-animations)/skills.svelte new file mode 100644 index 0000000000..0b125c5da7 --- /dev/null +++ b/src/routes/(marketing)/(components)/(ai-animations)/skills.svelte @@ -0,0 +1,179 @@ + + +
+
+ +
+ + + + + {#if typedText}{typedText}{:else}Ask anything...{/if} +
+ + +
+ {#each skills as skill} + {@const focused = skill === focusedSkill} + {#if focused} +
+
+ {skill} + + {#if complete} + + + + {/if} +
+
+
+ {:else} +
+
+ {skill} +
+
+
+ {/if} + {/each} +
+
+ + +
diff --git a/src/routes/(marketing)/(components)/ai-table.svelte b/src/routes/(marketing)/(components)/ai-table.svelte new file mode 100644 index 0000000000..91b084aef7 --- /dev/null +++ b/src/routes/(marketing)/(components)/ai-table.svelte @@ -0,0 +1,262 @@ + + + +
+ +
+

+ Works with every major LLM. + Find out how well your model integrates with Appwrite. +

+
+ + +
+
+ + +
+ + + + + + + {#each categoryKeys as cat} + + {/each} + + + + {#each models as model, i (model.name)} + {@const isLast = i === models.length - 1} + + + + + {#each categoryKeys as cat} + + {/each} + + {/each} + +
ModelOverall
+
+ + {model.name} +
+
+ {animatedScores[i].toFixed(1)}% +
+
+
diff --git a/src/routes/(marketing)/(components)/ai.svelte b/src/routes/(marketing)/(components)/ai.svelte new file mode 100644 index 0000000000..950fa2c69e --- /dev/null +++ b/src/routes/(marketing)/(components)/ai.svelte @@ -0,0 +1,176 @@ + + +
+
+

+ Streamline your AI workflows_ +

+ +
+ +
+ +
+

+ MCP - Connect AI agents to your Appwrite backend. + No custom integrations required. +

+
+
+ + +
+ +
+

+ Skills - Teach AI agents your backend, + so they always make the right call. +

+
+
+
+
+ + +
+
+ + + + +
+
+ {#each tools as tool, i} + + {/each} +
+
+
+
+ + + +
diff --git a/src/routes/(marketing)/+page.svelte b/src/routes/(marketing)/+page.svelte index b1d644a84b..c825703f23 100644 --- a/src/routes/(marketing)/+page.svelte +++ b/src/routes/(marketing)/+page.svelte @@ -12,6 +12,7 @@ import Pullquote from '$lib/components/marketing/pullquote.svelte'; import { FooterNav, MainFooter } from '$lib/components'; import LogoList from './(components)/logo-list.svelte'; + import Ai from './(components)/ai.svelte'; @@ -32,6 +33,7 @@ Just like a Swiss Army Knife you can choose and use the tools that you need with Appwrite. +
diff --git a/src/routes/api/arena/+server.ts b/src/routes/api/arena/+server.ts new file mode 100644 index 0000000000..bfc2bebfb6 --- /dev/null +++ b/src/routes/api/arena/+server.ts @@ -0,0 +1,20 @@ +import { json } from '@sveltejs/kit'; +import { VARS } from '$lib/system'; + +export async function GET() { + try { + const url = `${VARS.ARENA_ENDPOINT || 'https://arena.appwrite.network'}/api/summary/with-skills.json`; + const res = await fetch(url); + + if (!res.ok) { + throw new Error(`Arena API responded with status ${res.status}`); + } + + const data = await res.json(); + return json(data); + } catch (e) { + console.error('Failed to fetch arena data on server:', e); + // Default to returning an empty wrapper so the client can fail gracefully + return json({ models: [] }, { status: 500 }); + } +} diff --git a/src/routes/threads/data.json/+server.ts b/src/routes/threads/data.json/+server.ts index ab03e8a723..7307729981 100644 --- a/src/routes/threads/data.json/+server.ts +++ b/src/routes/threads/data.json/+server.ts @@ -1,12 +1,12 @@ import { json } from '@sveltejs/kit'; import type { RequestHandler } from './$types'; -import { PUBLIC_APPWRITE_ENDPOINT } from '$env/static/public'; +import { PUBLIC_APPWRITE_ENDPOINT, PUBLIC_APPWRITE_PROJECT_ID } from '$env/static/public'; import { iterateAllThreads } from '../helpers'; /* short-circuit for build runs on CI from external contributors */ function shouldSkipThreadsPrerender(): boolean { const endpoint = PUBLIC_APPWRITE_ENDPOINT; - return !endpoint || endpoint.includes('appwrite.test'); + return !endpoint || !PUBLIC_APPWRITE_PROJECT_ID || endpoint.includes('appwrite.test'); } export const prerender = true; diff --git a/static/images/docs/mcp/logos/color/claude.svg b/static/images/docs/mcp/logos/color/claude.svg new file mode 100644 index 0000000000..ee4e2b11e2 --- /dev/null +++ b/static/images/docs/mcp/logos/color/claude.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/images/docs/mcp/logos/color/gemini.svg b/static/images/docs/mcp/logos/color/gemini.svg new file mode 100644 index 0000000000..fd7d65bc2c --- /dev/null +++ b/static/images/docs/mcp/logos/color/gemini.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/static/images/docs/mcp/logos/color/kimi.svg b/static/images/docs/mcp/logos/color/kimi.svg new file mode 100644 index 0000000000..77a23ad054 --- /dev/null +++ b/static/images/docs/mcp/logos/color/kimi.svg @@ -0,0 +1,4 @@ + + + + diff --git a/static/images/docs/mcp/logos/color/openai.svg b/static/images/docs/mcp/logos/color/openai.svg new file mode 100644 index 0000000000..5128622dd5 --- /dev/null +++ b/static/images/docs/mcp/logos/color/openai.svg @@ -0,0 +1,3 @@ + + + diff --git a/static/images/docs/mcp/logos/dark/gemini.svg b/static/images/docs/mcp/logos/dark/gemini.svg new file mode 100644 index 0000000000..eb5161b2c2 --- /dev/null +++ b/static/images/docs/mcp/logos/dark/gemini.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/static/images/docs/mcp/logos/dark/kimi.svg b/static/images/docs/mcp/logos/dark/kimi.svg new file mode 100644 index 0000000000..9dd3f3fa10 --- /dev/null +++ b/static/images/docs/mcp/logos/dark/kimi.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/static/images/docs/mcp/logos/dark/opencode.svg b/static/images/docs/mcp/logos/dark/opencode.svg index 241ee076df..e9283459a9 100644 --- a/static/images/docs/mcp/logos/dark/opencode.svg +++ b/static/images/docs/mcp/logos/dark/opencode.svg @@ -1,4 +1,3 @@ - - + \ No newline at end of file