diff --git a/.optimize-cache.json b/.optimize-cache.json index 3d58927ecd..e6e37078b5 100644 --- a/.optimize-cache.json +++ b/.optimize-cache.json @@ -1135,6 +1135,10 @@ "images/docs/ai/audio-processing-light.png": "29a92249b7f2706307321d5bb96d4d20a7ac41b6b55e61e374608e9941e9a6b9", "images/docs/ai/computer-vision-dark.png": "9802337f7e7464e987c963a4dac750dbf3971765161049c7470e3ba976f15412", "images/docs/ai/computer-vision-light.png": "bb27aef8648b2188bc52e50a27df6f12b7c3c50dbcc9d47a327fe93f23d4a06b", + "images/docs/ai/docs-as-markdown/copy-page-dark.png": "ec3257ec9d3fdef157af6ab58e231507bcb54cd098c24a66b4e7e5ccbcb76748", + "images/docs/ai/docs-as-markdown/copy-page-light.png": "9a445794f70859c4c491312a472c825ae44cb5baf24565cd7955b8f3db7d77a7", + "images/docs/ai/docs-as-markdown/quickstart-dark.png": "501b13e454dfe52d371b023f6a97a9007035d936262e45579451592913911cea", + "images/docs/ai/docs-as-markdown/quickstart-light.png": "b1e0306a50ba1c897a75a5c05fcfda3a3b8b94a10844f2c0716186e9389db5a0", "images/docs/ai/integrations/anyscale/demo.png": "f32f7040d1a818291726c1e3cda33eeacc91ae5a37aa2da1f2dd45cb3f531532", "images/docs/ai/integrations/elevenlabs/demo.png": "6a4eba73a75c80676d7674d939b06ebcef5b99a8227d0b8c4df455777baa1534", "images/docs/ai/integrations/fal-ai/demo.png": "613c2b5dd7ac8290ee22c69578a609e33805aa1843998f752348676fabfa464f", diff --git a/src/lib/components/PromptBanner.svelte b/src/lib/components/PromptBanner.svelte index 1d0b82ca9d..37e19a435a 100644 --- a/src/lib/components/PromptBanner.svelte +++ b/src/lib/components/PromptBanner.svelte @@ -5,14 +5,18 @@ import { Button, Icon } from '$lib/components/ui'; import { Tooltip } from '$lib/components'; import { createDropdownMenu, melt } from '@melt-ui/svelte'; - import { onMount } from 'svelte'; + import { getContext, onMount } from 'svelte'; import { trackEvent } from '$lib/actions/analytics'; import AiPromptIcon from '$lib/components/ui/aiPromptIcon.svelte'; import { browser } from '$app/environment'; - // Only support co-located prompt.md - const routeExists = hasRoutePrompt(); - const prompt = routeExists ? (getRoutePrompt() ?? '') : ''; + // Check co-located prompt.md first, then fall back to prompt frontmatter path + const promptFrontmatter = getContext('prompt_path'); + const routeExists = + hasRoutePrompt() || (promptFrontmatter ? hasRoutePrompt(promptFrontmatter) : false); + const prompt = routeExists + ? (getRoutePrompt() ?? (promptFrontmatter ? getRoutePrompt(promptFrontmatter) : null) ?? '') + : ''; const exists = routeExists; const { copied, copy } = createCopy(prompt); diff --git a/src/markdoc/layouts/Article.svelte b/src/markdoc/layouts/Article.svelte index 3006def0ff..092b5c6cc5 100644 --- a/src/markdoc/layouts/Article.svelte +++ b/src/markdoc/layouts/Article.svelte @@ -30,8 +30,10 @@ export let difficulty: string | undefined = undefined; export let readtime: string | undefined = undefined; export let date: string | undefined = undefined; + export let prompt: string | undefined = undefined; setContext('headings', writable({})); + setContext('prompt_path', prompt); const headings = getContext('headings'); diff --git a/src/markdoc/tags/PromptCodeBlock.svelte b/src/markdoc/tags/PromptCodeBlock.svelte new file mode 100644 index 0000000000..c6d2d4afc3 --- /dev/null +++ b/src/markdoc/tags/PromptCodeBlock.svelte @@ -0,0 +1,70 @@ + + +
+
+
+ {#if badgeValue} +
+
{badgeValue}
+
+ {/if} +
+
+
    +
  • + + {#snippet asChild({ trigger })} + + {/snippet} + {#snippet tooltip()} + {copyText} + {/snippet} + +
  • +
+
+
+
+ + {@html result} +
+
diff --git a/src/markdoc/tags/Prompt_Content.svelte b/src/markdoc/tags/Prompt_Content.svelte new file mode 100644 index 0000000000..3d806b6d49 --- /dev/null +++ b/src/markdoc/tags/Prompt_Content.svelte @@ -0,0 +1,21 @@ + + +{#if promptText} + +{/if} diff --git a/src/markdoc/tags/_Module.svelte b/src/markdoc/tags/_Module.svelte index a7a8022ac1..3fd484edc7 100644 --- a/src/markdoc/tags/_Module.svelte +++ b/src/markdoc/tags/_Module.svelte @@ -23,4 +23,5 @@ export { default as Storage_Image } from './Storage_Image.svelte'; export { default as Video_Card } from './Video_Card.svelte'; export { default as Appwrite_Network_Map } from '../../lib/components/appwrite-network/map.svelte'; + export { default as Prompt_Content } from './Prompt_Content.svelte'; diff --git a/src/partials/mcp-add-ides-tools.md b/src/partials/mcp-add-ides-tools.md index a52adc883c..426936a912 100644 --- a/src/partials/mcp-add-ides-tools.md +++ b/src/partials/mcp-add-ides-tools.md @@ -3,25 +3,25 @@ You can add the MCP server to various AI tools and code editors: {% only_light %} {% cards %} -{% cards_item href="/docs/tooling/mcp/claude-desktop" title="Claude Desktop" image="/images/docs/mcp/logos/claude.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/claude-desktop" title="Claude Desktop" image="/images/docs/mcp/logos/claude.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/claude-code" title="Claude Code" image="/images/docs/mcp/logos/claude.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/claude-code" title="Claude Code" image="/images/docs/mcp/logos/claude.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/cursor" title="Cursor" image="/images/docs/mcp/logos/cursor-ai.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/cursor" title="Cursor" image="/images/docs/mcp/logos/cursor-ai.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/windsurf" title="Windsurf Editor" image="/images/docs/mcp/logos/windsurf.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/windsurf" title="Windsurf Editor" image="/images/docs/mcp/logos/windsurf.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/vscode" title="VS Code" image="/images/docs/mcp/logos/vscode.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/vscode" title="VS Code" image="/images/docs/mcp/logos/vscode.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/opencode" title="OpenCode" image="/images/docs/mcp/logos/opencode.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/opencode" title="OpenCode" image="/images/docs/mcp/logos/opencode.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/antigravity" title="Google Antigravity" image="/images/docs/mcp/logos/google-antigravity.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/antigravity" title="Google Antigravity" image="/images/docs/mcp/logos/google-antigravity.svg" %} {% /cards_item %} {% /cards %} @@ -30,25 +30,25 @@ You can add the MCP server to various AI tools and code editors: {% only_dark %} {% cards %} -{% cards_item href="/docs/tooling/mcp/claude-desktop" title="Claude Desktop" image="/images/docs/mcp/logos/dark/claude.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/claude-desktop" title="Claude Desktop" image="/images/docs/mcp/logos/dark/claude.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/claude-code" title="Claude Code" image="/images/docs/mcp/logos/dark/claude.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/claude-code" title="Claude Code" image="/images/docs/mcp/logos/dark/claude.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/cursor" title="Cursor" image="/images/docs/mcp/logos/dark/cursor-ai.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/cursor" title="Cursor" image="/images/docs/mcp/logos/dark/cursor-ai.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/windsurf" title="Windsurf Editor" image="/images/docs/mcp/logos/dark/windsurf.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/windsurf" title="Windsurf Editor" image="/images/docs/mcp/logos/dark/windsurf.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/vscode" title="VS Code" image="/images/docs/mcp/logos/dark/vscode.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/vscode" title="VS Code" image="/images/docs/mcp/logos/dark/vscode.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/opencode" title="OpenCode" image="/images/docs/mcp/logos/dark/opencode.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/opencode" title="OpenCode" image="/images/docs/mcp/logos/dark/opencode.svg" %} {% /cards_item %} -{% cards_item href="/docs/tooling/mcp/antigravity" title="Google Antigravity" image="/images/docs/mcp/logos/dark/google-antigravity.svg" %} +{% cards_item href="/docs/tooling/ai/ai-dev-tools/antigravity" title="Google Antigravity" image="/images/docs/mcp/logos/dark/google-antigravity.svg" %} {% /cards_item %} {% /cards %} diff --git a/src/redirects.json b/src/redirects.json index d283380d27..96919cc501 100644 --- a/src/redirects.json +++ b/src/redirects.json @@ -771,5 +771,49 @@ { "link": "/docs/products/auth/preferences-storage", "redirect": "/docs/products/auth/preferences" + }, + { + "link": "/docs/tooling/mcp", + "redirect": "/docs/tooling/ai" + }, + { + "link": "/docs/tooling/mcp/cursor", + "redirect": "/docs/tooling/ai/ai-dev-tools/cursor" + }, + { + "link": "/docs/tooling/mcp/vscode", + "redirect": "/docs/tooling/ai/ai-dev-tools/vscode" + }, + { + "link": "/docs/tooling/mcp/windsurf", + "redirect": "/docs/tooling/ai/ai-dev-tools/windsurf" + }, + { + "link": "/docs/tooling/mcp/opencode", + "redirect": "/docs/tooling/ai/ai-dev-tools/opencode" + }, + { + "link": "/docs/tooling/mcp/antigravity", + "redirect": "/docs/tooling/ai/ai-dev-tools/antigravity" + }, + { + "link": "/docs/tooling/mcp/claude-code", + "redirect": "/docs/tooling/ai/ai-dev-tools/claude-code" + }, + { + "link": "/docs/tooling/mcp/claude-desktop", + "redirect": "/docs/tooling/ai/ai-dev-tools/claude-desktop" + }, + { + "link": "/docs/tooling/mcp/api", + "redirect": "/docs/tooling/ai/mcp-servers/api" + }, + { + "link": "/docs/tooling/mcp/docs", + "redirect": "/docs/tooling/ai/mcp-servers/docs" + }, + { + "link": "/docs/tooling/skills", + "redirect": "/docs/tooling/ai/skills" } ] diff --git a/src/routes/docs/Sidebar.svelte b/src/routes/docs/Sidebar.svelte index a643a67de7..1e4e4f71b5 100644 --- a/src/routes/docs/Sidebar.svelte +++ b/src/routes/docs/Sidebar.svelte @@ -124,6 +124,12 @@ { label: 'Tooling', items: [ + { + label: 'AI', + href: '/docs/tooling/ai', + icon: 'icon-sparkles', + isParent: true + }, { label: 'CLI', href: '/docs/tooling/command-line/installation', @@ -140,16 +146,6 @@ href: '/docs/tooling/assistant', icon: 'icon-sparkles' }, - { - label: 'MCP Server', - href: '/docs/tooling/mcp', - icon: 'web-icon-mcp' - }, - { - label: 'Skills', - href: '/docs/tooling/skills', - icon: 'web-icon-skills' - }, { label: 'The Appwriter', href: '/docs/tooling/appwriter', diff --git a/src/routes/docs/quick-starts/android-java/+page.markdoc b/src/routes/docs/quick-starts/android-java/+page.markdoc index 7713ecf88a..c6a6c0df93 100644 --- a/src/routes/docs/quick-starts/android-java/+page.markdoc +++ b/src/routes/docs/quick-starts/android-java/+page.markdoc @@ -134,13 +134,14 @@ public class AppwriteHelper { account.createEmailPasswordSession( email, password, - new CoroutineCallback<>(result -> { - callback.onSuccess(result); - return null; - }, error -> { - callback.onError(error); - return null; - })); + new CoroutineCallback<>((result, error) -> { + if (error != null) { + callback.onError(error); + return; + } + callback.onSuccess(result); + }) + ); } public void register(String email, String password, final AuthCallback>> callback) { @@ -148,24 +149,27 @@ public class AppwriteHelper { ID.unique(), email, password, - new CoroutineCallback<>(result -> { - callback.onSuccess(result); - return null; - }, error -> { + new CoroutineCallback<>((result, error) -> { + if (error != null) { callback.onError(error); - return null; - }) + return; + } + callback.onSuccess(result); + }) ); } public void logout(final AuthCallback callback) { - account.deleteSession("current", new CoroutineCallback<>(result -> { - callback.onSuccess(result); - return null; - }, error -> { - callback.onError(error); - return null; - })); + account.deleteSession( + "current", + new CoroutineCallback<>((result, error) -> { + if (error != null) { + callback.onError(error); + return; + } + callback.onSuccess(result); + }) + ); } } ``` diff --git a/src/routes/docs/quick-starts/android-java/prompt.md b/src/routes/docs/quick-starts/android-java/prompt.md new file mode 100644 index 0000000000..fdbf80c102 --- /dev/null +++ b/src/routes/docs/quick-starts/android-java/prompt.md @@ -0,0 +1,378 @@ +## Add Appwrite auth to a new Android (Java) app with a working login/register/logout UI + +- Never assume project details. Ask the user for **Cloud Region**, **Project ID**, and **package name**. +- Use **Android Studio** as the development environment. +- Ensure the user creates a platform in the Appwrite Console with the correct **package name**. + +## Step 1: Create or use existing Android project + +- If you already have an Android project open in Android Studio, stay in it and use it. +- Otherwise, open Android Studio and click **New Project**. +- Choose a project template (e.g., **Empty Activity**) and click **Next**. +- Enter the app **name** and **package name**, then click **Finish**. + +## Step 2: Create Appwrite project + +- Ask the user to go to the [Appwrite Console](https://cloud.appwrite.io/console). +- If this is their first time, they should create an account and create their first project. +- Under **Add a platform**, add an **Android app** with the app's **name** and **package name** (the `applicationId` from the app-level `build.gradle`). + +## Step 3: Add the Appwrite SDK (ask user for Project ID) + +- Add the following dependency to the app-level `build.gradle` file inside the **dependencies** block: + +```groovy +implementation "io.appwrite:sdk-for-android:8.1.0" +``` + +- Add the OAuth callback activity inside the `` tag in `AndroidManifest.xml` (replace `` with actual project ID): + +```xml + + ... + + ... + + + + + + + + + + + +``` + +## Step 4: Create Appwrite helper class (ask user for Region and Project ID) + +- Ask the user for: + - **Cloud Region** (e.g., `fra`, `nyc`) + - **Project ID** (from Console -> Settings) +- Create file: `AppwriteHelper.java` with the following code (replace ``, ``, and ``): + +```java +package ; + +import android.content.Context; + +import java.util.Map; + +import io.appwrite.Client; +import io.appwrite.ID; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.models.Session; +import io.appwrite.models.User; +import io.appwrite.services.Account; + +public class AppwriteHelper { + private static AppwriteHelper instance; + private Client client; + private Account account; + + private AppwriteHelper(Context context) { + client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") + .setProject(""); + + account = new Account(client); + } + + public static synchronized AppwriteHelper getInstance(Context context) { + if (instance == null) { + instance = new AppwriteHelper(context.getApplicationContext()); + } + return instance; + } + + public interface AuthCallback { + void onSuccess(T result); + void onError(Exception error); + } + + public void login(String email, String password, final AuthCallback callback) { + account.createEmailPasswordSession( + email, + password, + new CoroutineCallback<>((result, error) -> { + if (error != null) { + callback.onError(new Exception(error)); + return; + } + callback.onSuccess(result); + }) + ); + } + + public void register(String email, String password, final AuthCallback>> callback) { + account.create( + ID.unique(), + email, + password, + new CoroutineCallback<>((result, error) -> { + if (error != null) { + callback.onError(new Exception(error)); + return; + } + callback.onSuccess(result); + }) + ); + } + + public void logout(final AuthCallback callback) { + account.deleteSession( + "current", + new CoroutineCallback<>((result, error) -> { + if (error != null) { + callback.onError(new Exception(error)); + return; + } + callback.onSuccess(result); + }) + ); + } +} +``` + +## Step 5: Create login UI in XML + +- Update `activity_main.xml` layout file: + +```xml + + + + + +